// Copyright (C) 2017 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.fixes;

import static com.google.gerrit.server.edit.tree.TreeModificationSubject.assertThatList;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.replay;

import com.google.common.collect.ImmutableList;
import com.google.gerrit.extensions.restapi.BinaryResult;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.reviewdb.client.Comment.Range;
import com.google.gerrit.reviewdb.client.FixReplacement;
import com.google.gerrit.server.change.FileContentUtil;
import com.google.gerrit.server.edit.tree.TreeModification;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.testing.GerritBaseTests;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import org.easymock.EasyMock;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

public class FixReplacementInterpreterTest extends GerritBaseTests {

  @Rule public ExpectedException expectedException = ExpectedException.none();

  private final FileContentUtil fileContentUtil = createMock(FileContentUtil.class);
  private final Repository repository = createMock(Repository.class);
  private final ProjectState projectState = createMock(ProjectState.class);
  private final ObjectId patchSetCommitId = createMock(ObjectId.class);
  private final String filePath1 = "an/arbitrary/file.txt";
  private final String filePath2 = "another/arbitrary/file.txt";

  private FixReplacementInterpreter fixReplacementInterpreter;

  @Before
  public void setUp() {
    fixReplacementInterpreter = new FixReplacementInterpreter(fileContentUtil);
  }

  @Test
  public void noReplacementsResultInNoTreeModifications() throws Exception {
    List<TreeModification> treeModifications = toTreeModifications();
    assertThatList(treeModifications).isEmpty();
  }

  @Test
  public void treeModificationsTargetCorrectFiles() throws Exception {
    FixReplacement fixReplacement =
        new FixReplacement(filePath1, new Range(1, 6, 3, 2), "Modified content");
    FixReplacement fixReplacement2 =
        new FixReplacement(filePath1, new Range(3, 5, 3, 5), "Second modification");
    mockFileContent(filePath1, "First line\nSecond line\nThird line\n");
    FixReplacement fixReplacement3 =
        new FixReplacement(filePath2, new Range(2, 0, 3, 0), "Another modified content");
    mockFileContent(filePath2, "1st line\n2nd line\n3rd line\n");

    replay(fileContentUtil);
    List<TreeModification> treeModifications =
        toTreeModifications(fixReplacement, fixReplacement3, fixReplacement2);
    List<TreeModification> sortedTreeModifications = getSortedCopy(treeModifications);
    assertThatList(sortedTreeModifications)
        .element(0)
        .asChangeFileContentModification()
        .filePath()
        .isEqualTo(filePath1);
    assertThatList(sortedTreeModifications)
        .element(0)
        .asChangeFileContentModification()
        .newContent()
        .startsWith("First");
    assertThatList(sortedTreeModifications)
        .element(1)
        .asChangeFileContentModification()
        .filePath()
        .isEqualTo(filePath2);
    assertThatList(sortedTreeModifications)
        .element(1)
        .asChangeFileContentModification()
        .newContent()
        .startsWith("1st");
  }

  @Test
  public void replacementsCanDeleteALine() throws Exception {
    FixReplacement fixReplacement = new FixReplacement(filePath1, new Range(2, 0, 3, 0), "");
    mockFileContent(filePath1, "First line\nSecond line\nThird line\n");

    replay(fileContentUtil);
    List<TreeModification> treeModifications = toTreeModifications(fixReplacement);
    assertThatList(treeModifications)
        .onlyElement()
        .asChangeFileContentModification()
        .newContent()
        .isEqualTo("First line\nThird line\n");
  }

  @Test
  public void replacementsCanAddALine() throws Exception {
    FixReplacement fixReplacement =
        new FixReplacement(filePath1, new Range(2, 0, 2, 0), "A new line\n");
    mockFileContent(filePath1, "First line\nSecond line\nThird line\n");

    replay(fileContentUtil);
    List<TreeModification> treeModifications = toTreeModifications(fixReplacement);
    assertThatList(treeModifications)
        .onlyElement()
        .asChangeFileContentModification()
        .newContent()
        .isEqualTo("First line\nA new line\nSecond line\nThird line\n");
  }

