// Copyright (C) 2013 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.git;

import static com.google.common.base.Preconditions.checkArgument;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.gerrit.common.data.LabelType;
import com.google.gerrit.common.data.LabelTypes;
import com.google.gerrit.common.data.LabelValue;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.common.data.PermissionRange;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.inject.Inject;

import java.util.Collection;
import java.util.List;

/**
 * Normalizes votes on labels according to project config and permissions.
 * <p>
 * Votes are recorded in the database for a user based on the state of the
 * project at that time: what labels are defined for the project, and what the
 * user is allowed to vote on. Both of those can change between the time a vote
 * is originally made and a later point, for example when a change is submitted.
 * This class normalizes old votes against current project configuration.
 */
public class LabelNormalizer {
  public static class Result {
    private final ImmutableList<PatchSetApproval> unchanged;
    private final ImmutableList<PatchSetApproval> updated;
    private final ImmutableList<PatchSetApproval> deleted;

    @VisibleForTesting
    Result(
        List<PatchSetApproval> unchanged,
        List<PatchSetApproval> updated,
        List<PatchSetApproval> deleted) {
      this.unchanged = ImmutableList.copyOf(unchanged);
      this.updated = ImmutableList.copyOf(updated);
      this.deleted = ImmutableList.copyOf(deleted);
    }

    public ImmutableList<PatchSetApproval> getUnchanged() {
      return unchanged;
    }

    public ImmutableList<PatchSetApproval> getUpdated() {
      return updated;
    }

    public ImmutableList<PatchSetApproval> getDeleted() {
      return deleted;
    }

    public Iterable<PatchSetApproval> getNormalized() {
      return Iterables.concat(unchanged, updated);
    }

    @Override
    public boolean equals(Object o) {
      if (o instanceof Result) {
        Result r = (Result) o;
        return Objects.equal(unchanged, r.unchanged)
            && Objects.equal(updated, r.updated)
            && Objects.equal(deleted, r.deleted);
      }
      return false;
    }

    @Override
    public int hashCode() {
      return Objects.hashCode(unchanged, updated, deleted);
    }

    @Override
    public String toString() {
      return Objects.toStringHelper(this)
          .add("unchanged", unchanged)
          .add("updated", updated)
          .add("deleted", deleted)
          .toString();
    }
  }

  private final ChangeControl.GenericFactory changeFactory;
  private final IdentifiedUser.GenericFactory userFactory;

  @Inject
  LabelNormalizer(ChangeControl.GenericFactory changeFactory,
      IdentifiedUser.GenericFactory userFactory) {
    this.changeFactory = changeFactory;
    this.userFactory = userFactory;
  }

  /**
   * @param change change containing the given approvals.
   * @param approvals list of approvals.
   * @return copies of approvals normalized to the defined ranges for the label
   *     type and permissions for the user. Approvals for unknown labels are not
   *     included in the output, nor are approvals where the user has no
   *     permissions for that label.
   * @throws NoSuchChangeException
   */
  public Result normalize(Change change,
      Collection<PatchSetApproval> approvals) throws NoSuchChangeException {
    return normalize(
        changeFactory.controlFor(change, userFactory.create(change.getOwner())),
        approvals);
  }

  /**
   * @param ctl change control containing the given approvals.
   * @param approvals list of approvals.
   * @return copies of approvals normalized to the defined ranges for the label
   *     type and permissions for the user. Approvals for unknown labels are not
   *     included in the output, nor are approvals where the user has no
   *     permissions for that label.
   */
  public Result normalize(ChangeControl ctl,
      Collection<PatchSetApproval> approvals) {
    List<PatchSetApproval> unchanged =
        Lists.newArrayListWithCapacity(approvals.size());
    List<PatchSetApproval> updated =
        Lists.newArrayListWithCapacity(approvals.size());
    List<PatchSetApproval> deleted =
        Lists.newArrayListWithCapacity(approvals.size());
    LabelTypes labelTypes = ctl.getLabelTypes();
    for (PatchSetApproval psa : approvals) {
      Change.Id changeId = psa.getKey().getParentKey().getParentKey();
      checkArgument(changeId.equals(ctl.getChange().getId()),
          "Approval %s does not match change %s",
          psa.getKey(), ctl.getChange().getKey());
      if (psa.isSubmit()) {
        unchanged.add(psa);
        continue;
      }
      LabelType label = labelTypes.byLabel(psa.getLabelId());
      if (label == null) {
        deleted.add(psa);
        continue;
      }
      PatchSetApproval copy = copy(psa);
      applyTypeFloor(label, copy);
      if (!applyRightFloor(ctl, label, copy)) {
        deleted.add(psa);
      } else if (copy.getValue() != psa.getValue()) {
        updated.add(copy);
      } else {
        unchanged.add(psa);
      }
    }
    return new Result(unchanged, updated, deleted);
  }

  /**
   * @param ctl change control (for any user).
   * @param lt label type.
   * @param id account ID.
   * @return whether the given account ID has any permissions to vote on this
   *     label for this change.
   */
  public boolean canVote(ChangeControl ctl, LabelType lt, Account.Id id) {
    return !getRange(ctl, lt, id).isEmpty();
  }

  private PatchSetApproval copy(PatchSetApproval src) {
    return new PatchSetApproval(src.getPatchSetId(), src);
  }

  private PermissionRange getRange(ChangeControl ctl, LabelType lt,
      Account.Id id) {
    String permission = Permission.forLabel(lt.getName());
    IdentifiedUser user = userFactory.create(id);
    return ctl.forUser(user).getRange(permission);
  }

  private boolean applyRightFloor(ChangeControl ctl, LabelType lt,
      PatchSetApproval a) {
    PermissionRange range = getRange(ctl, lt, a.getAccountId());
    if (range.isEmpty()) {
      return false;
    }
    a.setValue((short) range.squash(a.getValue()));
    return true;
  }

  private void applyTypeFloor(LabelType lt, PatchSetApproval a) {
    LabelValue atMin = lt.getMin();
    if (atMin != null && a.getValue() < atMin.getValue()) {
      a.setValue(atMin.getValue());
    }
    LabelValue atMax = lt.getMax();
    if (atMax != null && a.getValue() > atMax.getValue()) {
      a.setValue(atMax.getValue());
    }
  }
}
