// Copyright (C) 2012 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.ImmutableList.toImmutableList;

import com.google.common.collect.Streams;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.SubmitRecord;
import com.google.gerrit.entities.SubmitTypeRecord;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.api.changes.ChangeApi;
import com.google.gerrit.metrics.Description;
import com.google.gerrit.metrics.Description.Units;
import com.google.gerrit.metrics.MetricMaker;
import com.google.gerrit.metrics.Timer0;
import com.google.gerrit.server.change.ChangeJson;
import com.google.gerrit.server.index.OnlineReindexMode;
import com.google.gerrit.server.logging.CallerFinder;
import com.google.gerrit.server.plugincontext.PluginSetContext;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.rules.DefaultSubmitRule;
import com.google.gerrit.server.rules.PrologRule;
import com.google.gerrit.server.rules.SubmitRule;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.inject.assistedinject.Assisted;
import java.util.List;
import java.util.Optional;

/**
 * Evaluates a submit-like Prolog rule found in the rules.pl file of the current project and filters
 * the results through rules found in the parent projects, all the way up to All-Projects.
 */
public class SubmitRuleEvaluator {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  public interface Factory {
    /** Returns a new {@link SubmitRuleEvaluator} with the specified options */
    SubmitRuleEvaluator create(SubmitRuleOptions options);
  }

  @Singleton
  private static class Metrics {
    final Timer0 submitRuleEvaluationLatency;
    final Timer0 submitTypeEvaluationLatency;

    @Inject
    Metrics(MetricMaker metricMaker) {
      submitRuleEvaluationLatency =
          metricMaker.newTimer(
              "change/submit_rule_evaluation",
              new Description("Latency for evaluating submit rules on a change.")
                  .setCumulative()
                  .setUnit(Units.MILLISECONDS));
      submitTypeEvaluationLatency =
          metricMaker.newTimer(
              "change/submit_type_evaluation",
              new Description("Latency for evaluating the submit type on a change.")
                  .setCumulative()
                  .setUnit(Units.MILLISECONDS));
    }
  }

  private final ProjectCache projectCache;
  private final PrologRule prologRule;
  private final PluginSetContext<SubmitRule> submitRules;
  private final Metrics metrics;
  private final SubmitRuleOptions opts;
  private final CallerFinder callerFinder;

  @Inject
  private SubmitRuleEvaluator(
      ProjectCache projectCache,
      PrologRule prologRule,
      PluginSetContext<SubmitRule> submitRules,
      Metrics metrics,
      @Assisted SubmitRuleOptions options) {
    this.projectCache = projectCache;
    this.prologRule = prologRule;
    this.submitRules = submitRules;
    this.metrics = metrics;

    this.opts = options;

    this.callerFinder =
        CallerFinder.builder()
            .addTarget(ChangeApi.class)
            .addTarget(ChangeJson.class)
            .addTarget(ChangeData.class)
            .addTarget(SubmitRequirementsEvaluatorImpl.class)
            .build();
  }

  /**
   * Evaluate the submit rules.
   *
   * @return List of {@link SubmitRecord} objects returned from the evaluated rules, including any
   *     errors.
   * @param cd ChangeData to evaluate
   */
  public List<SubmitRecord> evaluate(ChangeData cd) {
    logger.atFine().log(
        "Evaluate submit rules for change %d (caller: %s)",
        cd.change().getId().get(), callerFinder.findCallerLazy());
    try (Timer0.Context ignored = metrics.submitRuleEvaluationLatency.start()) {
      Change change;
      ProjectState projectState;
      try {
        change = cd.change();
        if (change == null) {
          throw new StorageException("Change not found");
        }

        Project.NameKey name = cd.project();
        Optional<ProjectState> projectStateOptional = projectCache.get(name);
        if (!projectStateOptional.isPresent()) {
          throw new NoSuchProjectException(name);
        }
        projectState = projectStateOptional.get();
      } catch (NoSuchProjectException e) {
        throw new IllegalStateException("Unable to find project while evaluating submit rule", e);
      }

      if (change.isClosed() && (!opts.recomputeOnClosedChanges() || OnlineReindexMode.isActive())) {
        return cd.notes().getSubmitRecords().stream()
            .map(
                r -> {
                  SubmitRecord record = r.deepCopy();
                  if (record.status == SubmitRecord.Status.OK) {
                    // Submit records that were OK when they got merged are CLOSED now.
                    record.status = SubmitRecord.Status.CLOSED;
                  }
                  return record;
                })
            .collect(toImmutableList());
      }

      // We evaluate all the plugin-defined evaluators,
      // and then we collect the results in one list.
      return Streams.stream(submitRules)
          // Skip evaluating the default submit rule if the project has prolog rules.
          // Note that in this case, the prolog submit rule will handle labels for us
          .filter(
              projectState.hasPrologRules()
                  ? rule -> !(rule.get() instanceof DefaultSubmitRule)
                  : rule -> true)
          .map(
              c ->
                  c.call(
                      s -> {
                        Optional<SubmitRecord> evaluate = s.evaluate(cd);
                        if (evaluate.isPresent()) {
                          evaluate.get().ruleName =
                              c.getPluginName() + "~" + s.getClass().getSimpleName();
                        }
                        return evaluate;
                      }))
          .filter(Optional::isPresent)
          .map(Optional::get)
          .collect(toImmutableList());
    }
  }

  /**
   * Evaluate the submit type rules to get the submit type.
   *
   * @return record from the evaluated rules.
   */
  public SubmitTypeRecord getSubmitType(ChangeData cd) {
    try (Timer0.Context ignored = metrics.submitTypeEvaluationLatency.start()) {
      try {
        Project.NameKey name = cd.project();
        Optional<ProjectState> project = projectCache.get(name);
        if (!project.isPresent()) {
          throw new NoSuchProjectException(name);
        }
      } catch (NoSuchProjectException e) {
        throw new IllegalStateException("Unable to find project while evaluating submit rule", e);
      }

      return prologRule.getSubmitType(cd);
    }
  }
}
