// Copyright (C) 2021 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.server.project;

import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static com.google.gerrit.server.project.ProjectCache.illegalState;

import com.google.common.collect.ImmutableMap;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.SubmitRequirement;
import com.google.gerrit.entities.SubmitRequirementExpression;
import com.google.gerrit.entities.SubmitRequirementExpressionResult;
import com.google.gerrit.entities.SubmitRequirementExpressionResult.PredicateResult;
import com.google.gerrit.entities.SubmitRequirementResult;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.server.plugincontext.PluginSetContext;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.SubmitRequirementChangeQueryBuilder;
import com.google.gerrit.server.util.ManualRequestContext;
import com.google.gerrit.server.util.OneOffRequestContext;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Module;
import com.google.inject.Provider;
import com.google.inject.Scopes;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Stream;

/** Evaluates submit requirements for different change data. */
public class SubmitRequirementsEvaluatorImpl implements SubmitRequirementsEvaluator {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private final Provider<SubmitRequirementChangeQueryBuilder> queryBuilder;
  private final ProjectCache projectCache;
  private final PluginSetContext<SubmitRequirement> globalSubmitRequirements;
  private final OneOffRequestContext requestContext;

  public static Module module() {
    return new AbstractModule() {
      @Override
      protected void configure() {
        bind(SubmitRequirementsEvaluator.class)
            .to(SubmitRequirementsEvaluatorImpl.class)
            .in(Scopes.SINGLETON);
      }
    };
  }

  @Inject
  private SubmitRequirementsEvaluatorImpl(
      Provider<SubmitRequirementChangeQueryBuilder> queryBuilder,
      ProjectCache projectCache,
      PluginSetContext<SubmitRequirement> globalSubmitRequirements,
      OneOffRequestContext requestContext) {
    this.queryBuilder = queryBuilder;
    this.projectCache = projectCache;
    this.globalSubmitRequirements = globalSubmitRequirements;
    this.requestContext = requestContext;
  }

  @Override
  public void validateExpression(SubmitRequirementExpression expression)
      throws QueryParseException {
    try (ManualRequestContext ignored = requestContext.open()) {
      queryBuilder.get().parse(expression.expressionString());
    }
  }

  @Override
  public ImmutableMap<SubmitRequirement, SubmitRequirementResult> evaluateAllRequirements(
      ChangeData cd) {
    return getRequirements(cd);
  }

  @Override
  public SubmitRequirementResult evaluateRequirement(SubmitRequirement sr, ChangeData cd) {
    try (ManualRequestContext ignored = requestContext.open()) {
      // Use a request context to execute predicates as an internal user with expanded visibility.
      // This is so that the evaluation does not depend on who is running the current request (e.g.
      // a "ownerin" predicate with group that is not visible to the person making this request).

      Optional<SubmitRequirementExpressionResult> applicabilityResult =
          sr.applicabilityExpression().isPresent()
              ? Optional.of(evaluateExpression(sr.applicabilityExpression().get(), cd))
              : Optional.empty();
      Optional<SubmitRequirementExpressionResult> submittabilityResult =
          Optional.of(
              SubmitRequirementExpressionResult.notEvaluated(sr.submittabilityExpression()));
      Optional<SubmitRequirementExpressionResult> overrideResult =
          sr.overrideExpression().isPresent()
              ? Optional.of(
                  SubmitRequirementExpressionResult.notEvaluated(sr.overrideExpression().get()))
              : Optional.empty();
      if (!sr.applicabilityExpression().isPresent()
          || SubmitRequirementResult.assertPass(applicabilityResult)) {
        submittabilityResult = Optional.of(evaluateExpression(sr.submittabilityExpression(), cd));
        overrideResult =
            sr.overrideExpression().isPresent()
                ? Optional.of(evaluateExpression(sr.overrideExpression().get(), cd))
                : Optional.empty();
      }

      if (applicabilityResult.isPresent()) {
        logger.atFine().log(
            "Applicability expression result for SR name '%s':"
                + " passing atoms: %s, failing atoms: %s",
            sr.name(),
            applicabilityResult.get().passingAtoms(),
            applicabilityResult.get().failingAtoms());
      }
      if (submittabilityResult.isPresent()) {
        logger.atFine().log(
            "Submittability expression result for SR name '%s':"
                + " passing atoms: %s, failing atoms: %s",
            sr.name(),
            submittabilityResult.get().passingAtoms(),
            submittabilityResult.get().failingAtoms());
      }
      if (overrideResult.isPresent()) {
        logger.atFine().log(
            "Override expression result for SR name '%s':"
                + " passing atoms: %s, failing atoms: %s",
            sr.name(), overrideResult.get().passingAtoms(), overrideResult.get().failingAtoms());
      }

      return SubmitRequirementResult.builder()
          .legacy(Optional.of(false))
          .submitRequirement(sr)
          .patchSetCommitId(cd.currentPatchSet().commitId())
          .submittabilityExpressionResult(submittabilityResult)
          .applicabilityExpressionResult(applicabilityResult)
          .overrideExpressionResult(overrideResult)
          .build();
    }
  }

