// Copyright (C) 2018 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.googlesource.gerrit.plugins.simplesubmitrules.rules;

import com.google.common.annotations.VisibleForTesting;
import com.google.gerrit.common.data.LabelFunction;
import com.google.gerrit.common.data.LabelType;
import com.google.gerrit.common.data.SubmitRecord;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectConfig;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.project.SubmitRuleOptions;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.rules.SubmitRule;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.googlesource.gerrit.plugins.simplesubmitrules.SimpleSubmitRulesConfig;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.eclipse.jgit.lib.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/** Simple rule: require a non-author approval or block submission */
@Singleton
public class RequireNonAuthorApprovalRule implements SubmitRule {
  private static final Logger log = LoggerFactory.getLogger(RequireNonAuthorApprovalRule.class);
  private static final String E_UNABLE_TO_FETCH_CHANGE_OWNER = "Unable to fetch the change owner";
  private static final String E_UNABLE_TO_FETCH_LABELS =
      "Unable to fetch labels and approvals for the change";
  private final ProjectCache projectCache;

  @Inject
  public RequireNonAuthorApprovalRule(ProjectCache projectCache) {
    this.projectCache = projectCache;
  }

  @Override
  public Collection<SubmitRecord> evaluate(ChangeData cd, SubmitRuleOptions options) {
    ProjectState projectState = projectCache.get(cd.project());
    Config config = projectState.getConfig(ProjectConfig.PROJECT_CONFIG).getWithInheritance();

    Account.Id owner;
    try {
      owner = cd.change().getOwner();
    } catch (OrmException e) {
      log.error(E_UNABLE_TO_FETCH_CHANGE_OWNER, e);

      SubmitRecord submitRecord = new SubmitRecord();
      submitRecord.errorMessage = E_UNABLE_TO_FETCH_CHANGE_OWNER;
      submitRecord.status = SubmitRecord.Status.RULE_ERROR;
      return Collections.singletonList(submitRecord);
    }

    List<LabelType> labelTypes;
    List<PatchSetApproval> approvals;
    try {
      labelTypes = cd.getLabelTypes().getLabelTypes();
      approvals = cd.currentApprovals();
    } catch (OrmException e) {
      log.error(E_UNABLE_TO_FETCH_LABELS, e);

      SubmitRecord submitRecord = new SubmitRecord();
      submitRecord.errorMessage = E_UNABLE_TO_FETCH_LABELS;
      submitRecord.status = SubmitRecord.Status.RULE_ERROR;

      return Collections.singletonList(submitRecord);
    }

    SubmitRecord submitRecord = new SubmitRecord();
    submitRecord.status = SubmitRecord.Status.OK;
    submitRecord.labels = new ArrayList<>(labelTypes.size());

    for (LabelType t : labelTypes) {
      if (!config.getBoolean(
          t.getName(), SimpleSubmitRulesConfig.KEY_REQUIRE_NON_AUTHOR_APPROVAL, false)) {
        // The default rules are enough in this case.
        continue;
      }

      LabelFunction labelFunction = t.getFunction();
      if (labelFunction == null) {
        continue;
      }

      Collection<PatchSetApproval> approvalsForLabel = getApprovalsForLabel(approvals, t, owner);
      SubmitRecord.Label label = labelFunction.check(t, approvalsForLabel);

      switch (label.status) {
        case OK:
        case MAY:
          break;

        case NEED:
        case REJECT:
        case IMPOSSIBLE:
          submitRecord.labels.add(label);
          submitRecord.status = SubmitRecord.Status.NOT_READY;
          break;
      }
    }

    if (submitRecord.labels.isEmpty()) {
      return Collections.emptyList();
    }

    return Collections.singletonList(submitRecord);
  }

  /**
   * Returns the approvals for a given label, for everyone except from `user`, except if the vote is
   * negative.
   */
  @VisibleForTesting
  static Collection<PatchSetApproval> getApprovalsForLabel(
      Collection<PatchSetApproval> approvals, LabelType t, Account.Id user) {
    return approvals
        .stream()
        .filter(input -> input.getValue() < 0 || !input.getAccountId().equals(user))
        .filter(input -> input.getLabel().equals(t.getLabelId().get()))
        .collect(Collectors.toList());
  }
}
