// 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.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.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 Exception {
    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;
  }
}
