// Copyright (C) 2016 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.acceptance.api.change;

import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.extensions.client.ChangeKind.MERGE_FIRST_PARENT_UPDATE;
import static com.google.gerrit.extensions.client.ChangeKind.NO_CHANGE;
import static com.google.gerrit.extensions.client.ChangeKind.NO_CODE_CHANGE;
import static com.google.gerrit.extensions.client.ChangeKind.REWORK;
import static com.google.gerrit.extensions.client.ChangeKind.TRIVIAL_REBASE;
import static com.google.gerrit.extensions.client.ListChangesOption.CURRENT_COMMIT;
import static com.google.gerrit.extensions.client.ListChangesOption.CURRENT_REVISION;
import static com.google.gerrit.extensions.client.ListChangesOption.DETAILED_LABELS;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import static com.google.gerrit.server.project.testing.Util.category;
import static com.google.gerrit.server.project.testing.Util.value;
import static org.eclipse.jgit.lib.Constants.HEAD;

import com.google.common.collect.ImmutableList;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.GitUtil;
import com.google.gerrit.acceptance.NoHttpd;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.common.data.LabelType;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.extensions.api.changes.CherryPickInput;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.api.changes.RevisionApi;
import com.google.gerrit.extensions.client.ChangeKind;
import com.google.gerrit.extensions.common.ApprovalInfo;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.CommitInfo;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.project.testing.Util;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.revwalk.RevCommit;
import org.junit.Before;
import org.junit.Test;

@NoHttpd
public class StickyApprovalsIT extends AbstractDaemonTest {

  @Before
  public void setup() throws Exception {
    try (ProjectConfigUpdate u = updateProject(project)) {
      // Overwrite "Code-Review" label that is inherited from All-Projects.
      // This way changes to the "Code Review" label don't affect other tests.
      LabelType codeReview =
          category(
              "Code-Review",
              value(2, "Looks good to me, approved"),
              value(1, "Looks good to me, but someone else must approve"),
              value(0, "No score"),
              value(-1, "I would prefer that you didn't submit this"),
              value(-2, "Do not submit"));
      codeReview.setCopyAllScoresIfNoChange(false);
      u.getConfig().getLabelSections().put(codeReview.getName(), codeReview);

      LabelType verified =
          category("Verified", value(1, "Passes"), value(0, "No score"), value(-1, "Failed"));
      verified.setCopyAllScoresIfNoChange(false);
      u.getConfig().getLabelSections().put(verified.getName(), verified);

      AccountGroup.UUID registeredUsers = systemGroupBackend.getGroup(REGISTERED_USERS).getUUID();
      String heads = RefNames.REFS_HEADS + "*";
      Util.allow(
          u.getConfig(),
          Permission.forLabel(Util.codeReview().getName()),
          -2,
          2,
          registeredUsers,
          heads);
      Util.allow(
          u.getConfig(),
          Permission.forLabel(Util.verified().getName()),
          -1,
          1,
          registeredUsers,
          heads);
      u.save();
    }
  }

  @Test
  public void notSticky() throws Exception {
    assertNotSticky(
        EnumSet.of(REWORK, TRIVIAL_REBASE, NO_CODE_CHANGE, MERGE_FIRST_PARENT_UPDATE, NO_CHANGE));
  }

  @Test
  public void stickyOnMinScore() throws Exception {
    try (ProjectConfigUpdate u = updateProject(project)) {
      u.getConfig().getLabelSections().get("Code-Review").setCopyMinScore(true);
      u.save();
    }

    for (ChangeKind changeKind :
        EnumSet.of(REWORK, TRIVIAL_REBASE, NO_CODE_CHANGE, MERGE_FIRST_PARENT_UPDATE, NO_CHANGE)) {
      testRepo.reset(getRemoteHead());

      String changeId = createChange(changeKind);
      vote(admin, changeId, -1, 1);
      vote(user, changeId, -2, -1);

      updateChange(changeId, changeKind);
      ChangeInfo c = detailedChange(changeId);
      assertVotes(c, admin, 0, 0, changeKind);
      assertVotes(c, user, -2, 0, changeKind);
    }
  }

  @Test
  public void stickyOnMaxScore() throws Exception {
    try (ProjectConfigUpdate u = updateProject(project)) {
      u.getConfig().getLabelSections().get("Code-Review").setCopyMaxScore(true);
      u.save();
    }

    for (ChangeKind changeKind :
        EnumSet.of(REWORK, TRIVIAL_REBASE, NO_CODE_CHANGE, MERGE_FIRST_PARENT_UPDATE, NO_CHANGE)) {
      testRepo.reset(getRemoteHead());

      String changeId = createChange(changeKind);
      vote(admin, changeId, 2, 1);
      vote(user, changeId, 1, -1);

      updateChange(changeId, changeKind);
      ChangeInfo c = detailedChange(changeId);
      assertVotes(c, admin, 2, 0, changeKind);
      assertVotes(c, user, 0, 0, changeKind);
    }
  }

