// Copyright (C) 2020 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.testsuite.change;

import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.permissionKey;
import static com.google.gerrit.extensions.common.testing.CommitInfoSubject.assertThat;
import static com.google.gerrit.extensions.common.testing.CommitInfoSubject.hasCommit;
import static com.google.gerrit.extensions.restapi.testing.BinaryResultSubject.assertThat;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import static com.google.gerrit.truth.MapSubject.assertThatMap;

import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.testsuite.account.AccountOperations;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Permission;
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.client.ChangeKind;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.CommitInfo;
import com.google.gerrit.extensions.common.FileInfo;
import com.google.gerrit.extensions.common.RevisionInfo;
import com.google.gerrit.extensions.restapi.BinaryResult;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.inject.Inject;
import java.util.Map;
import org.eclipse.jgit.lib.ObjectId;
import org.junit.Test;

public class ChangeOperationsImplTest extends AbstractDaemonTest {

  @Inject private ChangeOperations changeOperations;
  @Inject private ProjectOperations projectOperations;
  @Inject private AccountOperations accountOperations;
  @Inject private RequestScopeOperations requestScopeOperations;

  @Test
  public void changeCanBeCreatedWithoutSpecifyingAnyParameters() throws Exception {
    Change.Id numericChangeId = changeOperations.newChange().create();

    ChangeInfo change = getChangeFromServer(numericChangeId);
    assertThat(change._number).isEqualTo(numericChangeId.get());
    assertThat(change.changeId).isNotEmpty();
  }

  @Test
  public void changeCanBeCreatedEvenWithRequestScopeOfArbitraryUser() throws Exception {
    Account.Id user = accountOperations.newAccount().create();

    requestScopeOperations.setApiUser(user);
    Change.Id numericChangeId = changeOperations.newChange().create();

    ChangeInfo change = getChangeFromServer(numericChangeId);
    assertThat(change._number).isEqualTo(numericChangeId.get());
  }

  @Test
  public void twoChangesWithoutAnyParametersDoNotClash() {
    Change.Id changeId1 = changeOperations.newChange().create();
    Change.Id changeId2 = changeOperations.newChange().create();

    TestChange change1 = changeOperations.change(changeId1).get();
    TestChange change2 = changeOperations.change(changeId2).get();
    assertThat(change1.numericChangeId()).isNotEqualTo(change2.numericChangeId());
    assertThat(change1.changeId()).isNotEqualTo(change2.changeId());
  }

  @Test
  public void twoSubsequentlyCreatedChangesDoNotDependOnEachOther() throws Exception {
    Change.Id changeId1 = changeOperations.newChange().create();
    Change.Id changeId2 = changeOperations.newChange().create();

    ChangeInfo change1 = getChangeFromServer(changeId1);
    ChangeInfo change2 = getChangeFromServer(changeId2);
    CommitInfo currentPatchsetCommit1 = change1.revisions.get(change1.currentRevision).commit;
    CommitInfo currentPatchsetCommit2 = change2.revisions.get(change2.currentRevision).commit;
    assertThat(currentPatchsetCommit1)
        .parents()
        .comparingElementsUsing(hasCommit())
        .doesNotContain(currentPatchsetCommit2.commit);
    assertThat(currentPatchsetCommit2)
        .parents()
        .comparingElementsUsing(hasCommit())
        .doesNotContain(currentPatchsetCommit1.commit);
  }

  @Test
  public void createdChangeHasAtLeastOnePatchset() throws Exception {
    Change.Id changeId = changeOperations.newChange().create();

    ChangeInfo change = getChangeFromServer(changeId);
    assertThatMap(change.revisions).size().isAtLeast(1);
  }

  @Test
  public void createdChangeIsInSpecifiedProject() throws Exception {
    Project.NameKey project = projectOperations.newProject().create();
    Change.Id changeId = changeOperations.newChange().project(project).create();

    ChangeInfo change = getChangeFromServer(changeId);
    assertThat(change.project).isEqualTo(project.get());
  }

  @Test
  public void changeCanBeCreatedInEmptyRepository() throws Exception {
    Project.NameKey project = projectOperations.newProject().noEmptyCommit().create();
    Change.Id changeId = changeOperations.newChange().project(project).create();

    ChangeInfo change = getChangeFromServer(changeId);
    assertThat(change.project).isEqualTo(project.get());
  }

