// 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.google.gerrit.server.change;

import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static java.util.stream.Collectors.toList;

import com.google.common.collect.HashBasedTable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.MultimapBuilder;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.Table;
import com.google.common.flogger.FluentLogger;
import com.google.common.primitives.Ints;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.LabelFunction;
import com.google.gerrit.entities.LabelType;
import com.google.gerrit.entities.LabelTypes;
import com.google.gerrit.entities.LabelValue;
import com.google.gerrit.entities.PatchSetApproval;
import com.google.gerrit.entities.SubmitRecord;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.ApprovalInfo;
import com.google.gerrit.extensions.common.LabelInfo;
import com.google.gerrit.extensions.common.VotingRangeInfo;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.account.AccountLoader;
import com.google.gerrit.server.logging.Metadata;
import com.google.gerrit.server.logging.TraceContext;
import com.google.gerrit.server.logging.TraceContext.TraceTimer;
import com.google.gerrit.server.notedb.ReviewerStateInternal;
import com.google.gerrit.server.permissions.LabelPermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.DeleteVoteControl;
import com.google.gerrit.server.project.RemoveReviewerControl;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.rules.PrologSubmitRuleUtil;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.TreeMap;

/**
 * Produces label-related entities, like {@link LabelInfo}s, which is serialized to JSON afterwards.
 */
@Singleton
public class LabelsJson {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private final PermissionBackend permissionBackend;
  private final DeleteVoteControl deleteVoteControl;
  private final RemoveReviewerControl removeReviewerControl;
  private final PrologSubmitRuleUtil ruleUtil;
  private final LabelsJsonRules labelsJsonRules;

  @Inject
  LabelsJson(
      PermissionBackend permissionBackend,
      DeleteVoteControl deleteVoteControl,
      RemoveReviewerControl removeReviewerControl,
      PrologSubmitRuleUtil ruleUtil,
      LabelsJsonRules labelsJsonRules) {
    this.permissionBackend = permissionBackend;
    this.deleteVoteControl = deleteVoteControl;
    this.removeReviewerControl = removeReviewerControl;
    this.ruleUtil = ruleUtil;
    this.labelsJsonRules = labelsJsonRules;
  }

  /**
   * Returns all {@link LabelInfo}s for a single change. Uses the provided {@link AccountLoader} to
   * lazily populate accounts. Callers have to call {@link AccountLoader#fill()} afterwards to
   * populate all accounts in the returned {@link LabelInfo}s.
   */
  @Nullable
  Map<String, LabelInfo> labelsFor(
      AccountLoader accountLoader, ChangeData cd, boolean standard, boolean detailed)
      throws PermissionBackendException {
    // Delegate to old implementation if submit rules are enabled.
    if (ruleUtil.isProjectRulesEnabled()) {
      return labelsJsonRules.labelsFor(accountLoader, cd, standard, detailed);
    }

    if (!standard && !detailed) {
      return null;
    }

    try (TraceTimer timer =
        TraceContext.newTimer(
            "Get labels", Metadata.builder().changeId(cd.change().getId().get()).build())) {
      LabelTypes labelTypes = cd.getLabelTypes();
      return cd.change().isMerged()
          ? labelsForSubmittedChange(accountLoader, cd, labelTypes, standard, detailed)
          : labelsForUnsubmittedChange(accountLoader, cd, labelTypes, standard, detailed);
    }
  }

