// 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.server.patch;

import static com.google.common.truth.Truth.assertThat;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.util.List;
import org.eclipse.jgit.diff.Edit;
import org.eclipse.jgit.diff.EditList;
import org.eclipse.jgit.diff.ReplaceEdit;
import org.junit.Test;

public class IntraLineLoaderTest {

  @Test
  public void rewriteAtStartOfLineIsRecognized() throws Exception {
    String a = "abc1\n";
    String b = "def1\n";
    assertThat(intraline(a, b)).isEqualTo(ref().replace("abc", "def").common("1\n").edits);
  }

  @Test
  public void rewriteAtEndOfLineIsRecognized() throws Exception {
    String a = "abc1\n";
    String b = "abc2\n";
    assertThat(intraline(a, b)).isEqualTo(ref().common("abc").replace("1", "2").common("\n").edits);
  }

  @Test
  public void completeRewriteIncludesNewline() throws Exception {
    String a = "abc1\n";
    String b = "def2\n";
    assertThat(intraline(a, b)).isEqualTo(ref().replace("abc1\n", "def2\n").edits);
  }

  @Test
  public void closeEditsAreCombined() throws Exception {
    String a = "ab1cdef2gh\n";
    String b = "ab2cdef3gh\n";
    assertThat(intraline(a, b))
        .isEqualTo(ref().common("ab").replace("1cdef2", "2cdef3").common("gh\n").edits);
  }

  @Test
  public void preferInsertAfterCommonPart1() throws Exception {
    String a = "start middle end\n";
    String b = "start middlemiddle end\n";
    assertThat(intraline(a, b))
        .isEqualTo(ref().common("start middle").insert("middle").common(" end\n").edits);
  }

  @Test
  public void preferInsertAfterCommonPart2() throws Exception {
    String a = "abc def\n";
    String b = "abc  def\n";
    assertThat(intraline(a, b)).isEqualTo(ref().common("abc ").insert(" ").common("def\n").edits);
  }

  @Test
  public void preferInsertAtLineBreak1() throws Exception {
    String a = "multi\nline\n";
    String b = "multi\nlinemulti\nline\n";
    assertThat(intraline(a, b)).isEqualTo(wordEdit(10, 10, 6, 16));
    // better would be:
    // assertThat(intraline(a, b)).isEqualTo(wordEdit(6, 6, 6, 16));
    // or the equivalent:
    // assertThat(intraline(a, b)).isEqualTo(ref()
    //    .common("multi\n").insert("linemulti\n").common("line\n").edits
    // );
  }

  // TODO: expected failure
  // the current code does not work on the first line
  // and the insert marker is in the wrong location
  @Test(expected = AssertionError.class)
  public void preferInsertAtLineBreak2() throws Exception {
    String a = "  abc\n    def\n";
    String b = "    abc\n      def\n";
    assertThat(intraline(a, b))
        .isEqualTo(ref().insert("  ").common("  abc\n").insert("  ").common("  def\n").edits);
  }

  // TODO: expected failure
  // the current code does not work on the first line
  @Test(expected = AssertionError.class)
  public void preferDeleteAtLineBreak() throws Exception {
    String a = "    abc\n      def\n";
    String b = "  abc\n    def\n";
    assertThat(intraline(a, b))
        .isEqualTo(ref().remove("  ").common("  abc\n").remove("  ").common("  def\n").edits);
  }

  @Test
  public void insertedWhitespaceIsRecognized() throws Exception {
    String a = " int *foobar\n";
    String b = " int * foobar\n";
    assertThat(intraline(a, b))
        .isEqualTo(ref().common(" int *").insert(" ").common("foobar\n").edits);
  }

  @Test
  public void insertedWhitespaceIsRecognizedInMultipleLines() throws Exception {
    //         |0    5   10  |  5   20    5   30
    String a = " int *foobar\n int *foobar\n";
    String b = " int * foobar\n int * foobar\n";
    assertThat(intraline(a, b))
        .isEqualTo(
            ref()
                .common(" int *")
                .insert(" ")
                .common("foobar\n")
                .common(" int *")
                .insert(" ")
                .common("foobar\n")
                .edits);
  }

  // helper functions to call IntraLineLoader.compute

  private static int countLines(String s) {
    int count = 0;
    for (int i = 0; i < s.length(); i++) {
      if (s.charAt(i) == '\n') {
        count++;
      }
    }
    return count;
  }

  private static List<Edit> intraline(String a, String b) throws Exception {
    return intraline(a, b, new Edit(0, countLines(a), 0, countLines(b)));
  }

  private static List<Edit> intraline(String a, String b, Edit lines) throws Exception {
    Text aText = new Text(a.getBytes(UTF_8));
    Text bText = new Text(b.getBytes(UTF_8));

    IntraLineDiff diff =
        IntraLineLoader.compute(aText, bText, ImmutableList.of(lines), ImmutableSet.of());

    assertThat(diff.getStatus()).isEqualTo(IntraLineDiff.Status.EDIT_LIST);
    List<Edit> actualEdits = diff.getEdits();
    assertThat(actualEdits).hasSize(1);
    Edit actualEdit = actualEdits.get(0);
    assertThat(actualEdit.getBeginA()).isEqualTo(lines.getBeginA());
    assertThat(actualEdit.getEndA()).isEqualTo(lines.getEndA());
    assertThat(actualEdit.getBeginB()).isEqualTo(lines.getBeginB());
    assertThat(actualEdit.getEndB()).isEqualTo(lines.getEndB());
    assertThat(actualEdit).isInstanceOf(ReplaceEdit.class);

    return ((ReplaceEdit) actualEdit).getInternalEdits();
  }

  // helpers to compute reference values

  private static List<Edit> wordEdit(int as, int ae, int bs, int be) {
    return EditList.singleton(new Edit(as, ae, bs, be));
  }

  private static Reference ref() {
    return new Reference();
  }

  private static class Reference {
    List<Edit> edits;
    private int posA;
    private int posB;

    Reference() {
      edits = new EditList();
      posA = posB = 0;
    }

    Reference common(String s) {
      int len = s.length();
      posA += len;
      posB += len;
      return this;
    }

    Reference insert(String s) {
      return replace("", s);
    }

    Reference remove(String s) {
      return replace(s, "");
    }

    Reference replace(String a, String b) {
      int lenA = a.length();
      int lenB = b.length();
      edits.add(new Edit(posA, posA + lenA, posB, posB + lenB));
      posA += lenA;
      posB += lenB;
      return this;
    }
  }
}
