// Copyright (C) 2019 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.fixCalculator;

import static com.google.gerrit.server.fixes.testing.FixResultSubject.assertThat;
import static com.google.gerrit.server.fixes.testing.GitEditSubject.assertThat;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.collect.ImmutableList;
import com.google.gerrit.entities.Comment.Range;
import com.google.gerrit.entities.FixReplacement;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.server.fixes.FixCalculator;
import com.google.gerrit.server.fixes.FixCalculator.FixResult;
import com.google.gerrit.server.patch.Text;
import org.eclipse.jgit.diff.Edit;
import org.junit.Test;

public class FixCalculatorVariousTest {
  private static final String multilineContentString =
      "First line\nSecond line\nThird line\nFourth line\nFifth line\n";
  private static final Text multilineContent = new Text(multilineContentString.getBytes(UTF_8));

  static FixResult calculateFixSingleReplacement(
      String content, int startLine, int startChar, int endLine, int endChar, String replacement)
      throws ResourceConflictException {
    FixReplacement fixReplacement =
        new FixReplacement(
            "AnyPath", new Range(startLine, startChar, endLine, endChar), replacement);
    return FixCalculator.calculateFix(
        new Text(content.getBytes(UTF_8)), ImmutableList.of(fixReplacement), false);
  }

  @Test
  public void lineNumberMustBePositive() {
    assertThrows(
        ResourceConflictException.class,
        () -> calculateFixSingleReplacement("First line\nSecond line", 0, 0, 0, 0, "Abc"));
  }

  @Test
  public void lineNumberMustExist() {
    assertThrows(
        ResourceConflictException.class,
        () -> calculateFixSingleReplacement("First line\nSecond line", 4, 0, 4, 0, "Abc"));
  }

  @Test
  public void startOffsetMustNotBeNegative() {
    assertThrows(
        ResourceConflictException.class,
        () -> calculateFixSingleReplacement("First line\nSecond line", 0, -1, 0, 0, "Abc"));
  }

  @Test
  public void endOffsetMustNotBeNegative() {
    assertThrows(
        ResourceConflictException.class,
        () -> calculateFixSingleReplacement("First line\nSecond line", 0, 0, 0, -1, "Abc"));
  }

  @Test
  public void insertAtTheEndOfSingleLineContentHasEOLMarkInvalidPosition() {
    assertThrows(
        ResourceConflictException.class,
        () -> calculateFixSingleReplacement("First line\n", 1, 11, 1, 11, "Abc"));
  }

  @Test
  public void startAfterEndOfLineMarkOfIntermediateLineThrowsAnException() {
    assertThrows(
        ResourceConflictException.class,
        () ->
            calculateFixSingleReplacement(
                "First line\nSecond line\nThird line\n", 1, 11, 2, 6, "Abc"));
  }

  @Test
  public void startAfterEndOfLineMarkOfLastLineThrowsAnException() {
    assertThrows(
        ResourceConflictException.class,
        () -> calculateFixSingleReplacement("First line\n", 1, 11, 2, 0, "Abc"));
  }

  @Test
  public void endAfterEndOfLineMarkOfIntermediateLineThrowsAnException() {
    assertThrows(
        ResourceConflictException.class,
        () ->
            calculateFixSingleReplacement(
                "First line\nSecond line\nThird line\n", 2, 0, 2, 12, "Abc"));
  }

  @Test
  public void endAfterEndOfLineMarkOfLastLineThrowsAnException() {
    assertThrows(
        ResourceConflictException.class,
        () -> calculateFixSingleReplacement("First line\nSecond line\n", 2, 0, 2, 12, "Abc"));
  }