  @Override
  public SubmitRequirementExpressionResult evaluateExpression(
      SubmitRequirementExpression expression, ChangeData changeData) {
    try {
      Predicate<ChangeData> predicate = queryBuilder.get().parse(expression.expressionString());
      PredicateResult predicateResult = evaluatePredicateTree(predicate, changeData);
      return SubmitRequirementExpressionResult.create(expression, predicateResult);
    } catch (QueryParseException | SubmitRequirementEvaluationException e) {
      logger.atWarning().withCause(e).log(
          "Failed to evaluate submit requirement expression: %s", expression.expressionString());
      return SubmitRequirementExpressionResult.error(expression, e.getMessage());
    }
  }

  /**
   * Evaluate and return all {@link SubmitRequirement}s.
   *
   * <p>This includes all globally bound {@link SubmitRequirement}s, as well as requirements stored
   * in this project's config and its parents.
   *
   * <p>The behaviour in case of the name match is controlled by {@link
   * SubmitRequirement#allowOverrideInChildProjects} of global {@link SubmitRequirement}.
   */
  private ImmutableMap<SubmitRequirement, SubmitRequirementResult> getRequirements(ChangeData cd) {
    Map<String, SubmitRequirement> globalRequirements = getGlobalRequirements();

    ProjectState state = projectCache.get(cd.project()).orElseThrow(illegalState(cd.project()));
    Map<String, SubmitRequirement> projectConfigRequirements = state.getSubmitRequirements();

    ImmutableMap<String, SubmitRequirement> requirements =
        Stream.concat(
                globalRequirements.entrySet().stream(),
                projectConfigRequirements.entrySet().stream())
            .collect(
                toImmutableMap(
                    Map.Entry::getKey,
                    Map.Entry::getValue,
                    (globalSubmitRequirement, projectConfigRequirement) ->
                        // Override with projectConfigRequirement if allowed by
                        // globalSubmitRequirement configuration
                        globalSubmitRequirement.allowOverrideInChildProjects()
                            ? projectConfigRequirement
                            : globalSubmitRequirement));
    ImmutableMap.Builder<SubmitRequirement, SubmitRequirementResult> results =
        ImmutableMap.builder();
    for (SubmitRequirement requirement : requirements.values()) {
      results.put(requirement, evaluateRequirement(requirement, cd));
    }
    return results.build();
  }

  /**
   * Returns a map of all global {@link SubmitRequirement}s, keyed by their lower-case name.
   *
   * <p>The global {@link SubmitRequirement}s apply to all projects and can be bound by plugins.
   */
  private Map<String, SubmitRequirement> getGlobalRequirements() {
    return globalSubmitRequirements.stream()
        .collect(
            toImmutableMap(
                globalRequirement -> globalRequirement.name().toLowerCase(Locale.US),
                Function.identity()));
  }

  /** Evaluate the predicate recursively using change data. */
  private PredicateResult evaluatePredicateTree(
      Predicate<ChangeData> predicate, ChangeData changeData) {
    PredicateResult.Builder predicateResult =
        PredicateResult.builder()
            .predicateString(predicate.isLeaf() ? predicate.getPredicateString() : "")
            .status(predicate.asMatchable().match(changeData));
    predicate
        .getChildren()
        .forEach(
            c -> predicateResult.addChildPredicateResult(evaluatePredicateTree(c, changeData)));
    return predicateResult.build();
  }
}
