// 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 com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.LabelType;
import com.google.gerrit.entities.SubmitRecord;
import com.google.gerrit.entities.SubmitRecord.Label;
import com.google.gerrit.entities.SubmitRequirement;
import com.google.gerrit.entities.SubmitRequirementExpression;
import com.google.gerrit.entities.SubmitRequirementExpressionResult;
import com.google.gerrit.entities.SubmitRequirementExpressionResult.Status;
import com.google.gerrit.entities.SubmitRequirementResult;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
import com.google.gerrit.server.rules.DefaultSubmitRule;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import org.eclipse.jgit.lib.ObjectId;

/**
 * Convert {@link com.google.gerrit.entities.SubmitRecord} entities to {@link
 * com.google.gerrit.entities.SubmitRequirementResult}s.
 */
public class SubmitRequirementsAdapter {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private SubmitRequirementsAdapter() {}

  /**
   * Retrieve legacy submit records (created by label functions and other {@link
   * com.google.gerrit.server.rules.SubmitRule}s) and convert them to submit requirement results.
   */
  public static Map<SubmitRequirement, SubmitRequirementResult> getLegacyRequirements(
      ChangeData cd) {
    // We use SubmitRuleOptions.defaults() which does not recompute submit rules for closed changes.
    // This doesn't have an effect since we never call this class (i.e. to evaluate submit
    // requirements) for closed changes.
    List<SubmitRecord> records = cd.submitRecords(SubmitRuleOptions.defaults());
    boolean areForced =
        records.stream().anyMatch(record -> SubmitRecord.Status.FORCED.equals(record.status));
    List<LabelType> labelTypes = cd.getLabelTypes().getLabelTypes();
    ObjectId commitId = cd.currentPatchSet().commitId();
    Map<String, List<SubmitRequirementResult>> srsByName =
        records.stream()
            // Filter out the "FORCED" submit record. This is a marker submit record that was just
            // used to indicate that all other records were forced. "FORCED" means that the change
            // was pushed with the %submit option bypassing submit rules.
            .filter(r -> !SubmitRecord.Status.FORCED.equals(r.status))
            .map(r -> createResult(r, labelTypes, commitId, areForced))
            .flatMap(List::stream)
            .collect(Collectors.groupingBy(sr -> sr.submitRequirement().name()));

    // We convert submit records to submit requirements by generating a separate
    // submit requirement result for each available label in each submit record.
    // The SR status is derived from the label status of the submit record.
    // This conversion might result in duplicate entries.
    // One such example can be a prolog rule emitting the same label name twice.
    // Another case might happen if two different submit rules emit the same label
    // name. In such cases, we need to merge these entries and return a single submit
    // requirement result. If both entries agree in their status, return any of them.
    // Otherwise, favour the entry that is blocking submission.
    ImmutableMap.Builder<SubmitRequirement, SubmitRequirementResult> result =
        ImmutableMap.builder();
    for (Map.Entry<String, List<SubmitRequirementResult>> entry : srsByName.entrySet()) {
      if (entry.getValue().size() == 1) {
        SubmitRequirementResult srResult = entry.getValue().iterator().next();
        result.put(srResult.submitRequirement(), srResult);
        continue;
      }
      // If all submit requirements with the same name match in status, return the first one.
      List<SubmitRequirementResult> resultsSameName = entry.getValue();
      boolean allNonBlocking = resultsSameName.stream().allMatch(sr -> sr.fulfilled());
      if (allNonBlocking) {
        result.put(resultsSameName.get(0).submitRequirement(), resultsSameName.get(0));
      } else {
        // Otherwise, return the first submit requirement result that is blocking submission.
        Optional<SubmitRequirementResult> nonFulfilled =
            resultsSameName.stream().filter(sr -> !sr.fulfilled()).findFirst();
        if (nonFulfilled.isPresent()) {
          result.put(nonFulfilled.get().submitRequirement(), nonFulfilled.get());
        }
      }
    }
    return result.build();
  }

