// Copyright (C) 2022 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.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.LabelFunction;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.client.ChangeKind;
import com.google.gerrit.server.events.CommitReceivedEvent;
import com.google.gerrit.server.git.validators.CommitValidationException;
import com.google.gerrit.server.git.validators.CommitValidationListener;
import com.google.gerrit.server.git.validators.CommitValidationMessage;
import com.google.gerrit.server.git.validators.ValidationMessage;
import com.google.gerrit.server.patch.DiffNotAvailableException;
import com.google.gerrit.server.patch.DiffOperations;
import com.google.gerrit.server.patch.DiffOptions;
import com.google.gerrit.server.patch.filediff.FileDiffOutput;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;

/**
 * Validates modifications to label configurations in the {@code project.config} file that is stored
 * in {@code refs/meta/config}.
 *
 * <p>Rejects setting/changing deprecated fields that are no longer supported (fields {@code
 * copyAnyScore}, {@code copyMinScore}, {@code copyMaxScore}, {@code copyAllScoresIfNoChange},
 * {@code copyAllScoresIfNoCodeChange}, {@code copyAllScoresOnMergeFirstParentUpdate}, {@code
 * copyAllScoresOnTrivialRebase}, {@code copyAllScoresIfListOfFilesDidNotChange}, {@code
 * copyValue}).
 *
 * <p>Updates that unset the deprecated fields or that don't touch them are allowed.
 */
@Singleton
public class LabelConfigValidator implements CommitValidationListener {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  @VisibleForTesting public static final String KEY_COPY_ANY_SCORE = "copyAnyScore";

  @VisibleForTesting public static final String KEY_COPY_MIN_SCORE = "copyMinScore";

  @VisibleForTesting public static final String KEY_COPY_MAX_SCORE = "copyMaxScore";

  @VisibleForTesting public static final String KEY_COPY_VALUE = "copyValue";

  @VisibleForTesting
  public static final String KEY_COPY_ALL_SCORES_ON_MERGE_FIRST_PARENT_UPDATE =
      "copyAllScoresOnMergeFirstParentUpdate";

  @VisibleForTesting
  public static final String KEY_COPY_ALL_SCORES_ON_TRIVIAL_REBASE = "copyAllScoresOnTrivialRebase";

  @VisibleForTesting
  public static final String KEY_COPY_ALL_SCORES_IF_NO_CODE_CHANGE = "copyAllScoresIfNoCodeChange";

  @VisibleForTesting
  public static final String KEY_COPY_ALL_SCORES_IF_NO_CHANGE = "copyAllScoresIfNoChange";

  @VisibleForTesting
  public static final String KEY_COPY_ALL_SCORES_IF_LIST_OF_FILES_DID_NOT_CHANGE =
      "copyAllScoresIfListOfFilesDidNotChange";

  // Map of deprecated boolean flags to the predicates that should be used in the copy condition
  // instead.
  private static final ImmutableMap<String, String> DEPRECATED_FLAGS =
      ImmutableMap.<String, String>builder()
          .put(KEY_COPY_ANY_SCORE, "is:ANY")
          .put(KEY_COPY_MIN_SCORE, "is:MIN")
          .put(KEY_COPY_MAX_SCORE, "is:MAX")
          .put(KEY_COPY_ALL_SCORES_IF_NO_CHANGE, "changekind:" + ChangeKind.NO_CHANGE.name())
          .put(
              KEY_COPY_ALL_SCORES_IF_NO_CODE_CHANGE,
              "changekind:" + ChangeKind.NO_CODE_CHANGE.name())
          .put(
              KEY_COPY_ALL_SCORES_ON_MERGE_FIRST_PARENT_UPDATE,
              "changekind:" + ChangeKind.MERGE_FIRST_PARENT_UPDATE.name())
          .put(
              KEY_COPY_ALL_SCORES_ON_TRIVIAL_REBASE,
              "changekind:" + ChangeKind.TRIVIAL_REBASE.name())
          .put(KEY_COPY_ALL_SCORES_IF_LIST_OF_FILES_DID_NOT_CHANGE, "has:unchanged-files")
          .build();

  private final DiffOperations diffOperations;

  @Inject
  public LabelConfigValidator(DiffOperations diffOperations) {
    this.diffOperations = diffOperations;
  }

