// Copyright 2014 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.devtools.build.lib.util;

import com.google.common.base.Joiner;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.common.options.Converter;
import com.google.devtools.common.options.OptionsParsingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import javax.annotation.Nullable;

/**
 * Handles options that specify list of included/excluded regex expressions. Validates whether
 * string is included in that filter.
 *
 * <p>String is considered to be included into the filter if it does not match any of the excluded
 * regex expressions and if it matches at least one included regex expression.
 */
@Immutable
public final class RegexFilter implements Predicate<String> {
  // Null inclusion or exclusion pattern means those patterns are not used.
  @Nullable private final Pattern inclusionPattern;
  @Nullable private final Pattern exclusionPattern;
  private final int hashCode;

  /**
   * Converts from a comma-separated list of regex expressions with optional -/+ prefix into the
   * RegexFilter. Commas prefixed with backslash are considered to be part of regex definition and
   * not a delimiter between separate regex expressions.
   *
   * <p>Order of expressions is not important. Empty entries are ignored. '-' marks an excluded
   * expression.
   */
  public static class RegexFilterConverter implements Converter<RegexFilter> {

    @Override
    public RegexFilter convert(String input) throws OptionsParsingException {
      List<String> inclusionList = new ArrayList<>();
      List<String> exclusionList = new ArrayList<>();

      for (String piece : input.split("(?<!\\\\),")) { // Split on ',' but not on '\,'
        piece = piece.replace("\\,", ",");
        boolean isExcluded = piece.startsWith("-");
        if (isExcluded || piece.startsWith("+")) {
          piece = piece.substring(1);
        }
        if (piece.length() > 0) {
          (isExcluded ? exclusionList : inclusionList).add(piece);
        }
      }

      try {
        return new RegexFilter(inclusionList, exclusionList);
      } catch (PatternSyntaxException e) {
        throw new OptionsParsingException("Failed to build valid regular expression: "
            + e.getMessage());
      }
    }

    @Override
    public String getTypeDescription() {
      return "a comma-separated list of regex expressions with prefix '-' specifying"
          + " excluded paths";
    }
  }

  /**
   * Constructor taking regexes directly.
   *
   * <p>Null {@code inclusionPattern} or {@code exclusionPattern} means that inclusion or exclusion
   * matching will not be applied, respectively.
   */
  private RegexFilter(@Nullable Pattern inclusionPattern, @Nullable Pattern exclusionPattern) {
    this.inclusionPattern = inclusionPattern;
    this.exclusionPattern = exclusionPattern;
    this.hashCode =
        Objects.hash(
            inclusionPattern == null ? null : inclusionPattern.pattern(),
            exclusionPattern == null ? null : exclusionPattern.pattern());
  }

  /** Creates new RegexFilter using provided inclusion and exclusion path lists. */
  public RegexFilter(List<String> inclusions, List<String> exclusions) {
    this(takeUnionOfRegexes(inclusions), takeUnionOfRegexes(exclusions));
  }

  /**
   * Converts a list of regex expressions into a single regex representing its union or null when
   * the list is empty.
   */
  private static Pattern takeUnionOfRegexes(List<String> regexList) {
    if (regexList.isEmpty()) {
      return null;
    }
    // Wraps each individual regex into an independent group, then combines them using '|' and
    // wraps the result in a non-capturing group.
    return Pattern.compile("(?:(?>" + Joiner.on(")|(?>").join(regexList) + "))");
  }

  /**
   * @return true iff given string is included (it does not match exclusion pattern (if any) and
   *     matches inclusionPatter (if any)).
   */
  public boolean isIncluded(String value) {
    if (exclusionPattern != null && exclusionPattern.matcher(value).find()) {
      return false;
    }
    if (inclusionPattern == null) {
      return true;
    }
    return inclusionPattern.matcher(value).find();
  }

  @Override
  public boolean test(String value) {
    return isIncluded(value);
  }

  @Nullable
  public String getInclusionRegex() {
    return inclusionPattern == null ? null : inclusionPattern.pattern();
  }

  @Nullable
  public String getExclusionRegex() {
    return exclusionPattern == null ? null : exclusionPattern.pattern();
  }

  @Override
  public String toString() {
    StringBuilder builder = new StringBuilder();
    if (inclusionPattern != null) {
      builder.append(inclusionPattern.pattern().replace(",", "\\,"));
      if (exclusionPattern != null) {
        builder.append(",");
      }
    }
    if (exclusionPattern != null) {
      builder.append("-");
      builder.append(exclusionPattern.pattern().replace(",", "\\,"));
    }
    return builder.toString();
  }

  @Override
  public boolean equals(Object other) {
    if (this == other) {
      return true;
    }
    if (!(other instanceof RegexFilter)) {
      return false;
    }

    RegexFilter otherFilter = (RegexFilter) other;
    if (this.exclusionPattern == null ^ otherFilter.exclusionPattern == null) {
      return false;
    }
    if (this.inclusionPattern == null ^ otherFilter.inclusionPattern == null) {
      return false;
    }
    if (this.exclusionPattern != null && !this.exclusionPattern.pattern().equals(
        otherFilter.exclusionPattern.pattern())) {
      return false;
    }
    if (this.inclusionPattern != null && !this.inclusionPattern.pattern().equals(
        otherFilter.inclusionPattern.pattern())) {
      return false;
    }
    return true;
  }

  @Override
  public int hashCode() {
    return hashCode;
  }
}