  static List<SubmitRequirementResult> createResult(
      SubmitRecord record, List<LabelType> labelTypes, ObjectId psCommitId, boolean isForced) {
    List<SubmitRequirementResult> results;
    if (record.ruleName != null && record.ruleName.equals(DefaultSubmitRule.RULE_NAME)) {
      results = createFromDefaultSubmitRecord(record.labels, labelTypes, psCommitId, isForced);
    } else {
      results = createFromCustomSubmitRecord(record, psCommitId, isForced);
    }
    logger.atFine().log("Converted submit record %s to submit requirements %s", record, results);
    return results;
  }

  private static List<SubmitRequirementResult> createFromDefaultSubmitRecord(
      @Nullable List<Label> labels,
      List<LabelType> labelTypes,
      ObjectId psCommitId,
      boolean isForced) {
    ImmutableList.Builder<SubmitRequirementResult> result = ImmutableList.builder();
    if (labels == null) {
      return result.build();
    }
    for (Label label : labels) {
      if (skipSubmitRequirementFor(label)) {
        continue;
      }
      Optional<LabelType> maybeLabelType = getLabelType(labelTypes, label.label);
      if (!maybeLabelType.isPresent()) {
        // Label type might have been removed from the project config. We don't have information
        // if it was blocking or not, hence we skip the label.
        continue;
      }
      LabelType labelType = maybeLabelType.get();
      if (!isBlocking(labelType)) {
        continue;
      }
      ImmutableList<String> atoms = toExpressionAtomList(labelType);
      SubmitRequirement.Builder req =
          SubmitRequirement.builder()
              .setName(label.label)
              .setSubmittabilityExpression(toExpression(atoms))
              .setAllowOverrideInChildProjects(labelType.isCanOverride());
      result.add(
          SubmitRequirementResult.builder()
              .legacy(Optional.of(true))
              .submitRequirement(req.build())
              .submittabilityExpressionResult(
                  createExpressionResult(toExpression(atoms), mapStatus(label), atoms))
              .patchSetCommitId(psCommitId)
              .forced(Optional.of(isForced))
              .build());
    }
    return result.build();
  }

  private static List<SubmitRequirementResult> createFromCustomSubmitRecord(
      SubmitRecord record, ObjectId psCommitId, boolean isForced) {
    String ruleName = record.ruleName != null ? record.ruleName : "Custom-Rule";
    if (record.labels == null || record.labels.isEmpty()) {
      SubmitRequirement sr =
          SubmitRequirement.builder()
              .setName(ruleName)
              .setSubmittabilityExpression(
                  SubmitRequirementExpression.create(String.format("rule:%s", ruleName)))
              .setAllowOverrideInChildProjects(false)
              .build();
      return ImmutableList.of(
          SubmitRequirementResult.builder()
              .legacy(Optional.of(true))
              .submitRequirement(sr)
              .submittabilityExpressionResult(
                  createExpressionResult(
                      sr.submittabilityExpression(),
                      mapStatus(record),
                      ImmutableList.of(ruleName),
                      record.errorMessage))
              .patchSetCommitId(psCommitId)
              .forced(Optional.of(isForced))
              .build());
    }
    ImmutableList.Builder<SubmitRequirementResult> result = ImmutableList.builder();
    for (Label label : record.labels) {
      if (skipSubmitRequirementFor(label)
          ||
          // If SubmitRecord is a PASS, then skip all the requirements
          // that are not a PASS as they would block the overall submit requirement
          // status from being a PASS
          (mapStatus(record) == Status.PASS && mapStatus(label) != Status.PASS)) {
        continue;
      }
      String expressionString = String.format("label:%s=%s", label.label, ruleName);
      SubmitRequirement sr =
          SubmitRequirement.builder()
              .setName(label.label)
              .setSubmittabilityExpression(SubmitRequirementExpression.create(expressionString))
              .setAllowOverrideInChildProjects(false)
              .build();
      result.add(
          SubmitRequirementResult.builder()
              .legacy(Optional.of(true))
              .submitRequirement(sr)
              .submittabilityExpressionResult(
                  createExpressionResult(
                      sr.submittabilityExpression(),
                      mapStatus(label),
                      ImmutableList.of(expressionString)))
              .patchSetCommitId(psCommitId)
              .build());
    }
    return result.build();
  }

