// Copyright (C) 2014 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.server.project;

import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.common.data.LabelFunction.ANY_WITH_BLOCK;
import static com.google.gerrit.common.data.LabelFunction.MAX_NO_BLOCK;
import static com.google.gerrit.common.data.LabelFunction.MAX_WITH_BLOCK;
import static com.google.gerrit.common.data.LabelFunction.NO_BLOCK;
import static com.google.gerrit.common.data.LabelFunction.NO_OP;
import static com.google.gerrit.extensions.client.ListChangesOption.DETAILED_LABELS;
import static com.google.gerrit.extensions.client.ListChangesOption.LABELS;
import static com.google.gerrit.extensions.client.ListChangesOption.SUBMITTABLE;
import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
import static com.google.gerrit.server.project.testing.Util.category;
import static com.google.gerrit.server.project.testing.Util.value;

import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.NoHttpd;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.common.data.LabelFunction;
import com.google.gerrit.common.data.LabelType;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.extensions.api.changes.AddReviewerInput;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.LabelInfo;
import com.google.gerrit.extensions.events.CommentAddedListener;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.extensions.registration.RegistrationHandle;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.gerrit.server.project.ProjectConfig;
import com.google.gerrit.server.project.testing.Util;
import com.google.inject.Inject;
import java.util.Arrays;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

@NoHttpd
public class CustomLabelIT extends AbstractDaemonTest {

  @Inject private DynamicSet<CommentAddedListener> source;

  private final LabelType label =
      category("CustomLabel", value(1, "Positive"), value(0, "No score"), value(-1, "Negative"));

  private final LabelType P = category("CustomLabel2", value(1, "Positive"), value(0, "No score"));

  private RegistrationHandle eventListenerRegistration;
  private CommentAddedListener.Event lastCommentAddedEvent;

  @Before
  public void setUp() throws Exception {
    try (ProjectConfigUpdate u = updateProject(project)) {
      AccountGroup.UUID anonymousUsers = systemGroupBackend.getGroup(ANONYMOUS_USERS).getUUID();
      Util.allow(
          u.getConfig(),
          Permission.forLabel(label.getName()),
          -1,
          1,
          anonymousUsers,
          "refs/heads/*");
      Util.allow(
          u.getConfig(), Permission.forLabel(P.getName()), 0, 1, anonymousUsers, "refs/heads/*");
      u.save();
    }

    eventListenerRegistration = source.add("gerrit", event -> lastCommentAddedEvent = event);
  }

  @After
  public void cleanup() {
    eventListenerRegistration.remove();
  }

  @Test
  public void customLabelNoOp_NegativeVoteNotBlock() throws Exception {
    label.setFunction(NO_OP);
    saveLabelConfig();
    PushOneCommit.Result r = createChange();
    revision(r).review(new ReviewInput().label(label.getName(), -1));
    ChangeInfo c = getWithLabels(r);
    LabelInfo q = c.labels.get(label.getName());
    assertThat(q.all).hasSize(1);
    assertThat(q.approved).isNull();
    assertThat(q.recommended).isNull();
    assertThat(q.disliked).isNull();
    assertThat(q.rejected).isNotNull();
    assertThat(q.blocking).isNull();
  }

  @Test
  public void customLabelNoBlock_NegativeVoteNotBlock() throws Exception {
    label.setFunction(NO_BLOCK);
    saveLabelConfig();
    PushOneCommit.Result r = createChange();
    revision(r).review(new ReviewInput().label(label.getName(), -1));
    ChangeInfo c = getWithLabels(r);
    LabelInfo q = c.labels.get(label.getName());
    assertThat(q.all).hasSize(1);
    assertThat(q.approved).isNull();
    assertThat(q.recommended).isNull();
    assertThat(q.disliked).isNull();
    assertThat(q.rejected).isNotNull();
    assertThat(q.blocking).isNull();
  }

  @Test
  public void customLabelMaxNoBlock_NegativeVoteNotBlock() throws Exception {
    label.setFunction(MAX_NO_BLOCK);
    saveLabelConfig();
    PushOneCommit.Result r = createChange();
    revision(r).review(new ReviewInput().label(label.getName(), -1));
    ChangeInfo c = getWithLabels(r);
    LabelInfo q = c.labels.get(label.getName());
    assertThat(q.all).hasSize(1);
    assertThat(q.approved).isNull();
    assertThat(q.recommended).isNull();
    assertThat(q.disliked).isNull();
    assertThat(q.rejected).isNotNull();
    assertThat(q.blocking).isNull();
  }

