// 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;

import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.collect.ImmutableList;
import com.google.gerrit.entities.Comment;
import com.google.gerrit.entities.FixReplacement;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.jgit.diff.ReplaceEdit;
import com.google.gerrit.server.patch.Text;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import org.eclipse.jgit.diff.Edit;

/**
 * Produces final version of an input content with all fixes applied together with list of edits.
 */
public class FixCalculator {
  private static final Comparator<FixReplacement> ASC_RANGE_FIX_REPLACEMENT_COMPARATOR =
      Comparator.comparing(fixReplacement -> fixReplacement.range);

  private FixCalculator() {}

  /**
   * Returns a result of applying fixes to an original content.
   *
   * @param originalContent is a text to which fixes must be applied
   * @param fixReplacements is a list of fixes to be applied
   * @throws ResourceConflictException if the fixReplacements contains invalid data (for example, if
   *     an item points to an invalid range or if some ranges are intersected).
   */
  public static String getNewFileContent(
      String originalContent, List<FixReplacement> fixReplacements)
      throws ResourceConflictException {
    FixResult fixResult = calculateFix(new Text(originalContent.getBytes(UTF_8)), fixReplacements);
    return fixResult.text.getString(0, fixResult.text.size(), false);
  }

  /**
   * Returns a result of applying fixes to an original content and list of applied edits.
   *
   * @param originalText is a text to which fixes must be applied
   * @param fixReplacements is a list of fixes to be applied
   * @return {@link FixResult}
   * @throws ResourceConflictException if the fixReplacements contains invalid data (for example, if
   *     an item points to an invalid range or if some ranges are intersected).
   */
  public static FixResult calculateFix(Text originalText, List<FixReplacement> fixReplacements)
      throws ResourceConflictException {
    List<FixReplacement> sortedReplacements = new ArrayList<>(fixReplacements);
    sortedReplacements.sort(ASC_RANGE_FIX_REPLACEMENT_COMPARATOR);
    if (!sortedReplacements.isEmpty() && sortedReplacements.get(0).range.startLine <= 0) {
      throw new ResourceConflictException(
          String.format(
              "Cannot calculate fix replacement for range %s",
              toString(sortedReplacements.get(0).range)));
    }
    ContentBuilder builder = new ContentBuilder(originalText);
    for (FixReplacement fixReplacement : sortedReplacements) {
      try {
        builder.addReplacement(fixReplacement);
      } catch (IndexOutOfBoundsException e) {
        throw new ResourceConflictException(
            String.format(
                "Cannot calculate fix replacement for range %s", toString(fixReplacement.range)),
            e);
      }
    }
    return builder.build();
  }

  private static String toString(Comment.Range range) {
    return String.format(
        "(%s:%s - %s:%s)", range.startLine, range.startChar, range.endLine, range.endChar);
  }
  /*
  Algorithm:
  Input:
    Original text (aka srcText)
    Sorted list of replacements in ascending order, where each replacement has:
        srcRange - part of the original text to be
                   replaced, inserted or deleted (see {@link Comment.Range} for details)
        replacement - text to be set instead of srcRange
    Replacement ranges must not intersect.

  Output:
    Final text (aka finalText)
    List of Edit, where each Edit is an instance of {@link ReplaceEdit}
      Each ReplaceEdit cover one or more lines in the original text
      Each ReplaceEdit contains one or more Edit for intraline edits
    See {@link ReplaceEdit} and {@link Edit} for details.
  *
  Note: The algorithm is implemented in this way to avoid string.replace operations.
  It has complexity O(len(replacements) + max(len(originalText), len(finalText)) )

  Main steps:
  - set srcPos to start of the original text. It is like a cursor position in the original text.
  - set dstPos to start of the final text.  It is like a cursor position in the final text.
  - the finalText initially empty

  - for each replacement:
       - append text between a previous and a current replacement to the finalText
           (because replacements were sorted, this part of text can't be changed by
             following replacements). I.e. append substring of srcText between srcPos
             and replacement.srcRange.start to the finalText
           Update srcPos and dstPos - set them at the end of appended text
           (i.e. srcPos points to the position before replacement.srcRange.start,
            dstPos points to the position where replacement.text should be inserted)
       - set dstReplacementStart = dstPos
       - append replacement.text to the finalText.
           Update srcPos and dstPos accordingly (i.e. srcPos points to the position after
           replacement.srcRange, dstPos points to the position in the finalText after
           the appended replacement.text).
       - set dstReplacementEnd = dstPos
       - dstRange = (dstReplacementStart, dstReplacementEnd) - is the range in the finalText.
       - srcRange = (replacement.Start, replacement.End) -  is the range in the original text *

       - If previously created ReplaceEdit ends on the same or previous line as srcRange.startLine,
           then intraline edit is added to it (and ReplaceEdit endLine must be updated if needed);
           srcRange and dstRange together is used to calculate intraline Edit
         otherwise
          create new ReplaceEdit and add intraline Edit to it
          srcRange and dstRange together is used to calculate intraline Edit

  - append text after the last replacements,
      i.e. add part of srcText after srcPos to the finalText

  - Return the finalText and all created ReplaceEdits

  Implementation notes:
  1) The intraline Edits inside ReplaceEdit stores positions relative to ReplaceEdit start.
  2) srcPos and dstPos tracks current position as 3 numbers:
  - line number
  - column number
  - textPos - absolute position from the start of the text. The textPos is used to calculate
  relative positions of Edit inside ReplaceEdit
     */
  private static class ContentBuilder {
    private static class FixRegion {
      int startSrcLine;
      int startDstLine;
      int startSrcPos;
      int startDstPos;
      List<Edit> internalEdits;