  @Test
  public void stickyOnTrivialRebase() throws Exception {
    try (ProjectConfigUpdate u = updateProject(project)) {
      u.getConfig().getLabelSections().get("Code-Review").setCopyAllScoresOnTrivialRebase(true);
      u.save();
    }

    String changeId = createChange(TRIVIAL_REBASE);
    vote(admin, changeId, 2, 1);
    vote(user, changeId, -2, -1);

    updateChange(changeId, NO_CHANGE);
    ChangeInfo c = detailedChange(changeId);
    assertVotes(c, admin, 2, 0, NO_CHANGE);
    assertVotes(c, user, -2, 0, NO_CHANGE);

    updateChange(changeId, TRIVIAL_REBASE);
    c = detailedChange(changeId);
    assertVotes(c, admin, 2, 0, TRIVIAL_REBASE);
    assertVotes(c, user, -2, 0, TRIVIAL_REBASE);

    assertNotSticky(EnumSet.of(REWORK, NO_CODE_CHANGE, MERGE_FIRST_PARENT_UPDATE));

    // check that votes are sticky when trivial rebase is done by cherry-pick
    testRepo.reset(getRemoteHead());
    changeId = createChange().getChangeId();
    vote(admin, changeId, 2, 1);
    vote(user, changeId, -2, -1);

    String cherryPickChangeId = cherryPick(changeId, TRIVIAL_REBASE);
    c = detailedChange(cherryPickChangeId);
    assertVotes(c, admin, 2, 0);
    assertVotes(c, user, -2, 0);

    // check that votes are not sticky when rework is done by cherry-pick
    testRepo.reset(getRemoteHead());
    changeId = createChange().getChangeId();
    vote(admin, changeId, 2, 1);
    vote(user, changeId, -2, -1);

    cherryPickChangeId = cherryPick(changeId, REWORK);
    c = detailedChange(cherryPickChangeId);
    assertVotes(c, admin, 0, 0);
    assertVotes(c, user, 0, 0);
  }

  @Test
  public void stickyOnNoCodeChange() throws Exception {
    try (ProjectConfigUpdate u = updateProject(project)) {
      u.getConfig().getLabelSections().get("Verified").setCopyAllScoresIfNoCodeChange(true);
      u.save();
    }

    String changeId = createChange(NO_CODE_CHANGE);
    vote(admin, changeId, 2, 1);
    vote(user, changeId, -2, -1);

    updateChange(changeId, NO_CHANGE);
    ChangeInfo c = detailedChange(changeId);
    assertVotes(c, admin, 0, 1, NO_CHANGE);
    assertVotes(c, user, 0, -1, NO_CHANGE);

    updateChange(changeId, NO_CODE_CHANGE);
    c = detailedChange(changeId);
    assertVotes(c, admin, 0, 1, NO_CODE_CHANGE);
    assertVotes(c, user, 0, -1, NO_CODE_CHANGE);

    assertNotSticky(EnumSet.of(REWORK, TRIVIAL_REBASE, MERGE_FIRST_PARENT_UPDATE));
  }

  @Test
  public void stickyOnMergeFirstParentUpdate() throws Exception {
    try (ProjectConfigUpdate u = updateProject(project)) {
      u.getConfig()
          .getLabelSections()
          .get("Code-Review")
          .setCopyAllScoresOnMergeFirstParentUpdate(true);
      u.save();
    }

    String changeId = createChange(MERGE_FIRST_PARENT_UPDATE);
    vote(admin, changeId, 2, 1);
    vote(user, changeId, -2, -1);

    updateChange(changeId, NO_CHANGE);
    ChangeInfo c = detailedChange(changeId);
    assertVotes(c, admin, 2, 0, NO_CHANGE);
    assertVotes(c, user, -2, 0, NO_CHANGE);

    updateChange(changeId, MERGE_FIRST_PARENT_UPDATE);
    c = detailedChange(changeId);
    assertVotes(c, admin, 2, 0, MERGE_FIRST_PARENT_UPDATE);
    assertVotes(c, user, -2, 0, MERGE_FIRST_PARENT_UPDATE);

    assertNotSticky(EnumSet.of(REWORK, NO_CODE_CHANGE, TRIVIAL_REBASE));
  }