  @Test
  public void customLabelMaxNoBlock_MaxVoteSubmittable() throws Exception {
    label.setFunction(MAX_NO_BLOCK);
    P.setFunction(NO_OP);
    saveLabelConfig();
    PushOneCommit.Result r = createChange();
    assertThat(info(r.getChangeId()).submittable).isNull();
    revision(r).review(ReviewInput.approve().label(label.getName(), 1));

    ChangeInfo c = getWithLabels(r);
    assertThat(c.submittable).isTrue();
    LabelInfo q = c.labels.get(label.getName());
    assertThat(q.all).hasSize(1);
    assertThat(q.approved).isNotNull();
    assertThat(q.recommended).isNull();
    assertThat(q.disliked).isNull();
    assertThat(q.rejected).isNull();
    assertThat(q.blocking).isNull();
  }

  @Test
  public void customLabelAnyWithBlock_NegativeVoteBlock() throws Exception {
    label.setFunction(ANY_WITH_BLOCK);
    saveLabelConfig();
    PushOneCommit.Result r = createChange();
    revision(r).review(new ReviewInput().label(label.getName(), -1));
    ChangeInfo c = getWithLabels(r);
    LabelInfo q = c.labels.get(label.getName());
    assertThat(q.all).hasSize(1);
    assertThat(q.approved).isNull();
    assertThat(q.recommended).isNull();
    assertThat(q.disliked).isNull();
    assertThat(q.rejected).isNotNull();
    assertThat(q.blocking).isTrue();
  }

  @Test
  public void customLabelAnyWithBlock_Addreviewer_ZeroVote() throws Exception {
    P.setFunction(ANY_WITH_BLOCK);
    saveLabelConfig();
    PushOneCommit.Result r = createChange();
    AddReviewerInput in = new AddReviewerInput();
    in.reviewer = user.email();
    gApi.changes().id(r.getChangeId()).addReviewer(in);

    ReviewInput input = new ReviewInput().label(P.getName(), 0);
    input.message = "foo";

    revision(r).review(input);
    ChangeInfo c = getWithLabels(r);
    LabelInfo q = c.labels.get(P.getName());
    assertThat(q.all).hasSize(2);
    assertThat(q.approved).isNull();
    assertThat(q.recommended).isNull();
    assertThat(q.disliked).isNull();
    assertThat(q.rejected).isNull();
    assertThat(q.blocking).isNull();
    assertThat(lastCommentAddedEvent.getComment()).isEqualTo("Patch Set 1:\n\n" + input.message);
  }

  @Test
  public void customLabelMaxWithBlock_NegativeVoteBlock() throws Exception {
    label.setFunction(MAX_WITH_BLOCK);
    saveLabelConfig();
    PushOneCommit.Result r = createChange();
    revision(r).review(new ReviewInput().label(label.getName(), -1));
    ChangeInfo c = getWithLabels(r);
    LabelInfo q = c.labels.get(label.getName());
    assertThat(q.all).hasSize(1);
    assertThat(q.approved).isNull();
    assertThat(q.recommended).isNull();
    assertThat(q.disliked).isNull();
    assertThat(q.rejected).isNotNull();
    assertThat(q.blocking).isTrue();
  }

  @Test
  public void customLabelMaxWithBlock_MaxVoteSubmittable() throws Exception {
    label.setFunction(MAX_WITH_BLOCK);
    P.setFunction(NO_OP);
    saveLabelConfig();
    PushOneCommit.Result r = createChange();
    assertThat(info(r.getChangeId()).submittable).isNull();
    revision(r).review(ReviewInput.approve().label(label.getName(), 1));

    ChangeInfo c = getWithLabels(r);
    assertThat(c.submittable).isTrue();
    LabelInfo q = c.labels.get(label.getName());
    assertThat(q.all).hasSize(1);
    assertThat(q.approved).isNotNull();
    assertThat(q.recommended).isNull();
    assertThat(q.disliked).isNull();
    assertThat(q.rejected).isNull();
    assertThat(q.blocking).isNull();
  }

  @Test
  public void customLabelMaxWithBlock_MaxVoteNegativeVoteBlock() throws Exception {
    label.setFunction(MAX_WITH_BLOCK);
    saveLabelConfig();
    PushOneCommit.Result r = createChange();
    revision(r).review(new ReviewInput().label(label.getName(), 1));
    revision(r).review(new ReviewInput().label(label.getName(), -1));
    ChangeInfo c = getWithLabels(r);
    LabelInfo q = c.labels.get(label.getName());
    assertThat(q.all).hasSize(1);
    assertThat(q.approved).isNull();
    assertThat(q.recommended).isNull();
    assertThat(q.disliked).isNull();
    assertThat(q.rejected).isNotNull();
    assertThat(q.blocking).isTrue();
  }