  @Test
  public void replacementsMaySpanMultipleLines() throws Exception {
    FixReplacement fixReplacement = new FixReplacement(filePath1, new Range(1, 6, 3, 1), "and t");
    mockFileContent(filePath1, "First line\nSecond line\nThird line\n");

    replay(fileContentUtil);
    List<TreeModification> treeModifications = toTreeModifications(fixReplacement);
    assertThatList(treeModifications)
        .onlyElement()
        .asChangeFileContentModification()
        .newContent()
        .isEqualTo("First and third line\n");
  }

  @Test
  public void replacementsMayOccurOnSameLine() throws Exception {
    FixReplacement fixReplacement1 = new FixReplacement(filePath1, new Range(2, 0, 2, 6), "A");
    FixReplacement fixReplacement2 =
        new FixReplacement(filePath1, new Range(2, 7, 2, 11), "modification");
    mockFileContent(filePath1, "First line\nSecond line\nThird line\n");

    replay(fileContentUtil);
    List<TreeModification> treeModifications =
        toTreeModifications(fixReplacement1, fixReplacement2);
    assertThatList(treeModifications)
        .onlyElement()
        .asChangeFileContentModification()
        .newContent()
        .isEqualTo("First line\nA modification\nThird line\n");
  }

  @Test
  public void replacementsMayTouch() throws Exception {
    FixReplacement fixReplacement1 =
        new FixReplacement(filePath1, new Range(1, 6, 2, 7), "modified ");
    FixReplacement fixReplacement2 =
        new FixReplacement(filePath1, new Range(2, 7, 3, 5), "content");
    mockFileContent(filePath1, "First line\nSecond line\nThird line\n");

    replay(fileContentUtil);
    List<TreeModification> treeModifications =
        toTreeModifications(fixReplacement1, fixReplacement2);
    assertThatList(treeModifications)
        .onlyElement()
        .asChangeFileContentModification()
        .newContent()
        .isEqualTo("First modified content line\n");
  }

  @Test
  public void replacementsCanAddContentAtEndOfFile() throws Exception {
    FixReplacement fixReplacement =
        new FixReplacement(filePath1, new Range(4, 0, 4, 0), "New content");
    mockFileContent(filePath1, "First line\nSecond line\nThird line\n");

    replay(fileContentUtil);
    List<TreeModification> treeModifications = toTreeModifications(fixReplacement);
    assertThatList(treeModifications)
        .onlyElement()
        .asChangeFileContentModification()
        .newContent()
        .isEqualTo("First line\nSecond line\nThird line\nNew content");
  }

  @Test
  public void replacementsCanModifySeveralFilesInAnyOrder() throws Exception {
    FixReplacement fixReplacement1 =
        new FixReplacement(filePath1, new Range(1, 1, 3, 2), "Modified content");
    mockFileContent(filePath1, "First line\nSecond line\nThird line\n");
    FixReplacement fixReplacement2 =
        new FixReplacement(filePath2, new Range(2, 0, 3, 0), "First modification\n");
    FixReplacement fixReplacement3 =
        new FixReplacement(filePath2, new Range(3, 0, 4, 0), "Second modification\n");
    mockFileContent(filePath2, "1st line\n2nd line\n3rd line\n");

    replay(fileContentUtil);
    List<TreeModification> treeModifications =
        toTreeModifications(fixReplacement3, fixReplacement1, fixReplacement2);
    List<TreeModification> sortedTreeModifications = getSortedCopy(treeModifications);
    assertThatList(sortedTreeModifications)
        .element(0)
        .asChangeFileContentModification()
        .newContent()
        .isEqualTo("FModified contentird line\n");
    assertThatList(sortedTreeModifications)
        .element(1)
        .asChangeFileContentModification()
        .newContent()
        .isEqualTo("1st line\nFirst modification\nSecond modification\n");
  }

  @Test
  public void lineSeparatorCanBeChanged() throws Exception {
    FixReplacement fixReplacement = new FixReplacement(filePath1, new Range(2, 11, 3, 0), "\r");
    mockFileContent(filePath1, "First line\nSecond line\nThird line\n");

    replay(fileContentUtil);
    List<TreeModification> treeModifications = toTreeModifications(fixReplacement);
    assertThatList(treeModifications)
        .onlyElement()
        .asChangeFileContentModification()
        .newContent()
        .isEqualTo("First line\nSecond line\rThird line\n");
  }