  @Test
  public void removedVotesNotSticky() throws Exception {
    try (ProjectConfigUpdate u = updateProject(project)) {
      u.getConfig().getLabelSections().get("Code-Review").setCopyAllScoresOnTrivialRebase(true);
      u.getConfig().getLabelSections().get("Verified").setCopyAllScoresIfNoCodeChange(true);
      u.save();
    }

    for (ChangeKind changeKind :
        EnumSet.of(REWORK, TRIVIAL_REBASE, NO_CODE_CHANGE, MERGE_FIRST_PARENT_UPDATE, NO_CHANGE)) {
      testRepo.reset(getRemoteHead());

      String changeId = createChange(changeKind);
      vote(admin, changeId, 2, 1);
      vote(user, changeId, -2, -1);

      // Remove votes by re-voting with 0
      vote(admin, changeId, 0, 0);
      vote(user, changeId, 0, 0);
      ChangeInfo c = detailedChange(changeId);
      assertVotes(c, admin, 0, 0, null);
      assertVotes(c, user, 0, 0, null);

      updateChange(changeId, changeKind);
      c = detailedChange(changeId);
      assertVotes(c, admin, 0, 0, changeKind);
      assertVotes(c, user, 0, 0, changeKind);
    }
  }

  @Test
  public void stickyAcrossMultiplePatchSets() throws Exception {
    try (ProjectConfigUpdate u = updateProject(project)) {
      u.getConfig().getLabelSections().get("Code-Review").setCopyMaxScore(true);
      u.getConfig().getLabelSections().get("Verified").setCopyAllScoresIfNoCodeChange(true);
      u.save();
    }

    String changeId = createChange(REWORK);
    vote(admin, changeId, 2, 1);

    for (int i = 0; i < 5; i++) {
      updateChange(changeId, NO_CODE_CHANGE);
      ChangeInfo c = detailedChange(changeId);
      assertVotes(c, admin, 2, 1, NO_CODE_CHANGE);
    }

    updateChange(changeId, REWORK);
    ChangeInfo c = detailedChange(changeId);
    assertVotes(c, admin, 2, 0, REWORK);
  }

  @Test
  public void copyMinMaxAcrossMultiplePatchSets() throws Exception {
    try (ProjectConfigUpdate u = updateProject(project)) {
      u.getConfig().getLabelSections().get("Code-Review").setCopyMaxScore(true);
      u.getConfig().getLabelSections().get("Code-Review").setCopyMinScore(true);
      u.save();
    }

    // Vote max score on PS1
    String changeId = createChange(REWORK);
    vote(admin, changeId, 2, 1);

    // Have someone else vote min score on PS2
    updateChange(changeId, REWORK);
    vote(user, changeId, -2, 0);
    ChangeInfo c = detailedChange(changeId);
    assertVotes(c, admin, 2, 0, REWORK);
    assertVotes(c, user, -2, 0, REWORK);

    // No vote changes on PS3
    updateChange(changeId, REWORK);
    c = detailedChange(changeId);
    assertVotes(c, admin, 2, 0, REWORK);
    assertVotes(c, user, -2, 0, REWORK);

    // Both users revote on PS4
    updateChange(changeId, REWORK);
    vote(admin, changeId, 1, 1);
    vote(user, changeId, 1, 1);
    c = detailedChange(changeId);
    assertVotes(c, admin, 1, 1, REWORK);
    assertVotes(c, user, 1, 1, REWORK);

    // New approvals shouldn't carry through to PS5
    updateChange(changeId, REWORK);
    c = detailedChange(changeId);
    assertVotes(c, admin, 0, 0, REWORK);
    assertVotes(c, user, 0, 0, REWORK);
  }

  @Test
  public void deleteStickyVote() throws Exception {
    String label = "Code-Review";
    try (ProjectConfigUpdate u = updateProject(project)) {
      u.getConfig().getLabelSections().get(label).setCopyMaxScore(true);
      u.save();
    }

    // Vote max score on PS1
    String changeId = createChange(REWORK);
    vote(admin, changeId, label, 2);
    assertVotes(detailedChange(changeId), admin, label, 2, null);
    updateChange(changeId, REWORK);
    assertVotes(detailedChange(changeId), admin, label, 2, REWORK);

    // Delete vote that was copied via sticky approval
    deleteVote(admin, changeId, "Code-Review");
    assertVotes(detailedChange(changeId), admin, label, 0, REWORK);
  }