  @Test
  public void customLabel_DisallowPostSubmit() throws Exception {
    label.setFunction(NO_OP);
    label.setAllowPostSubmit(false);
    P.setFunction(NO_OP);
    saveLabelConfig();

    PushOneCommit.Result r = createChange();
    revision(r).review(ReviewInput.approve());
    revision(r).submit();

    ChangeInfo info = getWithLabels(r);
    assertPermitted(info, "Code-Review", 2);
    assertPermitted(info, P.getName(), 0, 1);
    assertPermitted(info, label.getName());

    ReviewInput in = new ReviewInput();
    in.label(P.getName(), P.getMax().getValue());
    revision(r).review(in);

    in = new ReviewInput();
    in.label(label.getName(), label.getMax().getValue());
    exception.expect(ResourceConflictException.class);
    exception.expectMessage("Voting on labels disallowed after submit: " + label.getName());
    revision(r).review(in);
  }

  @Test
  public void customLabelWithUserPermissionChange() throws Exception {
    String testLabel = "Test-Label";
    configLabel(
        project,
        testLabel,
        LabelFunction.MAX_WITH_BLOCK,
        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 this is not merged as is"),
        value(-2, "This shall not be merged"));

    AccountGroup.UUID registered = SystemGroupBackend.REGISTERED_USERS;
    try (ProjectConfigUpdate u = updateProject(project)) {
      Util.allow(u.getConfig(), Permission.forLabel(testLabel), -2, +2, registered, "refs/heads/*");
      u.save();
    }

    PushOneCommit.Result result = createChange();
    String changeId = result.getChangeId();

    // admin votes 'Test-Label +2' and 'Code-Review +2'.
    ReviewInput input = new ReviewInput();
    input.label(testLabel, 2);
    input.label("Code-Review", 2);
    revision(result).review(input);

    // Verify the value of 'Test-Label' is +2.
    assertLabelStatus(changeId, testLabel);

    // The change is submittable.
    assertThat(gApi.changes().id(changeId).get().submittable).isTrue();

    // Update admin's permitted range for 'Test-Label' to be -1...+1.
    try (ProjectConfigUpdate u = updateProject(project)) {
      Util.remove(u.getConfig(), Permission.forLabel(testLabel), registered, "refs/heads/*");
      Util.allow(u.getConfig(), Permission.forLabel(testLabel), -1, +1, registered, "refs/heads/*");
      u.save();
    }

    // Verify admin doesn't have +2 permission any more.
    assertPermitted(gApi.changes().id(changeId).get(), testLabel, -1, 0, 1);

    // Verify the value of 'Test-Label' is still +2.
    assertLabelStatus(changeId, testLabel);

    // Verify the change is still submittable.
    assertThat(gApi.changes().id(changeId).get().submittable).isTrue();
    gApi.changes().id(changeId).current().submit();
  }

  @Test
  public void customLabel_withBranch() throws Exception {
    label.setRefPatterns(Arrays.asList("master"));
    saveLabelConfig();
    ProjectConfig cfg = projectCache.checkedGet(project).getConfig();
    assertThat(cfg.getLabelSections().get(label.getName()).getRefPatterns()).contains("master");
  }

  private void assertLabelStatus(String changeId, String testLabel) throws Exception {
    ChangeInfo changeInfo = getWithLabels(changeId);
    LabelInfo labelInfo = changeInfo.labels.get(testLabel);
    assertThat(labelInfo.all).hasSize(1);
    assertThat(labelInfo.approved).isNotNull();
    assertThat(labelInfo.recommended).isNull();
    assertThat(labelInfo.disliked).isNull();
    assertThat(labelInfo.rejected).isNull();
    assertThat(labelInfo.blocking).isNull();
  }

  private void saveLabelConfig() throws Exception {
    try (ProjectConfigUpdate u = updateProject(project)) {
      u.getConfig().getLabelSections().put(label.getName(), label);
      u.getConfig().getLabelSections().put(P.getName(), P);
      u.save();
    }
  }

  private ChangeInfo getWithLabels(PushOneCommit.Result r) throws Exception {
    return getWithLabels(r.getChangeId());
  }

  private ChangeInfo getWithLabels(String changeId) throws Exception {
    return get(changeId, LABELS, DETAILED_LABELS, SUBMITTABLE);
  }
}
