// 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.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.account.AccountLoader;
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.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;

  @Inject
  LabelsJson(PermissionBackend permissionBackend) {
    this.permissionBackend = permissionBackend;
  }

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

    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 {
    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();
  }

  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, standard);
    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) {
        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(Account.Id accountId, ChangeData cd) {
    Map<String, Short> result = new HashMap<>();
    for (PatchSetApproval psa : cd.currentApprovals()) {
      if (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 standard) {
    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 (standard) {
            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();
  }
}