  private static boolean isBlocking(LabelType labelType) {
    return labelType.getFunction().isBlock() || labelType.getFunction().isRequired();
  }

  private static SubmitRequirementExpression toExpression(List<String> atoms) {
    return SubmitRequirementExpression.create(String.join(" ", atoms));
  }

  private static ImmutableList<String> toExpressionAtomList(LabelType lt) {
    String ignoreSelfApproval =
        lt.isIgnoreSelfApproval() ? ",user=" + ChangeQueryBuilder.ARG_ID_NON_UPLOADER : "";
    switch (lt.getFunction()) {
      case MAX_WITH_BLOCK:
        return ImmutableList.of(
            String.format("label:%s=MAX", lt.getName()) + ignoreSelfApproval,
            String.format("-label:%s=MIN", lt.getName()));
      case ANY_WITH_BLOCK:
        return ImmutableList.of(String.format(String.format("-label:%s=MIN", lt.getName())));
      case MAX_NO_BLOCK:
        return ImmutableList.of(
            String.format(String.format("label:%s=MAX", lt.getName())) + ignoreSelfApproval);
      case NO_BLOCK:
      case NO_OP:
      case PATCH_SET_LOCK:
      default:
        return ImmutableList.of();
    }
  }

  private static Status mapStatus(Label label) {
    SubmitRequirementExpressionResult.Status status = Status.PASS;
    switch (label.status) {
      case OK:
      case MAY:
        status = Status.PASS;
        break;
      case REJECT:
      case NEED:
      case IMPOSSIBLE:
        status = Status.FAIL;
        break;
    }
    return status;
  }

  private static Status mapStatus(SubmitRecord submitRecord) {
    switch (submitRecord.status) {
      case OK:
      case CLOSED:
      case FORCED:
        return Status.PASS;
      case NOT_READY:
        return Status.FAIL;
      case RULE_ERROR:
      default:
        return Status.ERROR;
    }
  }

  private static SubmitRequirementExpressionResult createExpressionResult(
      SubmitRequirementExpression expression, Status status, ImmutableList<String> atoms) {
    return SubmitRequirementExpressionResult.create(
        expression,
        status,
        status == Status.PASS ? atoms : ImmutableList.of(),
        status == Status.FAIL ? atoms : ImmutableList.of());
  }

  private static SubmitRequirementExpressionResult createExpressionResult(
      SubmitRequirementExpression expression,
      Status status,
      ImmutableList<String> atoms,
      String errorMessage) {
    return SubmitRequirementExpressionResult.create(
        expression,
        status,
        status == Status.PASS ? atoms : ImmutableList.of(),
        status == Status.FAIL ? atoms : ImmutableList.of(),
        Optional.ofNullable(Strings.emptyToNull(errorMessage)));
  }

  private static Optional<LabelType> getLabelType(List<LabelType> labelTypes, String labelName) {
    List<LabelType> label =
        labelTypes.stream()
            .filter(lt -> lt.getName().equals(labelName))
            .collect(Collectors.toList());
    if (label.isEmpty()) {
      // Label might have been removed from the project.
      logger.atFine().log("Label '%s' was not found for the project.", labelName);
      return Optional.empty();
    } else if (label.size() > 1) {
      logger.atWarning().log("Found more than one label definition for label name '%s'", labelName);
      return Optional.empty();
    }
    return Optional.of(label.get(0));
  }

  /**
   * Returns true if we should skip creating a "submit requirement" result out of the "submit
   * record" label.
   */
  private static boolean skipSubmitRequirementFor(SubmitRecord.Label label) {
    return label.status == SubmitRecord.Label.Status.MAY;
  }
}