  @Test
  public void severalChangesInTheSameLineNonSorted() throws Exception {
    FixReplacement replace = new FixReplacement("path", new Range(2, 1, 2, 3), "ABC");
    FixReplacement insert = new FixReplacement("path", new Range(2, 5, 2, 5), "DEFG");
    FixReplacement delete = new FixReplacement("path", new Range(2, 7, 2, 9), "");
    FixResult result =
        FixCalculator.calculateFix(
            multilineContent, ImmutableList.of(replace, delete, insert), false);
    assertThat(result)
        .text()
        .isEqualTo("First line\nSABConDEFGd ne\nThird line\nFourth line\nFifth line\n");
    assertThat(result).edits().hasSize(1);
    Edit edit = result.edits.get(0);
    assertThat(edit).isReplace(1, 1, 1, 1);
    assertThat(edit).internalEdits().hasSize(3);
    assertThat(edit).internalEdits().element(0).isReplace(1, 2, 1, 3);
    assertThat(edit).internalEdits().element(1).isInsert(5, 6, 4);
    assertThat(edit).internalEdits().element(2).isDelete(7, 2, 12);
  }

  @Test
  public void severalChangesInConsecutiveLines() throws Exception {
    FixReplacement replace = new FixReplacement("path", new Range(2, 1, 2, 3), "ABC");
    FixReplacement insert = new FixReplacement("path", new Range(3, 5, 3, 5), "DEFG");
    FixReplacement delete = new FixReplacement("path", new Range(4, 7, 4, 9), "");
    FixResult result =
        FixCalculator.calculateFix(
            multilineContent, ImmutableList.of(replace, insert, delete), false);
    assertThat(result)
        .text()
        .isEqualTo("First line\nSABCond line\nThirdDEFG line\nFourth ne\nFifth line\n");
    assertThat(result).edits().hasSize(1);
    Edit edit = result.edits.get(0);
    assertThat(edit).isReplace(1, 3, 1, 3);
    assertThat(edit).internalEdits().hasSize(3);
    assertThat(edit).internalEdits().element(0).isReplace(1, 2, 1, 3);
    assertThat(edit).internalEdits().element(1).isInsert(17, 18, 4);
    assertThat(edit).internalEdits().element(2).isDelete(30, 2, 35);
  }

  @Test
  public void intraline() throws Exception {
    FixReplacement replace = new FixReplacement("path", new Range(2, 0, 2, 11), "Second ABC line");
    FixResult result =
        FixCalculator.calculateFix(multilineContent, ImmutableList.of(replace), true);
    assertThat(result)
        .text()
        .isEqualTo("First line\nSecond ABC line\nThird line\nFourth line\nFifth line\n");
    assertThat(result).edits().hasSize(1);
    Edit edit = result.edits.get(0);
    assertThat(edit).isReplace(1, 1, 1, 1);
    assertThat(edit).internalEdits().hasSize(1);
    assertThat(edit).internalEdits().element(0).isInsert(7, 7, 4);
  }

  @Test
  public void severalChangesInNonConsecutiveLines() throws Exception {
    FixReplacement replace = new FixReplacement("path", new Range(1, 1, 1, 3), "ABC");
    FixReplacement insert = new FixReplacement("path", new Range(3, 5, 3, 5), "DEFG");
    FixReplacement delete = new FixReplacement("path", new Range(5, 9, 6, 0), "");
    FixResult result =
        FixCalculator.calculateFix(
            multilineContent, ImmutableList.of(replace, insert, delete), false);
    assertThat(result)
        .text()
        .isEqualTo("FABCst line\nSecond line\nThirdDEFG line\nFourth line\nFifth lin");
    assertThat(result).edits().hasSize(3);
    assertThat(result).edits().element(0).isReplace(0, 1, 0, 1);
    assertThat(result).edits().element(0).internalEdits().onlyElement().isReplace(1, 2, 1, 3);
    assertThat(result).edits().element(1).isReplace(2, 1, 2, 1);
    assertThat(result).edits().element(1).internalEdits().onlyElement().isInsert(5, 5, 4);
    assertThat(result).edits().element(2).isReplace(4, 1, 4, 1);
    assertThat(result).edits().element(2).internalEdits().onlyElement().isDelete(9, 2, 9);
  }

