// Copyright (C) 2019 The Android Open Source Project
//
// 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.gerrit.plugins.checks;

import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.gerrit.index.query.QueryParser.AND;
import static com.google.gerrit.index.query.QueryParser.DEFAULT_FIELD;
import static com.google.gerrit.index.query.QueryParser.FIELD_NAME;
import static com.google.gerrit.index.query.QueryParser.NOT;
import static com.google.gerrit.index.query.QueryParser.OR;
import static java.util.Objects.requireNonNull;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Project;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.index.query.IndexPredicate;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.index.query.QueryParser;
import com.google.gerrit.server.AnonymousUser;
import com.google.gerrit.server.index.change.ChangeField;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
import com.google.gerrit.server.query.change.ChangeQueryProcessor;
import com.google.gerrit.server.query.change.ChangeStatusPredicate;
import com.google.gerrit.server.query.change.ProjectPredicate;
import com.google.gerrit.server.update.RetryHelper;
import com.google.gerrit.server.update.RetryHelper.ActionType;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import org.antlr.runtime.tree.Tree;
import org.eclipse.jgit.errors.ConfigInvalidException;

/**
 * Utility for validating and executing relevancy queries for checkers.
 *
 * <p>Instances are not threadsafe and should not be reused across requests. However, they may be
 * reused within a single request.
 */
public class CheckerQuery {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  // Note that this list contains *operators*, not predicates. If there are multiple operators
  // aliased together to the same predicate ("f:", "file:"), they all need to be listed explicitly.
  //
  // We chose to list operators instead of predicates because:
  //  * It insulates us from changes in implementation details of the query system, such as
  //    predicate classes being renamed, or additional predicates being ORed into existing
  //    operators.
  //  * It's easier to keep in sync with the documentation.
  //
  // This doesn't rule out switching to predicates in the future, particularly if the predicate
  // classes gain some informative methods like "boolean matchMethodNeedsToQueryIndex()".
  //
  // Predicates that definitely cannot be allowed:
  //  * Anything where match() needs to query the index, i.e. any full-text fields. This includes
  //    the default field.
  //  * Anything where post-filtering is unreasonably expensive.
  //  * Any predicate over projects, since that may conflict with the projects field.
  //
  // Beyond that, this set is mostly based on what we subjectively consider useful for limiting the
  // changes that a checker runs on. It will probably grow, based on user feedback.
  private static final ImmutableSortedSet<String> ALLOWED_OPERATORS =
      ImmutableSortedSet.of(
          "added",
          "after",
          "age",
          "assignee",
          "author",
          "before",
          "branch",
          "committer",
          "deleted",
          "delta",
          "destination",
          "dir",
          "directory",
          "ext",
          "extension",
          "f",
          "file",
          "footer",
          "hashtag",
          "intopic",
          // TODO(dborowitz): Support some is: operators but not others. Definitely not is:starred.
          "label",
          "onlyextensions",
          "onlyexts",
          "ownerin",
          "path",
          "r",
          "ref",
          "reviewer",
          "reviewerin",
          "size",
          "status",
          "submittable",
          "topic",
          "unresolved",
          "wip");

  @VisibleForTesting
  public static String clean(String query) throws ConfigInvalidException {
    String trimmed = requireNonNull(query).trim();
    if (trimmed.isEmpty()) {
      return trimmed;
    }
    try {
      checkOperators(QueryParser.parse(query));
    } catch (QueryParseException e) {
      throw new ConfigInvalidException("Invalid query: " + query + "\n" + e.getMessage(), e);
    }

    return trimmed;
  }

  private static void checkOperators(Tree node) throws ConfigInvalidException {
    switch (node.getType()) {
      case AND:
      case OR:
      case NOT:
        for (int i = 0; i < node.getChildCount(); i++) {
          checkOperators(node.getChild(i));
        }
        break;

      case FIELD_NAME:
        if (!ALLOWED_OPERATORS.contains(node.getText())) {
          throw new ConfigInvalidException("Unsupported operator: " + node);
        }
        break;

      case DEFAULT_FIELD:
        throw new ConfigInvalidException(
            "Specific search operator required: " + getOnlyChild(node));

      default:
        throw new ConfigInvalidException("Unsupported query: " + node);
    }
  }