  @Override
  public List<CommitValidationMessage> onCommitReceived(CommitReceivedEvent receiveEvent)
      throws CommitValidationException {
    try {
      if (!receiveEvent.refName.equals(RefNames.REFS_CONFIG)
          || !isFileChanged(receiveEvent, ProjectConfig.PROJECT_CONFIG)) {
        // The project.config file in refs/meta/config was not modified, hence we do not need to do
        // any validation and can return early.
        return ImmutableList.of();
      }

      ImmutableList.Builder<CommitValidationMessage> validationMessageBuilder =
          ImmutableList.builder();

      // Load the new config
      Config newConfig;
      try {
        newConfig = loadNewConfig(receiveEvent);
      } catch (ConfigInvalidException e) {
        // The current config is invalid, hence we cannot inspect the delta.
        // Rejecting invalid configs is not the responsibility of this validator, hence ignore this
        // exception here.
        logger.atWarning().log(
            "cannot inspect the project config, because parsing %s from revision %s"
                + " in project %s failed: %s",
            ProjectConfig.PROJECT_CONFIG,
            receiveEvent.commit.name(),
            receiveEvent.getProjectNameKey(),
            e.getMessage());
        return ImmutableList.of();
      }

      // Load the old config
      Optional<Config> oldConfig = loadOldConfig(receiveEvent);

      for (String labelName : newConfig.getSubsections(ProjectConfig.LABEL)) {
        for (String deprecatedFlag : DEPRECATED_FLAGS.keySet()) {
          if (flagChangedOrNewlySet(newConfig, oldConfig.orElse(null), labelName, deprecatedFlag)) {
            validationMessageBuilder.add(
                new CommitValidationMessage(
                    String.format(
                        "Parameter '%s.%s.%s' is deprecated and cannot be set,"
                            + " use '%s' in '%s.%s.%s' instead.",
                        ProjectConfig.LABEL,
                        labelName,
                        deprecatedFlag,
                        DEPRECATED_FLAGS.get(deprecatedFlag),
                        ProjectConfig.LABEL,
                        labelName,
                        ProjectConfig.KEY_COPY_CONDITION),
                    ValidationMessage.Type.ERROR));
          }
        }

        if (copyValuesChangedOrNewlySet(newConfig, oldConfig.orElse(null), labelName)) {
          validationMessageBuilder.add(
              new CommitValidationMessage(
                  String.format(
                      "Parameter '%s.%s.%s' is deprecated and cannot be set,"
                          + " use 'is:<copy-value>' in '%s.%s.%s' instead.",
                      ProjectConfig.LABEL,
                      labelName,
                      KEY_COPY_VALUE,
                      ProjectConfig.LABEL,
                      labelName,
                      ProjectConfig.KEY_COPY_CONDITION),
                  ValidationMessage.Type.ERROR));
        }

        // Ban modifying label functions to any blocking function value
        if (flagChangedOrNewlySet(
            newConfig, oldConfig.orElse(null), labelName, ProjectConfig.KEY_FUNCTION)) {
          String fnName =
              newConfig.getString(ProjectConfig.LABEL, labelName, ProjectConfig.KEY_FUNCTION);
          Optional<LabelFunction> labelFn = LabelFunction.parse(fnName);
          if (labelFn.isPresent() && !isLabelFunctionAllowed(labelFn.get())) {
            validationMessageBuilder.add(
                new CommitValidationMessage(
                    String.format(
                        "Value '%s' of '%s.%s.%s' is not allowed and cannot be set."
                            + " Label functions can only be set to {%s, %s, %s}."
                            + " Use submit requirements instead of label functions.",
                        fnName,
                        ProjectConfig.LABEL,
                        labelName,
                        ProjectConfig.KEY_FUNCTION,
                        LabelFunction.NO_BLOCK,
                        LabelFunction.NO_OP,
                        LabelFunction.PATCH_SET_LOCK),
                    ValidationMessage.Type.ERROR));
          }
        }

        // Ban deletions of label functions as well since the default is MaxWithBlock
        if (flagDeleted(newConfig, oldConfig.orElse(null), labelName, ProjectConfig.KEY_FUNCTION)) {
          validationMessageBuilder.add(
              new CommitValidationMessage(
                  String.format(
                      "Cannot delete '%s.%s.%s'."
                          + " Label functions can only be set to {%s, %s, %s}."
                          + " Use submit requirements instead of label functions.",
                      ProjectConfig.LABEL,
                      labelName,
                      ProjectConfig.KEY_FUNCTION,
                      LabelFunction.NO_BLOCK,
                      LabelFunction.NO_OP,
                      LabelFunction.PATCH_SET_LOCK),
                  ValidationMessage.Type.ERROR));
        }
      }

      ImmutableList<CommitValidationMessage> validationMessages = validationMessageBuilder.build();
      if (!validationMessages.isEmpty()) {
        throw new CommitValidationException(
            String.format(
                "invalid %s file in revision %s",
                ProjectConfig.PROJECT_CONFIG, receiveEvent.commit.getName()),
            validationMessages);
      }
      return ImmutableList.of();
    } catch (IOException | DiffNotAvailableException e) {
      String errorMessage =
          String.format(
              "failed to validate file %s for revision %s in ref %s of project %s",
              ProjectConfig.PROJECT_CONFIG,
              receiveEvent.commit.getName(),
              RefNames.REFS_CONFIG,
              receiveEvent.getProjectNameKey());
      logger.atSevere().withCause(e).log("%s", errorMessage);
      throw new CommitValidationException(errorMessage, e);
    }
  }