  @Test
  public void multipleChanges() throws Exception {
    String str =
        "First line\nSecond line\nThird line\nFourth line\nFifth line\nSixth line"
            + "\nSeventh line\nEighth line\nNinth line\nTenth line\n";
    Text content = new Text(str.getBytes(UTF_8));

    FixReplacement multiLineReplace =
        new FixReplacement("path", new Range(1, 2, 3, 3), "AB\nC\nDEFG\nQ\n");
    FixReplacement multiLineDelete = new FixReplacement("path", new Range(4, 8, 5, 8), "");
    FixReplacement singleLineInsert = new FixReplacement("path", new Range(5, 10, 5, 10), "QWERTY");

    FixReplacement singleLineReplace = new FixReplacement("path", new Range(7, 3, 7, 7), "XY");
    FixReplacement multiLineInsert =
        new FixReplacement("path", new Range(8, 7, 8, 7), "KLMNO\nASDF");

    FixReplacement singleLineDelete = new FixReplacement("path", new Range(10, 3, 10, 7), "");

    FixResult result =
        FixCalculator.calculateFix(
            content,
            ImmutableList.of(
                multiLineReplace,
                multiLineDelete,
                singleLineInsert,
                singleLineReplace,
                multiLineInsert,
                singleLineDelete),
            false);
    assertThat(result)
        .text()
        .isEqualTo(
            "FiAB\n"
                + "C\n"
                + "DEFG\n"
                + "Q\n"
                + "rd line\n"
                + "Fourth lneQWERTY\n"
                + "Sixth line\n"
                + "SevXY line\n"
                + "Eighth KLMNO\n"
                + "ASDFline\n"
                + "Ninth line\n"
                + "Tenine\n");
    assertThat(result).edits().hasSize(3);
    assertThat(result).edits().element(0).isReplace(0, 5, 0, 6);
    assertThat(result)
        .edits()
        .element(0)
        .internalEdits()
        .containsExactly(
            new Edit(2, 26, 2, 14), new Edit(42, 54, 30, 30), new Edit(56, 56, 32, 38));

    assertThat(result).edits().element(1).isReplace(6, 2, 7, 3);
    assertThat(result)
        .edits()
        .element(1)
        .internalEdits()
        .containsExactly(new Edit(3, 7, 3, 5), new Edit(20, 20, 18, 28));
    assertThat(result).edits().element(2).isReplace(9, 1, 11, 1);
    assertThat(result).edits().element(2).internalEdits().onlyElement().isDelete(3, 4, 3);
  }

  @Test
  public void changesMayTouch() throws Exception {
    FixReplacement firstReplace = new FixReplacement("path", new Range(1, 6, 2, 7), "modified ");
    FixReplacement consecutiveReplace =
        new FixReplacement("path", new Range(2, 7, 3, 5), "content");
    FixResult result =
        FixCalculator.calculateFix(
            multilineContent, ImmutableList.of(firstReplace, consecutiveReplace), false);
    assertThat(result).text().isEqualTo("First modified content line\nFourth line\nFifth line\n");
    assertThat(result).edits().hasSize(1);
    Edit edit = result.edits.get(0);
    assertThat(edit).isReplace(0, 3, 0, 1);
    // The current code creates two inline edits even though only one would be necessary. It
    // shouldn't make a visual difference to the user and hence we can ignore this.
    assertThat(edit).internalEdits().hasSize(2);
    assertThat(edit).internalEdits().element(0).isReplace(6, 12, 6, 9);
    assertThat(edit).internalEdits().element(1).isReplace(18, 10, 15, 7);
  }

  @Test
  public void overlappingChangesInMiddleOfLineRaisesException() throws Exception {
    FixReplacement firstReplace =
        new FixReplacement("path", new Range(2, 0, 3, 5), "First modification\n");
    FixReplacement secondReplace =
        new FixReplacement("path", new Range(3, 4, 4, 0), "Some other modified content\n");
    assertThrows(
        ResourceConflictException.class,
        () ->
            FixCalculator.calculateFix(
                multilineContent, ImmutableList.of(firstReplace, secondReplace), false));
  }

  @Test
  public void overlappingChangesInBeginningOfLineRaisesException() throws Exception {
    FixReplacement firstReplace =
        new FixReplacement("path", new Range(2, 0, 3, 1), "First modification\n");
    FixReplacement secondReplace =
        new FixReplacement("path", new Range(3, 0, 4, 0), "Some other modified content\n");
    assertThrows(
        ResourceConflictException.class,
        () ->
            FixCalculator.calculateFix(
                multilineContent, ImmutableList.of(firstReplace, secondReplace), false));
  }
}