      FixRegion() {
        this.internalEdits = new ArrayList<>();
      }
    }

    private final ContentProcessor contentProcessor;
    final ImmutableList.Builder<Edit> edits;
    FixRegion currentRegion;

    ContentBuilder(Text src) {
      this.contentProcessor = new ContentProcessor(src);
      this.edits = new ImmutableList.Builder<>();
    }

    void addReplacement(FixReplacement replacement) {
      if (shouldStartNewEdit(replacement)) {
        finishExistingEdit();
      }
      // processSrcContent expects that line number is 0-based,
      // but replacement.range.startLine is 1-based, so subtract 1
      processSrcContent(replacement.range.startLine - 1, replacement.range.startChar, true);
      processReplacement(replacement);
    }

    Text getNewText() {
      return new Text(contentProcessor.sb.toString().getBytes(UTF_8));
    }

    void finish() {
      finishExistingEdit();
      if (contentProcessor.hasMoreLines()) {
        contentProcessor.appendLinesToEndOfContent();
      }
    }

    public FixResult build() {
      finish();
      return new FixResult(edits.build(), this.getNewText());
    }

    private void finishExistingEdit() {
      if (contentProcessor.srcPosition.column > 0 || contentProcessor.dstPosition.column > 0) {
        contentProcessor.processToEndOfLine(true);
      }
      if (currentRegion != null) {
        int endSrc = contentProcessor.srcPosition.line;
        if (contentProcessor.srcPosition.column > 0) {
          endSrc++;
        }
        int endDst = contentProcessor.dstPosition.line;
        if (contentProcessor.dstPosition.column > 0) {
          endDst++;
        }
        ReplaceEdit edit =
            new ReplaceEdit(
                currentRegion.startSrcLine,
                endSrc,
                currentRegion.startDstLine,
                endDst,
                currentRegion.internalEdits);
        currentRegion = null;
        edits.add(edit);
      }
    }

    private boolean shouldStartNewEdit(FixReplacement replacement) {
      if (currentRegion == null) {
        return true;
      }
      // New edit must be started if there is at least one unchanged line after the last edit
      // Subtract 1 from replacement.range.startLine because it is a 1-based line number,
      // and contentProcessor.srcPosition.line is a 0-based line number
      return replacement.range.startLine - 1 > contentProcessor.srcPosition.line + 1;
    }

    private void processSrcContent(int toLine, int toColumn, boolean append)
        throws IndexOutOfBoundsException {
      // toLine >= currentSrcLineIndex
      if (toLine == contentProcessor.srcPosition.line) {
        contentProcessor.processLineToColumn(toColumn, append);
      } else {
        contentProcessor.processToEndOfLine(append);
        contentProcessor.processMultiline(toLine, append);
        contentProcessor.processLineToColumn(toColumn, append);
      }
    }

    private void processReplacement(FixReplacement fix) {
      if (currentRegion == null) {
        currentRegion = new FixRegion();
        currentRegion.startSrcLine = contentProcessor.srcPosition.line;
        currentRegion.startSrcPos = contentProcessor.srcPosition.getLineStartPos();
        currentRegion.startDstLine = contentProcessor.dstPosition.line;
        currentRegion.startDstPos = contentProcessor.dstPosition.getLineStartPos();
      }
      int srcStartPos = contentProcessor.srcPosition.textPos;
      int dstStartPos = contentProcessor.dstPosition.textPos;
      contentProcessor.appendReplacement(fix.replacement);
      processSrcContent(fix.range.endLine - 1, fix.range.endChar, false);

      currentRegion.internalEdits.add(
          new Edit(
              srcStartPos - currentRegion.startSrcPos,
              contentProcessor.srcPosition.textPos - currentRegion.startSrcPos,
              dstStartPos - currentRegion.startDstPos,
              contentProcessor.dstPosition.textPos - currentRegion.startDstPos));
    }
  }