  private static Tree getOnlyChild(Tree node) {
    checkState(node.getChildCount() == 1, "expected 1 child: %s", node);
    return node.getChild(0);
  }

  private final RetryHelper retryHelper;
  private final Provider<ChangeQueryProcessor> changeQueryProcessorProvider;
  private final ChangeQueryBuilder queryBuilder;

  @Inject
  CheckerQuery(
      RetryHelper retryHelper,
      Provider<AnonymousUser> anonymousUserProvider,
      Provider<ChangeQueryBuilder> queryBuilderProvider,
      Provider<ChangeQueryProcessor> changeQueryProcessorProvider) {
    this.retryHelper = retryHelper;
    this.changeQueryProcessorProvider = changeQueryProcessorProvider;
    // The user passed to the ChangeQueryBuilder just controls how it parses "self". Anonymous means
    // "self" is disallowed, which is correct for checker queries, since the results should not
    // depend on the calling user. However, note that results are still filtered by visibility, but
    // visibility is controlled by ChangeQueryProcessor, which always uses the current user and
    // can't be overridden.
    this.queryBuilder = queryBuilderProvider.get().asUser(anonymousUserProvider.get());
  }

  public boolean isCheckerRelevant(Checker checker, ChangeData cd) throws StorageException {
    if (!checker.getQuery().isPresent()) {
      return cd.change().isNew();
    }

    Predicate<ChangeData> predicate;
    try {
      predicate =
          createQueryPredicate(checker.getUuid(), checker.getRepository(), checker.getQuery());
    } catch (ConfigInvalidException e) {
      logger.atWarning().withCause(e).log(
          "skipping invalid query for checker %s", checker.getUuid());
      return false;
    }

    return predicate.asMatchable().match(cd);
  }

  /**
   * Cleans and validates a query string for storage in the checker configuration.
   *
   * <p>The query string is interpreted as a change query. Only a subset of query operators are
   * supported, as listed in the REST API documentation and {@link #ALLOWED_OPERATORS}.
   *
   * <p>In addition to syntactic validation and checking for allowed operators, this method actually
   * performs a query against the index, to ensure it passes any restrictions imposed by the index
   * implementation, such as length limits.
   *
   * @param checkerUuid the checker UUID.
   * @param repository the checker repository.
   * @param query a change query string, either from the checker in storage or a proposed new value
   *     provided by a user.
   * @return the query string, trimmed. May be empty, which indicates all changes match.
   * @throws ConfigInvalidException if the query is not a valid query, or it uses operators outside
   *     of the allowed set.
   */
  public String validate(CheckerUuid checkerUuid, Project.NameKey repository, String query)
      throws ConfigInvalidException, StorageException {
    // This parses the query string twice, which is unavoidable since there is currently no
    // QueryProcessor API which takes an Antlr Tree. That's ok; the parse cost is vastly outweighed
    // by the actual query execution.
    query = clean(query);
    queryMatchingChanges(
        checkerUuid,
        repository,
        Optional.ofNullable(Strings.emptyToNull(query)),
        qp -> qp.setUserProvidedLimit(1));
    return query;
  }

  public ImmutableList<ImmutableList<ChangeData>> queryMatchingChanges(List<Checker> checkers)
      throws ConfigInvalidException {

    try {
      List<Predicate<ChangeData>> predicateList = new ArrayList<>();
      for (Checker checker : checkers) {
        predicateList.add(
            createQueryPredicate(checker.getUuid(), checker.getRepository(), checker.getQuery()));
      }
      return executeIndexQueryWithRetry(qp -> {}, predicateList);
    } catch (QueryParseException e) {
      throw new ConfigInvalidException(
          String.format(
              "A checker in scheme %s has an invalid query (%s)",
              checkers.get(0).getUuid().scheme(), e.getMessage()));
    }
  }