  @Test
  public void replacementsDoNotNeedToBeOrderedAccordingToRange() throws Exception {
    FixReplacement fixReplacement1 =
        new FixReplacement(filePath1, new Range(1, 0, 2, 0), "1st modification\n");
    FixReplacement fixReplacement2 =
        new FixReplacement(filePath1, new Range(3, 0, 4, 0), "2nd modification\n");
    FixReplacement fixReplacement3 =
        new FixReplacement(filePath1, new Range(4, 0, 5, 0), "3rd modification\n");
    mockFileContent(filePath1, "First line\nSecond line\nThird line\nFourth line\nFifth line\n");

    replay(fileContentUtil);
    List<TreeModification> treeModifications =
        toTreeModifications(fixReplacement2, fixReplacement1, fixReplacement3);
    assertThatList(treeModifications)
        .onlyElement()
        .asChangeFileContentModification()
        .newContent()
        .isEqualTo(
            "1st modification\nSecond line\n2nd modification\n3rd modification\nFifth line\n");
  }

  @Test
  public void replacementsMustNotReferToNotExistingLine() throws Exception {
    FixReplacement fixReplacement =
        new FixReplacement(filePath1, new Range(5, 0, 5, 0), "A new line\n");
    mockFileContent(filePath1, "First line\nSecond line\nThird line\n");

    replay(fileContentUtil);

    expectedException.expect(ResourceConflictException.class);
    toTreeModifications(fixReplacement);
  }

  @Test
  public void replacementsMustNotReferToZeroLine() throws Exception {
    FixReplacement fixReplacement =
        new FixReplacement(filePath1, new Range(0, 0, 0, 0), "A new line\n");
    mockFileContent(filePath1, "First line\nSecond line\nThird line\n");

    replay(fileContentUtil);

    expectedException.expect(ResourceConflictException.class);
    toTreeModifications(fixReplacement);
  }

  @Test
  public void replacementsMustNotReferToNotExistingOffsetOfIntermediateLine() throws Exception {
    FixReplacement fixReplacement =
        new FixReplacement(filePath1, new Range(1, 0, 1, 11), "modified");
    mockFileContent(filePath1, "First line\nSecond line\nThird line\n");

    replay(fileContentUtil);

    expectedException.expect(ResourceConflictException.class);
    toTreeModifications(fixReplacement);
  }

  @Test
  public void replacementsMustNotReferToNotExistingOffsetOfLastLine() throws Exception {
    FixReplacement fixReplacement =
        new FixReplacement(filePath1, new Range(3, 0, 3, 11), "modified");
    mockFileContent(filePath1, "First line\nSecond line\nThird line\n");

    replay(fileContentUtil);

    expectedException.expect(ResourceConflictException.class);
    toTreeModifications(fixReplacement);
  }

  @Test
  public void replacementsMustNotReferToNegativeOffset() throws Exception {
    FixReplacement fixReplacement =
        new FixReplacement(filePath1, new Range(1, -1, 1, 5), "modified");
    mockFileContent(filePath1, "First line\nSecond line\nThird line\n");

    replay(fileContentUtil);

    expectedException.expect(ResourceConflictException.class);
    toTreeModifications(fixReplacement);
  }

  private void mockFileContent(String filePath, String fileContent) throws Exception {
    EasyMock.expect(
            fileContentUtil.getContent(repository, projectState, patchSetCommitId, filePath))
        .andReturn(BinaryResult.create(fileContent));
  }

  private List<TreeModification> toTreeModifications(FixReplacement... fixReplacements)
      throws Exception {
    return fixReplacementInterpreter.toTreeModifications(
        repository, projectState, patchSetCommitId, ImmutableList.copyOf(fixReplacements));
  }

  private static List<TreeModification> getSortedCopy(List<TreeModification> treeModifications) {
    List<TreeModification> sortedTreeModifications = new ArrayList<>(treeModifications);
    sortedTreeModifications.sort(Comparator.comparing(TreeModification::getFilePath));
    return sortedTreeModifications;
  }
}