  private ChangeInfo detailedChange(String changeId) throws Exception {
    return gApi.changes().id(changeId).get(DETAILED_LABELS, CURRENT_REVISION, CURRENT_COMMIT);
  }

  private void assertNotSticky(Set<ChangeKind> changeKinds) throws Exception {
    for (ChangeKind changeKind : changeKinds) {
      testRepo.reset(getRemoteHead());

      String changeId = createChange(changeKind);
      vote(admin, changeId, +2, 1);
      vote(user, changeId, -2, -1);

      updateChange(changeId, changeKind);
      ChangeInfo c = detailedChange(changeId);
      assertVotes(c, admin, 0, 0, changeKind);
      assertVotes(c, user, 0, 0, changeKind);
    }
  }

  private String createChange(ChangeKind kind) throws Exception {
    switch (kind) {
      case NO_CODE_CHANGE:
      case REWORK:
      case TRIVIAL_REBASE:
      case NO_CHANGE:
        return createChange().getChangeId();
      case MERGE_FIRST_PARENT_UPDATE:
        return createChangeForMergeCommit();
      default:
        throw new IllegalStateException("unexpected change kind: " + kind);
    }
  }

  private void updateChange(String changeId, ChangeKind changeKind) throws Exception {
    switch (changeKind) {
      case NO_CODE_CHANGE:
        noCodeChange(changeId);
        return;
      case REWORK:
        rework(changeId);
        return;
      case TRIVIAL_REBASE:
        trivialRebase(changeId);
        return;
      case MERGE_FIRST_PARENT_UPDATE:
        updateFirstParent(changeId);
        return;
      case NO_CHANGE:
        noChange(changeId);
        return;
      default:
        fail("unexpected change kind: " + changeKind);
    }
  }

  private void noCodeChange(String changeId) throws Exception {
    TestRepository<?>.CommitBuilder commitBuilder =
        testRepo.amendRef("HEAD").insertChangeId(changeId.substring(1));
    commitBuilder
        .message("New subject " + System.nanoTime())
        .author(admin.getIdent())
        .committer(new PersonIdent(admin.getIdent(), testRepo.getDate()));
    commitBuilder.create();
    GitUtil.pushHead(testRepo, "refs/for/master", false);
    assertThat(getChangeKind(changeId)).isEqualTo(NO_CODE_CHANGE);
  }

  private void noChange(String changeId) throws Exception {
    ChangeInfo change = gApi.changes().id(changeId).get();
    String commitMessage = change.revisions.get(change.currentRevision).commit.message;

    TestRepository<?>.CommitBuilder commitBuilder =
        testRepo.amendRef("HEAD").insertChangeId(changeId.substring(1));
    commitBuilder
        .message(commitMessage)
        .author(admin.getIdent())
        .committer(new PersonIdent(admin.getIdent(), testRepo.getDate()));
    commitBuilder.create();
    GitUtil.pushHead(testRepo, "refs/for/master", false);
    assertThat(getChangeKind(changeId)).isEqualTo(NO_CHANGE);
  }

  private void rework(String changeId) throws Exception {
    PushOneCommit push =
        pushFactory.create(
            db,
            admin.getIdent(),
            testRepo,
            PushOneCommit.SUBJECT,
            PushOneCommit.FILE_NAME,
            "new content " + System.nanoTime(),
            changeId);
    push.to("refs/for/master").assertOkStatus();
    assertThat(getChangeKind(changeId)).isEqualTo(REWORK);
  }

  private void trivialRebase(String changeId) throws Exception {
    setApiUser(admin);
    testRepo.reset(getRemoteHead());
    PushOneCommit push =
        pushFactory.create(
            db,
            admin.getIdent(),
            testRepo,
            "Other Change",
            "a" + System.nanoTime() + ".txt",
            PushOneCommit.FILE_CONTENT);
    PushOneCommit.Result r = push.to("refs/for/master");
    r.assertOkStatus();
    RevisionApi revision = gApi.changes().id(r.getChangeId()).current();
    ReviewInput in = new ReviewInput().label("Code-Review", 2).label("Verified", 1);
    revision.review(in);
    revision.submit();

    gApi.changes().id(changeId).current().rebase();
    assertThat(getChangeKind(changeId)).isEqualTo(TRIVIAL_REBASE);
  }

  private String createChangeForMergeCommit() throws Exception {
    ObjectId initial = repo().exactRef(HEAD).getLeaf().getObjectId();

    PushOneCommit.Result parent1 = createChange("parent 1", "p1.txt", "content 1");

    testRepo.reset(initial);
    PushOneCommit.Result parent2 = createChange("parent 2", "p2.txt", "content 2");

    testRepo.reset(parent1.getCommit());

    PushOneCommit merge = pushFactory.create(db, admin.getIdent(), testRepo);
    merge.setParents(ImmutableList.of(parent1.getCommit(), parent2.getCommit()));
    PushOneCommit.Result result = merge.to("refs/for/master");
    result.assertOkStatus();
    return result.getChangeId();
  }