  public ImmutableList<ChangeData> queryMatchingChanges(Checker checker)
      throws ConfigInvalidException, StorageException {
    return queryMatchingChanges(
        checker.getUuid(), checker.getRepository(), checker.getQuery(), qp -> {});
  }

  private ImmutableList<ChangeData> queryMatchingChanges(
      CheckerUuid checkerUuid,
      Project.NameKey repository,
      Optional<String> optionalQuery,
      Consumer<ChangeQueryProcessor> queryProcessorSetup)
      throws ConfigInvalidException, StorageException {
    try {
      return executeIndexQueryWithRetry(
          queryProcessorSetup, createQueryPredicate(checkerUuid, repository, optionalQuery));
    } catch (QueryParseException e) {
      throw invalidQueryException(checkerUuid, optionalQuery, e);
    }
  }

  private Predicate<ChangeData> createQueryPredicate(
      CheckerUuid checkerUuid, Project.NameKey repository, Optional<String> optionalQuery)
      throws ConfigInvalidException {
    Predicate<ChangeData> predicate = new ProjectPredicate(repository.get());

    if (optionalQuery.isPresent()) {
      String query = optionalQuery.get();
      Predicate<ChangeData> predicateForQuery;
      try {
        predicateForQuery = queryBuilder.parse(query);
      } catch (QueryParseException e) {
        throw invalidQueryException(checkerUuid, optionalQuery, e);
      }

      if (!predicateForQuery.isMatchable()) {
        // Assuming nobody modified the query behind Gerrit's back, this is programmer error:
        // CheckerQuery should not be able to produce non-matchable queries.
        logger.atWarning().log(
            "change query of checker %s is not matchable: %s", checkerUuid, optionalQuery.get());
        throw invalidQueryException(checkerUuid, optionalQuery, null);
      }

      predicate = Predicate.and(predicate, predicateForQuery);
    }

    if (!hasStatusPredicate(predicate)) {
      predicate = Predicate.and(ChangeStatusPredicate.open(), predicate);
    }

    return predicate;
  }

  private static boolean hasStatusPredicate(Predicate<ChangeData> predicate) {
    if (predicate instanceof IndexPredicate) {
      return ((IndexPredicate<ChangeData>) predicate)
          .getField()
          .getName()
          .equals(ChangeField.STATUS.getName());
    }
    return predicate.getChildren().stream().anyMatch(CheckerQuery::hasStatusPredicate);
  }

  // TODO(ekempin): Retrying the query should be done by ChangeQueryProcessor.
  private ImmutableList<ChangeData> executeIndexQueryWithRetry(
      Consumer<ChangeQueryProcessor> queryProcessorSetup, Predicate<ChangeData> predicate)
      throws StorageException, QueryParseException {
    return executeIndexQueryWithRetry(queryProcessorSetup, ImmutableList.of(predicate)).get(0);
  }

  private ImmutableList<ImmutableList<ChangeData>> executeIndexQueryWithRetry(
      Consumer<ChangeQueryProcessor> queryProcessorSetup, List<Predicate<ChangeData>> predicateList)
      throws StorageException, QueryParseException {
    try {
      return retryHelper.execute(
          ActionType.INDEX_QUERY,
          () -> {
            ChangeQueryProcessor qp = changeQueryProcessorProvider.get();
            queryProcessorSetup.accept(qp);
            return qp.query(predicateList).stream()
                .map(predicate -> predicate.entities())
                .collect(toImmutableList());
          },
          StorageException.class::isInstance);
    } catch (Exception e) {
      Throwables.throwIfUnchecked(e);
      Throwables.throwIfInstanceOf(e, QueryParseException.class);
      Throwables.throwIfInstanceOf(e, StorageException.class);
      throw new StorageException(e);
    }
  }

  private static ConfigInvalidException invalidQueryException(
      CheckerUuid checkerUuid,
      Optional<String> optionalQuery,
      @Nullable QueryParseException parseException) {
    String msg =
        String.format(
            "change query of checker %s is invalid: %s", checkerUuid, optionalQuery.orElse(""));
    if (parseException != null) {
      msg += " (" + parseException.getMessage() + ")";
    }
    return new ConfigInvalidException(msg, parseException);
  }
}