  /**
   * Returns A map of all label names and the values that the provided user has permission to vote
   * on.
   *
   * @param filterApprovalsBy a Gerrit user ID.
   * @param cd {@link ChangeData} corresponding to a specific gerrit change.
   * @return A Map where the key contain a label name, and the value is a list of the permissible
   *     vote values that the user can vote on.
   */
  Map<String, Collection<String>> permittedLabels(Account.Id filterApprovalsBy, ChangeData cd)
      throws PermissionBackendException {
    try (TraceTimer timer =
        TraceContext.newTimer(
            "Get permitted labels",
            Metadata.builder().changeId(cd.change().getId().get()).build())) {
      SetMultimap<String, String> permitted = LinkedHashMultimap.create();
      boolean isMerged = cd.change().isMerged();
      Map<String, Short> currentUserVotes = currentLabels(filterApprovalsBy, cd);
      for (LabelType labelType : cd.getLabelTypes().getLabelTypes()) {
        if (isMerged && !labelType.isAllowPostSubmit()) {
          continue;
        }
        Set<LabelPermission.WithValue> can =
            permissionBackend.absentUser(filterApprovalsBy).change(cd).test(labelType);
        for (LabelPermission.WithValue val : can) {
          logger.atFine().log(
              "User %s For label %s can vote %s ", filterApprovalsBy, val.label(), val.value());
        }

        for (LabelValue v : labelType.getValues()) {
          boolean ok = can.contains(new LabelPermission.WithValue(labelType, v));
          if (isMerged) {
            // Votes cannot be decreased if the change is merged. Only accept the label value if
            // it's
            // greater or equal than the user's latest vote.
            short prev = currentUserVotes.getOrDefault(labelType.getName(), (short) 0);
            ok &= v.getValue() >= prev;
          }
          if (ok) {
            permitted.put(labelType.getName(), v.formatValue());
          }
        }
      }
      clearOnlyZerosEntries(permitted);
      return permitted.asMap();
    }
  }

  /**
   * Returns A map of all labels that the provided user has permission to remove.
   *
   * @param accountLoader to load the reviewers' data with.
   * @param user a Gerrit user.
   * @param cd {@link ChangeData} corresponding to a specific gerrit change.
   * @return A Map of {@code labelName} -> {Map of {@code value} -> List of {@link AccountInfo}}
   *     that the user can remove votes from.
   */
  Map<String, Map<String, List<AccountInfo>>> removableLabels(
      AccountLoader accountLoader, CurrentUser user, ChangeData cd)
      throws PermissionBackendException {
    try (TraceTimer timer =
        TraceContext.newTimer(
            "Get removable labels",
            Metadata.builder().changeId(cd.change().getId().get()).build())) {
      if (cd.change().isMerged()) {
        return new HashMap<>();
      }

      Map<String, Map<String, List<AccountInfo>>> res = new HashMap<>();
      LabelTypes labelTypes = cd.getLabelTypes();
      for (PatchSetApproval approval : cd.currentApprovals()) {
        Optional<LabelType> labelType = labelTypes.byLabel(approval.labelId());
        if (!labelType.isPresent()) {
          continue;
        }
        if (!(deleteVoteControl.testDeleteVotePermissions(user, cd, approval, labelType.get())
            || removeReviewerControl.testRemoveReviewer(
                cd, user, approval.accountId(), approval.value()))) {
          continue;
        }
        if (!res.containsKey(approval.label())) {
          res.put(approval.label(), new HashMap<>());
        }
        String labelValue = LabelValue.formatValue(approval.value());
        if (!res.get(approval.label()).containsKey(labelValue)) {
          res.get(approval.label()).put(labelValue, new ArrayList<>());
        }
        res.get(approval.label()).get(labelValue).add(accountLoader.get(approval.accountId()));
      }
      return res;
    }
  }

  private static void clearOnlyZerosEntries(SetMultimap<String, String> permitted) {
    List<String> toClear = Lists.newArrayListWithCapacity(permitted.keySet().size());
    for (Map.Entry<String, Collection<String>> e : permitted.asMap().entrySet()) {
      if (isOnlyZero(e.getValue())) {
        toClear.add(e.getKey());
      }
    }
    for (String label : toClear) {
      permitted.removeAll(label);
    }
  }

  private static boolean isOnlyZero(Collection<String> values) {
    return values.isEmpty() || (values.size() == 1 && values.contains(" 0"));
  }

  private static void addApproval(LabelInfo label, ApprovalInfo approval) {
    if (label.all == null) {
      label.all = new ArrayList<>();
    }
    label.all.add(approval);
  }

