// 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.api;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.extensions.restapi.TopLevelResource;
import com.google.gerrit.index.query.AndPredicate;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.plugins.checks.Check;
import com.google.gerrit.plugins.checks.CheckKey;
import com.google.gerrit.plugins.checks.Checker;
import com.google.gerrit.plugins.checks.CheckerQuery;
import com.google.gerrit.plugins.checks.CheckerUuid;
import com.google.gerrit.plugins.checks.Checkers;
import com.google.gerrit.plugins.checks.Checks;
import com.google.gerrit.plugins.checks.Checks.GetCheckOptions;
import com.google.gerrit.plugins.checks.index.CheckPredicate;
import com.google.gerrit.plugins.checks.index.CheckQueryBuilder;
import com.google.gerrit.plugins.checks.index.CheckStatePredicate;
import com.google.gerrit.plugins.checks.index.CheckerPredicate;
import com.google.gerrit.plugins.checks.index.CheckerSchemePredicate;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.kohsuke.args4j.Option;

public class QueryPendingChecks implements RestReadView<TopLevelResource> {
  private final CheckQueryBuilder checkQueryBuilder;
  private final Checkers checkers;
  private final Checks checks;
  private final Provider<CheckerQuery> checkerQueryProvider;
  private String queryString;

  @Option(
      name = "--query",
      aliases = {"-q"},
      metaVar = "QUERY",
      usage = "check query")
  public QueryPendingChecks setQuery(String queryString) {
    this.queryString = queryString;
    return this;
  }

  @Inject
  public QueryPendingChecks(
      CheckQueryBuilder checkQueryBuilder,
      Checkers checkers,
      Checks checks,
      Provider<CheckerQuery> checkerQueryProvider) {
    this.checkQueryBuilder = checkQueryBuilder;
    this.checkers = checkers;
    this.checks = checks;
    this.checkerQueryProvider = checkerQueryProvider;
  }

  public List<PendingChecksInfo> apply()
      throws RestApiException, IOException, ConfigInvalidException, StorageException {
    return apply(TopLevelResource.INSTANCE).value();
  }

  @Override
  public Response<List<PendingChecksInfo>> apply(TopLevelResource resource)
      throws RestApiException, IOException, ConfigInvalidException, StorageException {
    if (queryString == null) {
      throw new BadRequestException("query is required");
    }

    Predicate<Check> predicate = validateQuery(parseQuery(queryString));
    if (!hasStatePredicate(predicate)) {
      predicate = Predicate.and(new CheckStatePredicate(CheckState.NOT_STARTED), predicate);
    }
    // this variable is for the lambda expressions when using orElseThrow
    final Predicate<Check> finalPredicate = predicate;

    if (countPredicates(predicate, CheckerPredicate.class) == 1) {
      // Checker query
      Optional<Checker> checker =
          checkers.getChecker(
              getCheckerUuidFromQuery(predicate)
                  .orElseThrow(
                      () ->
                          new IllegalStateException(
                              String.format("no checker predicate found: %s", finalPredicate))));
      if (!checker.isPresent() || checker.get().isDisabled()) {
        return Response.ok(ImmutableList.of());
      }
      List<ChangeData> changes = checkerQueryProvider.get().queryMatchingChanges(checker.get());
      return Response.ok(getPendingChecksOfChecker(checker.get(), predicate, changes));
    }
    // Scheme query
    String scheme =
        getSchemeFromQuery(predicate)
            .orElseThrow(
                () ->
                    new IllegalStateException(
                        String.format("no checker scheme predicate found: %s", finalPredicate)));
    ImmutableList<Checker> checkersOfScheme = checkers.listCheckers(scheme);
    List<List<ChangeData>> changes =
        checkerQueryProvider.get().queryMatchingChanges(checkersOfScheme);
    List<PendingChecksInfo> pendingChecks = new ArrayList<>();
    for (int i = 0; i < changes.size(); i++) {
      pendingChecks.addAll(
          getPendingChecksOfChecker(checkersOfScheme.get(i), predicate, changes.get(i)));
    }
    return Response.ok(pendingChecks);
  }

  private List<PendingChecksInfo> getPendingChecksOfChecker(
      Checker checker, Predicate<Check> query, List<ChangeData> changes) throws IOException {

    // The query system can only match against the current patch set; ignore non-current patch sets
    // for now.
    List<PendingChecksInfo> pendingChecks = new ArrayList<>();
    CheckerUuid checkerUuid = checker.getUuid();
    for (ChangeData cd : changes) {
      PatchSet patchSet = cd.currentPatchSet();
      CheckKey checkKey = CheckKey.create(cd.project(), patchSet.id(), checkerUuid);

      // Backfill if check is not present.
      // Backfilling is only done for relevant checkers (checkers where the repository and the query
      // matches the change). Since the change was found by executing the query of the checker we
      // know that the checker is relevant for this patch set and hence backfilling should be done.
      Check check =
          checks
              .getCheck(checkKey, GetCheckOptions.defaults())
              .orElseGet(() -> Check.newBackfilledCheck(cd.project(), patchSet, checker));

      if (query.asMatchable().match(check)) {
        pendingChecks.add(createPendingChecksInfo(cd.project(), patchSet, checkerUuid, check));
      }
    }
    return pendingChecks;
  }

  private Predicate<Check> parseQuery(String query) throws BadRequestException {
    try {
      return checkQueryBuilder.parse(query.trim());
    } catch (QueryParseException e) {
      throw new BadRequestException(e.getMessage());
    }
  }