  @Test
  public void createdChangeHasSpecifiedTargetBranch() throws Exception {
    Project.NameKey project = projectOperations.newProject().branches("test-branch").create();
    Change.Id changeId =
        changeOperations.newChange().project(project).branch("test-branch").create();

    ChangeInfo change = getChangeFromServer(changeId);
    assertThat(change.branch).isEqualTo("test-branch");
  }

  @Test
  public void createdChangeUsesTipOfTargetBranchAsParentByDefault() throws Exception {
    Project.NameKey project = projectOperations.newProject().branches("test-branch").create();
    ObjectId parentCommitId = projectOperations.project(project).getHead("test-branch").getId();
    Change.Id changeId =
        changeOperations.newChange().project(project).branch("test-branch").create();

    ChangeInfo change = getChangeFromServer(changeId);
    CommitInfo currentPatchsetCommit = change.revisions.get(change.currentRevision).commit;
    assertThat(currentPatchsetCommit)
        .parents()
        .onlyElement()
        .commit()
        .isEqualTo(parentCommitId.getName());
  }

  @Test
  public void createdChangeHasSpecifiedOwner() throws Exception {
    Account.Id changeOwner = accountOperations.newAccount().create();
    Change.Id changeId = changeOperations.newChange().owner(changeOwner).create();

    ChangeInfo change = getChangeFromServer(changeId);
    assertThat(change.owner._accountId).isEqualTo(changeOwner.get());
  }

  @Test
  public void changeOwnerDoesNotNeedAnyPermissionsForChangeCreation() throws Exception {
    Account.Id changeOwner = accountOperations.newAccount().create();
    Project.NameKey project = projectOperations.newProject().branches("test-branch").create();
    // Remove any read and push permissions which might potentially exist. Without read, users
    // shouldn't be able to do anything. The newly created project should only inherit from
    // All-Projects.
    projectOperations
        .project(project)
        .forUpdate()
        .remove(permissionKey(Permission.READ).ref("refs/heads/test-branch"))
        .remove(permissionKey(Permission.PUSH).ref("refs/heads/test-branch"))
        .update();
    projectOperations
        .allProjectsForUpdate()
        .remove(permissionKey(Permission.READ).ref("refs/heads/test-branch"))
        .remove(permissionKey(Permission.PUSH).ref("refs/heads/test-branch"))
        .update();

    Change.Id changeId =
        changeOperations
            .newChange()
            .owner(changeOwner)
            .branch("test-branch")
            .project(project)
            .create();

    ChangeInfo change = getChangeFromServer(changeId);
    assertThat(change.owner._accountId).isEqualTo(changeOwner.get());
  }

  @Test
  public void createdChangeHasSpecifiedCommitMessage() throws Exception {
    Change.Id changeId =
        changeOperations
            .newChange()
            .commitMessage("Summary line\n\nDetailed description.")
            .create();

    ChangeInfo change = getChangeFromServer(changeId);
    CommitInfo currentPatchsetCommit = change.revisions.get(change.currentRevision).commit;
    assertThat(currentPatchsetCommit).message().startsWith("Summary line\n\nDetailed description.");
  }

  @Test
  public void changeCannotBeCreatedWithoutCommitMessage() {
    assertThrows(
        IllegalStateException.class, () -> changeOperations.newChange().commitMessage("").create());
  }

  @Test
  public void commitMessageOfCreatedChangeAutomaticallyGetsChangeId() throws Exception {
    Change.Id changeId =
        changeOperations
            .newChange()
            .commitMessage("Summary line\n\nDetailed description.")
            .create();

    ChangeInfo change = getChangeFromServer(changeId);
    CommitInfo currentPatchsetCommit = change.revisions.get(change.currentRevision).commit;
    assertThat(currentPatchsetCommit).message().contains("Change-Id:");
  }

  @Test
  public void changeIdSpecifiedInCommitMessageIsKeptForCreatedChange() throws Exception {
    Change.Id changeId =
        changeOperations
            .newChange()
            .commitMessage("Summary line\n\nChange-Id: I0123456789012345678901234567890123456789")
            .create();

    ChangeInfo change = getChangeFromServer(changeId);
    CommitInfo currentPatchsetCommit = change.revisions.get(change.currentRevision).commit;
    assertThat(currentPatchsetCommit)
        .message()
        .contains("Change-Id: I0123456789012345678901234567890123456789");
    assertThat(change.changeId).isEqualTo("I0123456789012345678901234567890123456789");
  }

