// 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 com.google.auto.value.AutoValue;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.flogger.FluentLogger;
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.plugins.checks.api.BlockingCondition;
import com.google.gerrit.plugins.checks.api.CheckerStatus;
import com.google.gerrit.reviewdb.client.Project;
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.gwtorm.server.OrmException;
import com.google.inject.Provider;
import java.sql.Timestamp;
import java.util.List;
import java.util.Optional;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.ObjectId;

/** Definition of a checker. */
@AutoValue
public abstract class Checker {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  /**
   * Returns the UUID of the checker.
   *
   * <p>The UUID is unique across all checkers.
   *
   * @return UUID
   */
  public abstract CheckerUuid getUuid();

  /**
   * Returns the display name of the checker.
   *
   * <p>Checkers may not have a name, in this case {@link Optional#empty()} is returned.
   *
   * @return display name of the checker
   */
  public abstract Optional<String> getName();

  /**
   * Returns the description of the checker.
   *
   * <p>Checkers may not have a description, in this case {@link Optional#empty()} is returned.
   *
   * @return the description of the checker
   */
  public abstract Optional<String> getDescription();

  /**
   * Returns the URL of the checker.
   *
   * <p>Checkers may not have a URL, in this case {@link Optional#empty()} is returned.
   *
   * @return the URL of the checker
   */
  public abstract Optional<String> getUrl();

  /**
   * Returns the repository to which the checker applies.
   *
   * <p>The repository is the exact name of a repository (no prefix, no regexp).
   *
   * @return the repository to which the checker applies
   */
  public abstract Project.NameKey getRepository();

  /**
   * Returns the status of the checker.
   *
   * @return the status of the checker.
   */
  public abstract CheckerStatus getStatus();

  /**
   * Returns the blocking conditions for the checker.
   *
   * @return the blocking conditions for the checker.
   */
  public abstract ImmutableSortedSet<BlockingCondition> getBlockingConditions();

  /**
   * Returns the query for the checker.
   *
   * <p>If set, represents a limited change query that all relevant changes will match.
   *
   * @return the query for the checker.
   */
  public abstract Optional<String> getQuery();

  /**
   * Returns the creation timestamp of the checker.
   *
   * @return the creation timestamp
   */
  public abstract Timestamp getCreated();

  /**
   * Returns the timestamp of when the checker was last updated.
   *
   * @return the last updated timestamp
   */
  public abstract Timestamp getUpdated();

  /**
   * Returns the ref state of the checker.
   *
   * @return the ref state
   */
  public abstract ObjectId getRefState();

  public abstract Builder toBuilder();

  public static Builder builder() {
    return new AutoValue_Checker.Builder();
  }

  public boolean isDisabled() {
    return CheckerStatus.DISABLED == getStatus();
  }

  public boolean isCheckerRelevant(ChangeData cd, ChangeQueryBuilder changeQueryBuilder)
      throws OrmException {
    if (!getQuery().isPresent()) {
      return cd.change().isNew();
    }

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

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

  public List<ChangeData> queryMatchingChanges(
      RetryHelper retryHelper,
      ChangeQueryBuilder changeQueryBuilder,
      Provider<ChangeQueryProcessor> changeQueryProcessorProvider)
      throws ConfigInvalidException, OrmException {
    return executeIndexQueryWithRetry(
        retryHelper, changeQueryProcessorProvider, createQueryPredicate(changeQueryBuilder));
  }

  private Predicate<ChangeData> createQueryPredicate(ChangeQueryBuilder changeQueryBuilder)
      throws ConfigInvalidException {
    Predicate<ChangeData> predicate = new ProjectPredicate(getRepository().get());

    if (getQuery().isPresent()) {
      String query = getQuery().get();
      Predicate<ChangeData> predicateForQuery;
      try {
        predicateForQuery = changeQueryBuilder.parse(query);
      } catch (QueryParseException e) {
        throw new ConfigInvalidException(
            String.format("change query of checker %s is invalid: %s", getUuid(), query), 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.
        throw new ConfigInvalidException(
            String.format("change query of checker %s is non-matchable: %s", getUuid(), query));
      }

      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(Checker::hasStatusPredicate);
  }

  // TODO(ekempin): Retrying the query should be done by ChangeQueryProcessor.
  private List<ChangeData> executeIndexQueryWithRetry(
      RetryHelper retryHelper,
      Provider<ChangeQueryProcessor> changeQueryProcessorProvider,
      Predicate<ChangeData> predicate)
      throws OrmException {
    try {
      return retryHelper.execute(
          ActionType.INDEX_QUERY,
          () -> changeQueryProcessorProvider.get().query(predicate).entities(),
          OrmException.class::isInstance);
    } catch (Exception e) {
      Throwables.throwIfUnchecked(e);
      Throwables.throwIfInstanceOf(e, OrmException.class);
      throw new OrmException(e);
    }
  }

  /**
   * Checks whether a {@link Checker} is required for submission or not.
   *
   * @return true if the {@link Checker} required for submission.
   */
  public boolean isRequired() {
    ImmutableSet<BlockingCondition> blockingConditions = getBlockingConditions();
    if (blockingConditions.isEmpty()) {
      return false;
    } else if (blockingConditions.size() > 1
        || !blockingConditions.contains(BlockingCondition.STATE_NOT_PASSING)) {
      // When a new blocking condition is introduced, this needs to be adjusted to respect that.
      String errorMessage = String.format("illegal blocking conditions %s", blockingConditions);
      throw new IllegalStateException(errorMessage);
    }
    return true;
  }

  /** A builder for an {@link Checker}. */
  @AutoValue.Builder
  public abstract static class Builder {
    public abstract Builder setUuid(CheckerUuid uuid);

    public abstract CheckerUuid getUuid();

    public abstract Builder setName(String name);

    public abstract Builder setDescription(String description);

    public abstract Builder setUrl(String url);

    public abstract Builder setRepository(Project.NameKey repository);

    public abstract Builder setStatus(CheckerStatus status);

    public abstract Builder setBlockingConditions(Iterable<BlockingCondition> enumList);

    public abstract Builder setQuery(String query);

    public abstract Builder setCreated(Timestamp created);

    public abstract Builder setUpdated(Timestamp updated);

    public abstract Builder setRefState(ObjectId refState);

    public abstract Checker build();
  }
}
