// 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 java.util.stream.Collectors.toList;

import com.google.auto.value.AutoValue;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.ImmutableMap;
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.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.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;

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

  /**
   * 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 {
    if (!standard && !detailed) {
      return null;
    }

    try (TraceTimer timer =
        TraceContext.newTimer(
            "Get labels", Metadata.builder().changeId(cd.change().getId().get()).build())) {
      LabelTypes labelTypes = cd.getLabelTypes();
      Map<String, LabelWithStatus> withStatus =
          cd.change().isMerged()
              ? labelsForSubmittedChange(accountLoader, cd, labelTypes, standard, detailed)
              : labelsForUnsubmittedChange(accountLoader, cd, labelTypes, standard, detailed);
      return ImmutableMap.copyOf(Maps.transformValues(withStatus, LabelWithStatus::label));
    }
  }

  /**
   * 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 (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, LabelWithStatus> labelsForUnsubmittedChange(
      AccountLoader accountLoader,
      ChangeData cd,
      LabelTypes labelTypes,
      boolean standard,
      boolean detailed)
      throws PermissionBackendException {
    Map<String, LabelWithStatus> labels =
        initLabels(accountLoader, cd, labelTypes, /*includeAccountInfo=*/ standard || detailed);
    setAllApprovals(accountLoader, cd, labels, detailed);

    for (Map.Entry<String, LabelWithStatus> 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, LabelWithStatus l) {
    l.label().defaultValue = type.getDefaultValue();
    l.label().values = new LinkedHashMap<>();
    for (LabelValue v : type.getValues()) {
      l.label().values.put(v.formatValue(), v.getText());
    }
    if (isOnlyZero(l.label().values.keySet())) {
      l.label().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, LabelWithStatus> 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());
      }
    }

    Set<String> labelNames = new HashSet<>();
    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()) {
        labelNames.add(type.get().getName());
        // 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. All applying labels can be retrieved from
    // the submit records, which is what initLabels does.
    // 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, LabelWithStatus> labels;
    labels = initLabels(accountLoader, cd, labelTypes, standard);

    // Also include all labels for which approvals exists. E.g. there can be
    // approvals for labels that are ignored by a Prolog submit rule and hence
    // it wouldn't be included in the submit records.
    for (String name : labelNames) {
      if (!labels.containsKey(name)) {
        labels.put(name, LabelWithStatus.create(new LabelInfo(), null));
      }
    }

    labels.entrySet().stream()
        .filter(e -> labelTypes.byLabel(e.getKey()).isPresent())
        .forEach(e -> setLabelValues(labelTypes.byLabel(e.getKey()).get(), e.getValue()));

    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, LabelWithStatus> entry : labels.entrySet()) {
        ApprovalInfo ai = approvalInfo(accountLoader, accountId, 0, null, null, null);
        byLabel.put(entry.getKey(), ai);
        addApproval(entry.getValue().label(), 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, LabelWithStatus> initLabels(
      AccountLoader accountLoader,
      ChangeData cd,
      LabelTypes labelTypes,
      boolean includeAccountInfo) {
    Map<String, LabelWithStatus> labels = new TreeMap<>(labelTypes.nameComparator());
    for (SubmitRecord rec : submitRecords(cd)) {
      if (rec.labels == null) {
        continue;
      }
      for (SubmitRecord.Label r : rec.labels) {
        LabelWithStatus p = labels.get(r.label);
        if (p == null || p.status().compareTo(r.status) < 0) {
          LabelInfo n = new LabelInfo();
          if (includeAccountInfo) {
            switch (r.status) {
              case OK:
                n.approved = accountLoader.get(r.appliedBy);
                break;
              case REJECT:
                n.rejected = accountLoader.get(r.appliedBy);
                n.blocking = true;
                break;
              case IMPOSSIBLE:
              case MAY:
              case NEED:
              default:
                break;
            }
          }

          n.optional = r.status == SubmitRecord.Label.Status.MAY ? true : null;
          labels.put(r.label, LabelWithStatus.create(n, r.status));
        }
      }
    }
    setLabelsDescription(labels, labelTypes);
    return labels;
  }

  private void setLabelsDescription(
      Map<String, LabelsJson.LabelWithStatus> labels, LabelTypes labelTypes) {
    for (Map.Entry<String, LabelWithStatus> entry : labels.entrySet()) {
      String labelName = entry.getKey();
      Optional<LabelType> type = labelTypes.byLabel(labelName);
      if (!type.isPresent()) {
        continue;
      }
      LabelWithStatus labelWithStatus = entry.getValue();
      labelWithStatus.label().description = type.get().getDescription().orElse(null);
    }
  }

  private void setLabelScores(
      AccountLoader accountLoader,
      LabelType type,
      LabelWithStatus l,
      short score,
      Account.Id accountId) {
    if (l.label().approved != null || l.label().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.label().rejected = accountLoader.get(accountId);
      } else if (score == type.getMax().getValue()) {
        l.label().approved = accountLoader.get(accountId);
      } else if (score < 0) {
        l.label().disliked = accountLoader.get(accountId);
        l.label().value = score;
      } else if (score > 0 && l.label().disliked == null) {
        l.label().recommended = accountLoader.get(accountId);
        l.label().value = score;
      }
    }
  }

  private void setAllApprovals(
      AccountLoader accountLoader,
      ChangeData cd,
      Map<String, LabelWithStatus> 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, LabelWithStatus> 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().label(),
            approvalInfo(accountLoader, accountId, value, permittedVotingRange, tag, date));
      }
    }
  }

  private List<SubmitRecord> submitRecords(ChangeData cd) {
    return cd.submitRecords(ChangeJson.SUBMIT_RULE_OPTIONS_LENIENT);
  }

  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;
  }

  @AutoValue
  abstract static class LabelWithStatus {
    private static LabelWithStatus create(LabelInfo label, SubmitRecord.Label.Status status) {
      return new AutoValue_LabelsJson_LabelWithStatus(label, status);
    }

    abstract LabelInfo label();

    @Nullable
    abstract SubmitRecord.Label.Status status();
  }
}