  @Test
  public void createdChangeHasSpecifiedFiles() throws Exception {
    Change.Id changeId =
        changeOperations
            .newChange()
            .file("file1")
            .content("Line 1")
            .file("path/to/file2.txt")
            .content("Line one")
            .create();

    ChangeInfo change = getChangeFromServer(changeId);
    Map<String, FileInfo> files = change.revisions.get(change.currentRevision).files;
    assertThatMap(files).keys().containsExactly("file1", "path/to/file2.txt");
    BinaryResult fileContent1 = gApi.changes().id(changeId.get()).current().file("file1").content();
    assertThat(fileContent1).asString().isEqualTo("Line 1");
    BinaryResult fileContent2 =
        gApi.changes().id(changeId.get()).current().file("path/to/file2.txt").content();
    assertThat(fileContent2).asString().isEqualTo("Line one");
  }

  @Test
  public void existingChangeCanBeCheckedForExistence() {
    Change.Id changeId = changeOperations.newChange().create();

    boolean exists = changeOperations.change(changeId).exists();

    assertThat(exists).isTrue();
  }

  @Test
  public void notExistingChangeCanBeCheckedForExistence() {
    Change.Id changeId = Change.id(123456789);

    boolean exists = changeOperations.change(changeId).exists();

    assertThat(exists).isFalse();
  }

  @Test
  public void retrievingNotExistingChangeFails() {
    Change.Id changeId = Change.id(123456789);
    assertThrows(IllegalStateException.class, () -> changeOperations.change(changeId).get());
  }

  @Test
  public void numericChangeIdOfExistingChangeCanBeRetrieved() {
    Change.Id changeId = changeOperations.newChange().create();

    TestChange change = changeOperations.change(changeId).get();
    assertThat(change.numericChangeId()).isEqualTo(changeId);
  }

  @Test
  public void changeIdOfExistingChangeCanBeRetrieved() {
    Change.Id changeId =
        changeOperations
            .newChange()
            .commitMessage("Summary line\n\nChange-Id: I0123456789012345678901234567890123456789")
            .create();

    TestChange change = changeOperations.change(changeId).get();
    assertThat(change.changeId()).isEqualTo("I0123456789012345678901234567890123456789");
  }

  @Test
  public void currentPatchsetOfExistingChangeCanBeRetrieved() throws Exception {
    Change.Id changeId = changeOperations.newChange().create();

    TestPatchset patchset = changeOperations.change(changeId).currentPatchset().get();

    ChangeInfo expectedChange = getChangeFromServer(changeId);
    String expectedCommitId = expectedChange.currentRevision;
    int expectedPatchsetNumber = expectedChange.revisions.get(expectedCommitId)._number;
    assertThat(patchset.commitId()).isEqualTo(ObjectId.fromString(expectedCommitId));
    assertThat(patchset.patchsetId()).isEqualTo(PatchSet.id(changeId, expectedPatchsetNumber));
  }

  @Test
  public void earlierPatchsetOfExistingChangeCanBeRetrieved() {
    Change.Id changeId = changeOperations.newChange().create();
    PatchSet.Id earlierPatchsetId =
        changeOperations.change(changeId).currentPatchset().get().patchsetId();
    PatchSet.Id currentPatchsetId = changeOperations.change(changeId).newPatchset().create();

    TestPatchset earlierPatchset =
        changeOperations.change(changeId).patchset(earlierPatchsetId).get();

    assertThat(earlierPatchset.patchsetId()).isEqualTo(earlierPatchsetId);
    assertThat(earlierPatchset.patchsetId()).isNotEqualTo(currentPatchsetId);
  }

  @Test
  public void newPatchsetCanBeCreatedWithoutSpecifyingAnyParameters() throws Exception {
    Change.Id changeId = changeOperations.newChange().create();
    ChangeInfo unmodifiedChange = getChangeFromServer(changeId);
    int originalPatchsetCount = unmodifiedChange.revisions.size();

    PatchSet.Id patchsetId = changeOperations.change(changeId).newPatchset().create();

    ChangeInfo change = getChangeFromServer(changeId);
    assertThatMap(change.revisions).hasSize(originalPatchsetCount + 1);
    RevisionInfo currentRevision = change.revisions.get(change.currentRevision);
    assertThat(currentRevision._number).isEqualTo(patchsetId.get());
  }