  private static Predicate<Check> validateQuery(Predicate<Check> predicate)
      throws BadRequestException {
    int numCheckPredicates = countPredicates(predicate, CheckerPredicate.class);
    int numSchemePredicates = countPredicates(predicate, CheckerSchemePredicate.class);
    String exceptionMessage =
        String.format(
            "query must be '%s:<checker-uuid>' or '%s:<checker-uuid> AND <other-operators>' or '%s:<checker-scheme>' or '%s:<checker-scheme> AND <other-operators>'",
            CheckQueryBuilder.FIELD_CHECKER,
            CheckQueryBuilder.FIELD_CHECKER,
            CheckQueryBuilder.FIELD_SCHEME,
            CheckQueryBuilder.FIELD_SCHEME);
    if (numCheckPredicates + numSchemePredicates != 1) {
      throw new BadRequestException(
          String.format(
              "query must contain exactly 1 '%s' operator or '%s' operator",
              CheckQueryBuilder.FIELD_CHECKER, CheckQueryBuilder.FIELD_SCHEME));
    }

    // the root predicate must either be an AndPredicate ....
    if (predicate instanceof AndPredicate) {
      // if the root predicate is an AndPredicate, any of its direct children must be a
      // CheckerPredicate or CheckerSchemePredicate, the other child predicates can be anything
      // (including any combination of
      // AndPredicate, OrPredicate and NotPredicate).
      if (predicate.getChildren().stream().noneMatch(CheckerPredicate.class::isInstance)
          && predicate.getChildren().stream().noneMatch(CheckerSchemePredicate.class::isInstance)) {
        throw new BadRequestException(exceptionMessage);
      }
      // ... or a CheckerPredicate / CheckerSchemePredicate
    } else if (!(predicate instanceof CheckerPredicate
        || predicate instanceof CheckerSchemePredicate)) {
      throw new BadRequestException(exceptionMessage);
    }
    return predicate;
  }

  private static boolean hasStatePredicate(Predicate<Check> predicate) {
    if (predicate instanceof CheckStatePredicate) {
      return true;
    }
    if (predicate.getChildCount() == 0) {
      return false;
    }
    return predicate.getChildren().stream().anyMatch(QueryPendingChecks::hasStatePredicate);
  }

  /**
   * Counts the number of {@link CheckerPredicate}s in the given predicate.
   *
   * <p>This method doesn't validate that the checker predicates appear in any particular location.
   *
   * @param predicate the predicate in which the checker predicates should be counted
   * @param predicateClass the class of the predicate (schema or checker)
   * @return the number of checker predicates in the given predicate
   */
  private static int countPredicates(
      Predicate<Check> predicate, Class<? extends CheckPredicate> predicateClass) {
    if (predicateClass.isInstance(predicate)) {
      return 1;
    }
    if (predicate.getChildCount() == 0) {
      return 0;
    }
    return predicate.getChildren().stream()
        .mapToInt(p -> QueryPendingChecks.countPredicates(p, predicateClass))
        .sum();
  }

  private static Optional<CheckerUuid> getCheckerUuidFromQuery(Predicate<Check> predicate) {
    // the query validation (see #validateQuery(Predicate<Check>)) ensures that there is exactly 1
    // CheckerPredicate or CheckerSchemePredicate and that it is on the first or second level of the
    // predicate tree.

    if (predicate instanceof CheckerPredicate) {
      return Optional.of(((CheckerPredicate) predicate).getCheckerUuid());
    }

    Optional<CheckerPredicate> checkerPredicate =
        predicate.getChildren().stream()
            .filter(CheckerPredicate.class::isInstance)
            .map(p -> (CheckerPredicate) p)
            .findAny();
    return checkerPredicate.map(CheckerPredicate::getCheckerUuid);
  }

  private static Optional<String> getSchemeFromQuery(Predicate<Check> predicate) {
    // the query validation (see #validateQuery(Predicate<Check>)) ensures that there is exactly 1
    // CheckerPredicate or CheckerSchemePredicate and that it is on the first or second level of the
    // predicate tree.

    if (predicate instanceof CheckerSchemePredicate) {
      return Optional.of(((CheckerSchemePredicate) predicate).getCheckerScheme());
    }

    Optional<CheckerSchemePredicate> checkerSchemePredicate =
        predicate.getChildren().stream()
            .filter(CheckerSchemePredicate.class::isInstance)
            .map(p -> (CheckerSchemePredicate) p)
            .findAny();
    return checkerSchemePredicate.map(CheckerSchemePredicate::getCheckerScheme);
  }

  private static PendingChecksInfo createPendingChecksInfo(
      Project.NameKey repositoryName, PatchSet patchSet, CheckerUuid checkerUuid, Check check) {
    PendingChecksInfo pendingChecksInfo = new PendingChecksInfo();

    pendingChecksInfo.patchSet = new CheckablePatchSetInfo();
    pendingChecksInfo.patchSet.repository = repositoryName.get();
    pendingChecksInfo.patchSet.changeNumber = patchSet.id().changeId().get();
    pendingChecksInfo.patchSet.patchSetId = patchSet.number();

    pendingChecksInfo.pendingChecks =
        ImmutableMap.of(checkerUuid.get(), new PendingCheckInfo(check.state()));

    return pendingChecksInfo;
  }
}