  private Map<String, LabelInfo> labelsForUnsubmittedChange(
      AccountLoader accountLoader,
      ChangeData cd,
      LabelTypes labelTypes,
      boolean standard,
      boolean detailed)
      throws PermissionBackendException {
    Map<String, LabelInfo> labels =
        initLabels(accountLoader, cd, labelTypes, /* includeAccountInfo= */ standard || detailed);
    setAllApprovals(accountLoader, cd, labels, detailed);

    for (Map.Entry<String, LabelInfo> e : labels.entrySet()) {
      Optional<LabelType> type = labelTypes.byLabel(e.getKey());
      if (!type.isPresent()) {
        continue;
      }
      if (standard || detailed) {
        for (PatchSetApproval psa : cd.currentApprovals()) {
          if (type.get().matches(psa)) {
            short val = psa.value();
            Account.Id accountId = psa.accountId();
            setLabelScores(accountLoader, type.get(), e.getValue(), val, accountId);
          }
        }
      }
      setLabelValues(type.get(), e.getValue());
    }
    return labels;
  }

  private Integer parseRangeValue(String value) {
    if (value.startsWith("+")) {
      value = value.substring(1);
    } else if (value.startsWith(" ")) {
      value = value.trim();
    }
    return Ints.tryParse(value);
  }

  private ApprovalInfo approvalInfo(
      AccountLoader accountLoader,
      Account.Id id,
      @Nullable Integer value,
      @Nullable VotingRangeInfo permittedVotingRange,
      @Nullable String tag,
      @Nullable Instant date) {
    ApprovalInfo ai = new ApprovalInfo(id.get(), value, permittedVotingRange, tag, date);
    accountLoader.put(ai);
    return ai;
  }

  private void setLabelValues(LabelType type, LabelInfo l) {
    l.defaultValue = type.getDefaultValue();
    l.values = new LinkedHashMap<>();
    for (LabelValue v : type.getValues()) {
      l.values.put(v.formatValue(), v.getText());
    }
    if (isOnlyZero(l.values.keySet())) {
      l.values = null;
    }
  }

  private Map<String, Short> currentLabels(@Nullable Account.Id accountId, ChangeData cd) {
    Map<String, Short> result = new HashMap<>();
    for (PatchSetApproval psa : cd.currentApprovals()) {
      if (accountId == null || psa.accountId().equals(accountId)) {
        result.put(psa.label(), psa.value());
      }
    }
    return result;
  }

  private Map<String, LabelInfo> labelsForSubmittedChange(
      AccountLoader accountLoader,
      ChangeData cd,
      LabelTypes labelTypes,
      boolean standard,
      boolean detailed)
      throws PermissionBackendException {
    Set<Account.Id> allUsers = new HashSet<>();
    if (detailed) {
      // Users expect to see all reviewers on closed changes, even if they
      // didn't vote on the latest patch set. If we don't need detailed labels,
      // we aren't including 0 votes for all users below, so we can just look at
      // the latest patch set (in the next loop).
      for (PatchSetApproval psa : cd.approvals().values()) {
        allUsers.add(psa.accountId());
      }
    }

    SetMultimap<Account.Id, PatchSetApproval> current =
        MultimapBuilder.hashKeys().hashSetValues().build();
    for (PatchSetApproval a : cd.currentApprovals()) {
      allUsers.add(a.accountId());
      Optional<LabelType> type = labelTypes.byLabel(a.labelId());
      if (type.isPresent()) {
        // Not worth the effort to distinguish between votable/non-votable for 0
        // values on closed changes, since they can't vote anyway.
        current.put(a.accountId(), a);
      }
    }

    // Since voting on merged changes is allowed all labels which apply to
    // the change must be returned. This is calculated based on labelTypes.
    // It's not possible to only compute the labels based on the approvals
    // since merged changes may not have approvals for all labels (e.g. if not
    // all labels are required for submit or if the change was auto-closed due
    // to direct push or if new labels were defined after the change was
    // merged).
    Map<String, LabelInfo> labels = initLabels(accountLoader, cd, labelTypes, standard);

    for (Account.Id accountId : allUsers) {
      Map<String, ApprovalInfo> byLabel = Maps.newHashMapWithExpectedSize(labels.size());
      Map<String, VotingRangeInfo> pvr = Collections.emptyMap();
      if (detailed) {
        pvr = getPermittedVotingRanges(permittedLabels(accountId, cd));
      }
      for (Map.Entry<String, LabelInfo> entry : labels.entrySet()) {
        ApprovalInfo ai = approvalInfo(accountLoader, accountId, 0, null, null, null);
        byLabel.put(entry.getKey(), ai);
        addApproval(entry.getValue(), ai);
      }
      for (PatchSetApproval psa : current.get(accountId)) {
        Optional<LabelType> type = labelTypes.byLabel(psa.labelId());
        if (!type.isPresent()) {
          continue;
        }

        short val = psa.value();
        ApprovalInfo info = byLabel.get(type.get().getName());
        if (info != null) {
          info.value = Integer.valueOf(val);
          info.permittedVotingRange = pvr.getOrDefault(type.get().getName(), null);
          info.setDate(psa.granted());
          info.tag = psa.tag().orElse(null);
          if (psa.postSubmit()) {
            info.postSubmit = true;
          }
        }
        if (!standard) {
          continue;
        }

        setLabelScores(accountLoader, type.get(), labels.get(type.get().getName()), val, accountId);
      }
    }
    return labels;
  }