  /**
   * Whether the given file was changed in the given revision.
   *
   * @param receiveEvent the receive event
   * @param fileName the name of the file
   */
  private boolean isFileChanged(CommitReceivedEvent receiveEvent, String fileName)
      throws DiffNotAvailableException {
    Map<String, FileDiffOutput> fileDiffOutputs;
    if (receiveEvent.commit.getParentCount() > 0) {
      // normal commit with one parent: use listModifiedFilesAgainstParent with parentNum = 1 to
      // compare against the only parent (using parentNum = 0 to compare against the default parent
      // would also work)
      // merge commit with 2 or more parents: must use listModifiedFilesAgainstParent with parentNum
      // = 1 to compare against the first parent (using parentNum = 0 would compare against the
      // auto-merge)
      fileDiffOutputs =
          diffOperations.listModifiedFilesAgainstParent(
              receiveEvent.getProjectNameKey(), receiveEvent.commit, 1, DiffOptions.DEFAULTS);
    } else {
      // initial commit: must use listModifiedFilesAgainstParent with parentNum = 0
      fileDiffOutputs =
          diffOperations.listModifiedFilesAgainstParent(
              receiveEvent.getProjectNameKey(),
              receiveEvent.commit,
              /* parentNum=*/ 0,
              DiffOptions.DEFAULTS);
    }
    return fileDiffOutputs.keySet().contains(fileName);
  }

  private Config loadNewConfig(CommitReceivedEvent receiveEvent)
      throws IOException, ConfigInvalidException {
    ProjectLevelConfig.Bare bareConfig = new ProjectLevelConfig.Bare(ProjectConfig.PROJECT_CONFIG);
    bareConfig.load(receiveEvent.project.getNameKey(), receiveEvent.revWalk, receiveEvent.commit);
    return bareConfig.getConfig();
  }

  private Optional<Config> loadOldConfig(CommitReceivedEvent receiveEvent) throws IOException {
    if (receiveEvent.commit.getParentCount() == 0) {
      // initial commit, an old config doesn't exist
      return Optional.empty();
    }

    try {
      ProjectLevelConfig.Bare bareConfig =
          new ProjectLevelConfig.Bare(ProjectConfig.PROJECT_CONFIG);
      bareConfig.load(
          receiveEvent.project.getNameKey(),
          receiveEvent.revWalk,
          receiveEvent.commit.getParent(0));
      return Optional.of(bareConfig.getConfig());
    } catch (ConfigInvalidException e) {
      // the old config is not parseable, treat this the same way as if an old config didn't exist
      // so that all parameters in the new config are validated
      logger.atWarning().log(
          "cannot inspect the old project config, because parsing %s from parent revision %s"
              + " in project %s failed: %s",
          ProjectConfig.PROJECT_CONFIG,
          receiveEvent.commit.name(),
          receiveEvent.getProjectNameKey(),
          e.getMessage());
      return Optional.empty();
    }
  }

  private static boolean flagChangedOrNewlySet(
      Config newConfig, @Nullable Config oldConfig, String labelName, String key) {
    if (oldConfig == null) {
      return newConfig.getNames(ProjectConfig.LABEL, labelName).contains(key);
    }

    // Use getString rather than getBoolean so that we do not have to deal with values that cannot
    // be parsed as a boolean.
    String oldValue = oldConfig.getString(ProjectConfig.LABEL, labelName, key);
    String newValue = newConfig.getString(ProjectConfig.LABEL, labelName, key);
    return newValue != null && !newValue.equals(oldValue);
  }

  private static boolean flagDeleted(
      Config newConfig, @Nullable Config oldConfig, String labelName, String key) {
    if (oldConfig == null) {
      return false;
    }
    String oldValue = oldConfig.getString(ProjectConfig.LABEL, labelName, key);
    String newValue = newConfig.getString(ProjectConfig.LABEL, labelName, key);
    return oldValue != null && newValue == null;
  }

  private static boolean copyValuesChangedOrNewlySet(
      Config newConfig, @Nullable Config oldConfig, String labelName) {
    if (oldConfig == null) {
      return newConfig.getNames(ProjectConfig.LABEL, labelName).contains(KEY_COPY_VALUE);
    }

    // Ignore the order in which the copy values are defined in the new and old config, since the
    // order doesn't matter for this parameter.
    ImmutableSet<String> oldValues =
        ImmutableSet.copyOf(
            oldConfig.getStringList(ProjectConfig.LABEL, labelName, KEY_COPY_VALUE));
    ImmutableSet<String> newValues =
        ImmutableSet.copyOf(
            newConfig.getStringList(ProjectConfig.LABEL, labelName, KEY_COPY_VALUE));
    return !newValues.isEmpty() && !Sets.difference(newValues, oldValues).isEmpty();
  }

  private static boolean isLabelFunctionAllowed(LabelFunction labelFunction) {
    return labelFunction.equals(LabelFunction.NO_BLOCK)
        || labelFunction.equals(LabelFunction.NO_OP)
        || labelFunction.equals(LabelFunction.PATCH_SET_LOCK);
  }
}
