// Copyright (C) 2020 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.codeowners.config;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static java.util.Objects.requireNonNull;

import com.google.auto.value.AutoValue;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.primitives.Ints;
import com.google.gerrit.entities.LabelType;
import com.google.gerrit.entities.PatchSetApproval;
import com.google.gerrit.server.project.ProjectState;
import java.util.Optional;

/**
 * Approval that is required for an action.
 *
 * <p>A required approval is used to represent:
 *
 * <ul>
 *   <li>the approval that is required from code owners to approve the files in a change (see {@link
 *       RequiredApprovalConfig})
 *   <li>the approval that is required to override the code owners submit check (see {@link
 *       OverrideApprovalConfig})
 * </ul>
 */
@AutoValue
public abstract class RequiredApproval {
  /** The label on which an approval is required. */
  public abstract LabelType labelType();

  /** The voting value that is required on the {@link #labelType()} . */
  public abstract short value();

  /**
   * Whether the given patch set approval fulfills this required approval
   *
   * @param patchSetApproval the patch set approval for which it should be checked whether it is
   *     fulfilled by this required approval
   */
  public boolean isApprovedBy(PatchSetApproval patchSetApproval) {
    requireNonNull(patchSetApproval, "patchSetApproval");
    return labelType().getLabelId().equals(patchSetApproval.key().labelId())
        && patchSetApproval.value() >= value();
  }

  @Override
  public final String toString() {
    return labelType().getName() + "+" + value();
  }

  /**
   * Parses a string-representation of a {@link RequiredApproval}.
   *
   * @param projectState the project for which the required approval should be parsed
   * @param requiredApprovalString the string-representation of a {@link RequiredApproval}, must
   *     have the format "<label-name>+<label-vote>"
   * @return the parsed {@link RequiredApproval}
   * @throws IllegalArgumentException thrown if the given string cannot be parsed as {@link
   *     RequiredApproval} or if it contains an invalid label name or voting value
   * @throws IllegalStateException thrown if the parsed label doesn't exist on the project, or if
   *     the parsed voting value is not allowed for the label
   */
  static RequiredApproval parse(ProjectState projectState, String requiredApprovalString)
      throws IllegalArgumentException, IllegalStateException {
    requireNonNull(projectState, "projectState");
    requireNonNull(requiredApprovalString, "requiredApprovalString");

    int pos = requiredApprovalString.lastIndexOf('+');
    checkArgument(pos > 0, "Invalid format, expected '<label-name>+<label-value>'.");
    String labelName = requiredApprovalString.substring(0, pos);
    LabelType.checkName(labelName);

    Optional<LabelType> labelType =
        projectState.getLabelTypes().getLabelTypes().stream()
            .filter(lt -> lt.getName().equals(labelName))
            .findFirst();
    checkState(
        labelType.isPresent(),
        "Label %s doesn't exist for project %s.",
        labelName,
        projectState.getName());

    String votingValueString = requiredApprovalString.substring(pos + 1);
    Integer votingValue = Ints.tryParse(votingValueString);
    checkArgument(votingValue != null, "Invalid voting value: %s", votingValueString);
    checkArgument(votingValue > 0, "Voting value must be positive: %s", votingValueString);
    checkState(
        labelType.get().getByValue().containsKey(votingValue.shortValue()),
        "Label %s on project %s doesn't allow value %s.",
        labelName,
        projectState.getName(),
        votingValue);

    return create(labelType.get(), votingValue.shortValue());
  }

  /**
   * Creates the default {@link RequiredApproval} if no {@link RequiredApproval} was configured.
   *
   * @param projectState the project for which the default required approval should be returned
   * @param defaultLabel name of the default label
   * @param defaultValue default value that is required for the default label
   * @return the default {@link RequiredApproval}
   * @throws IllegalStateException thrown if the default label doesn't exist on the project, or if
   *     the default voting value is not allowed for the label
   */
  static RequiredApproval createDefault(
      ProjectState projectState, String defaultLabel, short defaultValue)
      throws IllegalStateException {
    requireNonNull(projectState, "projectState");
    requireNonNull(defaultLabel, "defaultLabel");

    Optional<LabelType> labelType =
        projectState.getLabelTypes().getLabelTypes().stream()
            .filter(lt -> lt.getName().equals(defaultLabel))
            .findFirst();
    checkState(
        labelType.isPresent(),
        "Default label %s doesn't exist for project %s.",
        defaultLabel,
        projectState.getName());
    checkState(
        labelType.get().getByValue().containsKey(defaultValue),
        "Label %s on project %s doesn't allow default value %s.",
        defaultLabel,
        projectState.getName(),
        defaultValue);
    return create(labelType.get(), defaultValue);
  }

  @VisibleForTesting
  public static RequiredApproval create(LabelType labelType, short vote) {
    return new AutoValue_RequiredApproval(labelType, vote);
  }
}