  private static class ContentProcessor {
    static class ContentPosition {
      int line;
      int column;
      int textPos;

      void appendMultilineContent(int lineCount, int charCount) {
        line += lineCount;
        column = 0;
        textPos += charCount;
      }

      void appendLineEndedWithEOLMark(int charCount) {
        textPos += charCount;
        line++;
        column = 0;
      }

      void appendStringWithoutEOLMark(int charCount) {
        textPos += charCount;
        column += charCount;
      }

      int getLineStartPos() {
        return textPos - column;
      }
    }

    private final StringBuilder sb;
    final ContentPosition srcPosition;
    final ContentPosition dstPosition;
    String currentSrcLine;
    Text src;
    boolean endOfSource;

    ContentProcessor(Text src) {
      this.src = src;
      sb = new StringBuilder(src.size());
      srcPosition = new ContentPosition();
      dstPosition = new ContentPosition();
      endOfSource = src.size() == 0;
    }

    void processMultiline(int toLine, boolean append) {
      if (endOfSource || toLine <= srcPosition.line) {
        return;
      }
      int fromLine = srcPosition.line;
      String lines = src.getString(fromLine, toLine, false);
      int lineCount = toLine - fromLine;
      int charCount = lines.length();
      srcPosition.appendMultilineContent(lineCount, charCount);

      if (append) {
        sb.append(lines);
        dstPosition.appendMultilineContent(lineCount, charCount);
      }
      currentSrcLine = null;
      endOfSource = srcPosition.line >= src.size();
    }

    void processToEndOfLine(boolean append) {
      if (endOfSource) {
        return;
      }
      String srcLine = getCurrentSrcLine();
      int from = srcPosition.column;
      int charCount = srcLine.length() - from;
      boolean lastLineNoEOLMark = srcPosition.line >= src.size() - 1 && src.isMissingNewlineAtEnd();
      if (!lastLineNoEOLMark) {
        srcPosition.appendLineEndedWithEOLMark(charCount);
        endOfSource = srcPosition.line >= src.size();
      } else {
        srcPosition.appendStringWithoutEOLMark(charCount);
        endOfSource = true;
      }
      if (append) {
        sb.append(srcLine, from, srcLine.length());
        if (!lastLineNoEOLMark) {
          dstPosition.appendLineEndedWithEOLMark(charCount);
        } else {
          dstPosition.appendStringWithoutEOLMark(charCount);
        }
      }
      currentSrcLine = null;
    }

    void processLineToColumn(int to, boolean append) throws IndexOutOfBoundsException {
      if (to == 0) {
        return;
      }
      String srcLine = getCurrentSrcLine();
      if (to > srcLine.length()) {
        throw new IndexOutOfBoundsException("Parameter to is out of string");
      } else if (to == srcLine.length()) {
        if (srcPosition.line < src.size() - 1 || !src.isMissingNewlineAtEnd()) {
          throw new IndexOutOfBoundsException("The processLineToColumn shouldn't add end of line");
        }
      }
      int from = srcPosition.column;
      int charCount = to - from;
      srcPosition.appendStringWithoutEOLMark(charCount);
      if (append) {
        sb.append(srcLine, from, to);
        dstPosition.appendStringWithoutEOLMark(charCount);
      }
    }

    void appendLinesToEndOfContent() {
      processMultiline(src.size(), true);
    }

    void appendReplacement(String replacement) {
      if (replacement.length() == 0) {
        return;
      }
      sb.append(replacement);
      int lastNewLinePos = -1;
      int newLineMarkCount = 0;
      while (true) {
        int index = replacement.indexOf('\n', lastNewLinePos + 1);
        if (index < 0) {
          break;
        }
        lastNewLinePos = index;
        newLineMarkCount++;
      }
      if (newLineMarkCount > 0) {
        dstPosition.appendMultilineContent(newLineMarkCount, lastNewLinePos + 1);
      }
      dstPosition.appendStringWithoutEOLMark(replacement.length() - lastNewLinePos - 1);
    }

    boolean hasMoreLines() {
      return !endOfSource;
    }

    private String getCurrentSrcLine() {
      if (currentSrcLine == null) {
        currentSrcLine = src.getString(srcPosition.line, srcPosition.line + 1, false);
      }
      return currentSrcLine;
    }
  }

  /** The result of applying fix to a file content */
  public static class FixResult {
    /** List of edits to transform an original text to a final text (with all fixes applied) */
    public final ImmutableList<Edit> edits;
    /** Final text with all applied fixes */
    public final Text text;

    FixResult(ImmutableList<Edit> edits, Text text) {
      this.edits = edits;
      this.text = text;
    }
  }
}