  @Test
  public void newPatchsetIsCopyOfPreviousPatchsetByDefault() throws Exception {
    Change.Id changeId = changeOperations.newChange().create();

    PatchSet.Id patchsetId = changeOperations.change(changeId).newPatchset().create();

    ChangeInfo change = getChangeFromServer(changeId);
    RevisionInfo patchsetRevision = getRevision(change, patchsetId);
    assertThat(patchsetRevision.kind).isEqualTo(ChangeKind.NO_CHANGE);
  }

  @Test
  public void newPatchsetCanHaveReplacedFileContent() throws Exception {
    Change.Id changeId = changeOperations.newChange().file("file1").content("Line 1").create();

    PatchSet.Id patchsetId =
        changeOperations
            .change(changeId)
            .newPatchset()
            .file("file1")
            .content("Different content")
            .create();

    ChangeInfo change = getChangeFromServer(changeId);
    Map<String, FileInfo> files = change.revisions.get(change.currentRevision).files;
    assertThatMap(files).keys().containsExactly("file1");
    BinaryResult fileContent = getFileContent(changeId, patchsetId, "file1");
    assertThat(fileContent).asString().isEqualTo("Different content");
  }

  @Test
  public void newPatchsetCanHaveAdditionalFile() throws Exception {
    Change.Id changeId = changeOperations.newChange().file("file1").content("Line 1").create();

    PatchSet.Id patchsetId =
        changeOperations
            .change(changeId)
            .newPatchset()
            .file("file2")
            .content("My file content")
            .create();

    ChangeInfo change = getChangeFromServer(changeId);
    Map<String, FileInfo> files = change.revisions.get(change.currentRevision).files;
    assertThatMap(files).keys().containsExactly("file1", "file2");
    BinaryResult fileContent = getFileContent(changeId, patchsetId, "file2");
    assertThat(fileContent).asString().isEqualTo("My file content");
  }

  @Test
  public void newPatchsetCanHaveLessFiles() throws Exception {
    Change.Id changeId =
        changeOperations
            .newChange()
            .file("file1")
            .content("Line 1")
            .file("file2")
            .content("Line one")
            .create();

    changeOperations.change(changeId).newPatchset().file("file2").delete().create();

    ChangeInfo change = getChangeFromServer(changeId);
    Map<String, FileInfo> files = change.revisions.get(change.currentRevision).files;
    assertThatMap(files).keys().containsExactly("file1");
  }

  @Test
  public void newPatchsetCanHaveRenamedFile() throws Exception {
    Change.Id changeId =
        changeOperations
            .newChange()
            .file("file1")
            .content("Line 1")
            .file("file2")
            .content("Line one")
            .create();

    PatchSet.Id patchsetId =
        changeOperations
            .change(changeId)
            .newPatchset()
            .file("file2")
            .renameTo("renamed file")
            .create();

    ChangeInfo change = getChangeFromServer(changeId);
    Map<String, FileInfo> files = change.revisions.get(change.currentRevision).files;
    assertThatMap(files).keys().containsExactly("file1", "renamed file");
    BinaryResult fileContent = getFileContent(changeId, patchsetId, "renamed file");
    assertThat(fileContent).asString().isEqualTo("Line one");
  }

  private ChangeInfo getChangeFromServer(Change.Id changeId) throws RestApiException {
    return gApi.changes().id(changeId.get()).get();
  }

  private RevisionInfo getRevision(ChangeInfo change, PatchSet.Id patchsetId) {
    return change.revisions.values().stream()
        .filter(revision -> revision._number == patchsetId.get())
        .findAny()
        .orElseThrow(
            () ->
                new IllegalStateException(
                    String.format(
                        "Change %d doesn't have specified patchset %d.",
                        change._number, patchsetId.get())));
  }

  private BinaryResult getFileContent(Change.Id changeId, PatchSet.Id patchsetId, String filePath)
      throws RestApiException {
    return gApi.changes().id(changeId.get()).revision(patchsetId.get()).file(filePath).content();
  }
}