  private Map<String, LabelInfo> initLabels(
      AccountLoader accountLoader,
      ChangeData cd,
      LabelTypes labelTypes,
      boolean includeAccountInfo) {
    Map<String, LabelInfo> labels = new TreeMap<>(labelTypes.nameComparator());

    for (LabelType t : labelTypes.getLabelTypes()) {
      LabelFunction labelFunction = t.getFunction();
      checkState(
          labelFunction != null,
          "Unable to find the LabelFunction for label %s, change %s",
          t.getName(),
          cd.getId());

      List<PatchSetApproval> approvals = cd.currentApprovals();
      ImmutableList<PatchSetApproval> approvalsForLabel = getApprovalsForLabel(approvals, t);
      LabelFunction.LabelStatus labelStatus = labelFunction.checkNoRule(t, approvalsForLabel);

      LabelInfo labelInfo = new LabelInfo();
      if (includeAccountInfo) {
        switch (labelStatus.status()) {
          case OK:
            labelInfo.approved = accountLoader.get(labelStatus.voter());
            break;
          case REJECT:
            labelInfo.rejected = accountLoader.get(labelStatus.voter());
            labelInfo.blocking = true;
            break;
          case IMPOSSIBLE:
          case MAY:
          case NEED:
          default:
            break;
        }
      }

      labelInfo.optional = labelStatus.status() == SubmitRecord.Label.Status.MAY ? true : null;
      labelInfo.description = t.getDescription().orElse(null);
      labels.put(t.getName(), labelInfo);
    }

    return labels;
  }

  private static ImmutableList<PatchSetApproval> getApprovalsForLabel(
      List<PatchSetApproval> approvals, LabelType t) {
    return approvals.stream()
        .filter(psa -> psa.label().equals(t.getLabelId().get()))
        .collect(toImmutableList());
  }

  private void setLabelScores(
      AccountLoader accountLoader, LabelType type, LabelInfo l, short score, Account.Id accountId) {
    if (l.approved != null || l.rejected != null) {
      return;
    }

    if (type.getMin() == null || type.getMax() == null) {
      // Can't set score for unknown or misconfigured type.
      return;
    }

    if (score != 0) {
      if (score == type.getMin().getValue()) {
        l.rejected = accountLoader.get(accountId);
      } else if (score == type.getMax().getValue()) {
        l.approved = accountLoader.get(accountId);
      } else if (score < 0) {
        l.disliked = accountLoader.get(accountId);
        l.value = score;
      } else if (score > 0 && l.disliked == null) {
        l.recommended = accountLoader.get(accountId);
        l.value = score;
      }
    }
  }