  private void updateFirstParent(String changeId) throws Exception {
    ChangeInfo c = detailedChange(changeId);
    List<CommitInfo> parents = c.revisions.get(c.currentRevision).commit.parents;
    String parent1 = parents.get(0).commit;
    String parent2 = parents.get(1).commit;
    RevCommit commitParent2 = testRepo.getRevWalk().parseCommit(ObjectId.fromString(parent2));

    testRepo.reset(parent1);
    PushOneCommit.Result newParent1 = createChange("new parent 1", "p1-1.txt", "content 1-1");

    PushOneCommit merge = pushFactory.create(db, admin.getIdent(), testRepo, changeId);
    merge.setParents(ImmutableList.of(newParent1.getCommit(), commitParent2));
    PushOneCommit.Result result = merge.to("refs/for/master");
    result.assertOkStatus();

    assertThat(getChangeKind(changeId)).isEqualTo(MERGE_FIRST_PARENT_UPDATE);
  }

  private String cherryPick(String changeId, ChangeKind changeKind) throws Exception {
    switch (changeKind) {
      case REWORK:
      case TRIVIAL_REBASE:
        break;
      case NO_CODE_CHANGE:
      case NO_CHANGE:
      case MERGE_FIRST_PARENT_UPDATE:
      default:
        fail("unexpected change kind: " + changeKind);
    }

    testRepo.reset(getRemoteHead());
    PushOneCommit.Result r =
        pushFactory
            .create(
                db,
                admin.getIdent(),
                testRepo,
                PushOneCommit.SUBJECT,
                "other.txt",
                "new content " + System.nanoTime())
            .to("refs/for/master");
    r.assertOkStatus();
    vote(admin, r.getChangeId(), 2, 1);
    merge(r);

    String subject =
        TRIVIAL_REBASE.equals(changeKind)
            ? PushOneCommit.SUBJECT
            : "Reworked change " + System.nanoTime();
    CherryPickInput in = new CherryPickInput();
    in.destination = "master";
    in.message = String.format("%s\n\nChange-Id: %s", subject, changeId);
    ChangeInfo c = gApi.changes().id(changeId).revision("current").cherryPick(in).get();
    return c.changeId;
  }

  private ChangeKind getChangeKind(String changeId) throws Exception {
    ChangeInfo c = gApi.changes().id(changeId).get(CURRENT_REVISION);
    return c.revisions.get(c.currentRevision).kind;
  }

  private void vote(TestAccount user, String changeId, String label, int vote) throws Exception {
    setApiUser(user);
    gApi.changes().id(changeId).current().review(new ReviewInput().label(label, vote));
  }

  private void vote(TestAccount user, String changeId, int codeReviewVote, int verifiedVote)
      throws Exception {
    setApiUser(user);
    ReviewInput in =
        new ReviewInput().label("Code-Review", codeReviewVote).label("Verified", verifiedVote);
    gApi.changes().id(changeId).current().review(in);
  }

  private void deleteVote(TestAccount user, String changeId, String label) throws Exception {
    setApiUser(user);
    gApi.changes().id(changeId).reviewer(user.getId().toString()).deleteVote(label);
  }

  private void assertVotes(ChangeInfo c, TestAccount user, int codeReviewVote, int verifiedVote) {
    assertVotes(c, user, codeReviewVote, verifiedVote, null);
  }

  private void assertVotes(
      ChangeInfo c, TestAccount user, int codeReviewVote, int verifiedVote, ChangeKind changeKind) {
    assertVotes(c, user, "Code-Review", codeReviewVote, changeKind);
    assertVotes(c, user, "Verified", verifiedVote, changeKind);
  }

  private void assertVotes(
      ChangeInfo c, TestAccount user, String label, int expectedVote, ChangeKind changeKind) {
    Integer vote = 0;
    if (c.labels.get(label) != null && c.labels.get(label).all != null) {
      for (ApprovalInfo approval : c.labels.get(label).all) {
        if (approval._accountId == user.id.get()) {
          vote = approval.value;
          break;
        }
      }
    }

    String name = "label = " + label;
    if (changeKind != null) {
      name += "; changeKind = " + changeKind.name();
    }
    assertThat(vote).named(name).isEqualTo(expectedVote);
  }
}