  private void setAllApprovals(
      AccountLoader accountLoader, ChangeData cd, Map<String, LabelInfo> labels, boolean detailed)
      throws PermissionBackendException {
    checkState(
        !cd.change().isMerged(),
        "should not call setAllApprovals on %s change",
        ChangeUtil.status(cd.change()));

    // Include a user in the output for this label if either:
    //  - They are an explicit reviewer.
    //  - They ever voted on this change.
    Set<Account.Id> allUsers = new HashSet<>();
    allUsers.addAll(cd.reviewers().byState(ReviewerStateInternal.REVIEWER));
    for (PatchSetApproval psa : cd.approvals().values()) {
      allUsers.add(psa.accountId());
    }

    Table<Account.Id, String, PatchSetApproval> current =
        HashBasedTable.create(allUsers.size(), cd.getLabelTypes().getLabelTypes().size());
    for (PatchSetApproval psa : cd.currentApprovals()) {
      current.put(psa.accountId(), psa.label(), psa);
    }

    LabelTypes labelTypes = cd.getLabelTypes();
    for (Account.Id accountId : allUsers) {
      Map<String, VotingRangeInfo> pvr = null;
      PermissionBackend.ForChange perm = null;
      if (detailed) {
        perm = permissionBackend.absentUser(accountId).change(cd);
        pvr = getPermittedVotingRanges(permittedLabels(accountId, cd));
      }
      for (Map.Entry<String, LabelInfo> e : labels.entrySet()) {
        Optional<LabelType> lt = labelTypes.byLabel(e.getKey());
        if (!lt.isPresent()) {
          // Ignore submit record for undefined label; likely the submit rule
          // author didn't intend for the label to show up in the table.
          continue;
        }
        Integer value;
        VotingRangeInfo permittedVotingRange =
            pvr == null ? null : pvr.getOrDefault(lt.get().getName(), null);
        String tag = null;
        Instant date = null;
        PatchSetApproval psa = current.get(accountId, lt.get().getName());
        if (psa != null) {
          value = Integer.valueOf(psa.value());
          if (value == 0) {
            // This may be a dummy approval that was inserted when the reviewer
            // was added. Explicitly check whether the user can vote on this
            // label.
            value = perm != null && perm.test(new LabelPermission(lt.get())) ? 0 : null;
          }
          tag = psa.tag().orElse(null);
          date = psa.granted();
          if (psa.postSubmit()) {
            logger.atWarning().log("unexpected post-submit approval on open change: %s", psa);
          }
        } else {
          // Either the user cannot vote on this label, or they were added as a
          // reviewer but have not responded yet. Explicitly check whether the
          // user can vote on this label.
          value = perm != null && perm.test(new LabelPermission(lt.get())) ? 0 : null;
        }
        addApproval(
            e.getValue(),
            approvalInfo(accountLoader, accountId, value, permittedVotingRange, tag, date));
      }
    }
  }

  private Map<String, VotingRangeInfo> getPermittedVotingRanges(
      Map<String, Collection<String>> permittedLabels) {
    Map<String, VotingRangeInfo> permittedVotingRanges =
        Maps.newHashMapWithExpectedSize(permittedLabels.size());
    for (String label : permittedLabels.keySet()) {
      List<Integer> permittedVotingRange =
          permittedLabels.get(label).stream()
              .map(this::parseRangeValue)
              .filter(java.util.Objects::nonNull)
              .sorted()
              .collect(toList());

      if (permittedVotingRange.isEmpty()) {
        permittedVotingRanges.put(label, null);
      } else {
        int minPermittedValue = permittedVotingRange.get(0);
        int maxPermittedValue = Iterables.getLast(permittedVotingRange);
        permittedVotingRanges.put(label, new VotingRangeInfo(minPermittedValue, maxPermittedValue));
      }
    }
    return permittedVotingRanges;
  }
}
