// Copyright (C) 2013 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.client.diff;

import static com.google.gerrit.client.diff.DisplaySide.A;
import static com.google.gerrit.client.diff.DisplaySide.B;
import static com.google.gerrit.client.diff.OverviewBar.MarkType.DELETE;
import static com.google.gerrit.client.diff.OverviewBar.MarkType.EDIT;
import static com.google.gerrit.client.diff.OverviewBar.MarkType.INSERT;

import com.google.gerrit.client.diff.DiffInfo.Region;
import com.google.gerrit.client.diff.DiffInfo.Span;
import com.google.gerrit.client.rpc.Natives;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.JsArrayString;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.EventListener;

import net.codemirror.lib.CodeMirror;
import net.codemirror.lib.CodeMirror.LineClassWhere;
import net.codemirror.lib.Configuration;
import net.codemirror.lib.LineCharacter;
import net.codemirror.lib.LineWidget;
import net.codemirror.lib.TextMarker;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/** Colors modified regions for {@link SideBySide2}. */
class ChunkManager {
  private static final String DATA_LINES = "_cs2h";
  private static double guessedLineHeightPx = 15;
  private static final JavaScriptObject focusA = initOnClick(A);
  private static final JavaScriptObject focusB = initOnClick(B);
  private static final native JavaScriptObject initOnClick(DisplaySide s) /*-{
    return $entry(function(e){
      @com.google.gerrit.client.diff.ChunkManager::focus(
        Lcom/google/gwt/dom/client/NativeEvent;
        Lcom/google/gerrit/client/diff/DisplaySide;)(e,s)
    });
  }-*/;

  private static void focus(NativeEvent event, DisplaySide side) {
    Element e = Element.as(event.getEventTarget());
    for (e = DOM.getParent(e); e != null; e = DOM.getParent(e)) {
      EventListener l = DOM.getEventListener(e);
      if (l instanceof SideBySide2) {
        ((SideBySide2) l).getCmFromSide(side).focus();
        event.stopPropagation();
      }
    }
  };

  static void focusOnClick(Element e, DisplaySide side) {
    onClick(e, side == A ? focusA : focusB);
  }

  private static final native void onClick(Element e, JavaScriptObject f)
  /*-{ e.onclick = f }-*/;

  private final SideBySide2 host;
  private final CodeMirror cmA;
  private final CodeMirror cmB;
  private final OverviewBar sidePanel;
  private final LineMapper mapper;

  private List<DiffChunkInfo> chunks;
  private List<TextMarker> markers;
  private List<Runnable> undo;
  private List<LineWidget> padding;
  private List<Element> paddingDivs;

  ChunkManager(SideBySide2 host,
      CodeMirror cmA,
      CodeMirror cmB,
      OverviewBar sidePanel) {
    this.host = host;
    this.cmA = cmA;
    this.cmB = cmB;
    this.sidePanel = sidePanel;
    this.mapper = new LineMapper();
  }

  LineMapper getLineMapper() {
    return mapper;
  }

  DiffChunkInfo getFirst() {
    return !chunks.isEmpty() ? chunks.get(0) : null;
  }

  void reset() {
    mapper.reset();
    for (TextMarker m : markers) {
      m.clear();
    }
    for (Runnable r : undo) {
      r.run();
    }
    for (LineWidget w : padding) {
      w.clear();
    }
  }

  void render(DiffInfo diff) {
    chunks = new ArrayList<>();
    markers = new ArrayList<>();
    undo = new ArrayList<>();
    padding = new ArrayList<>();
    paddingDivs = new ArrayList<>();

    String diffColor = diff.meta_a() == null || diff.meta_b() == null
        ? DiffTable.style.intralineBg()
        : DiffTable.style.diff();

    for (Region current : Natives.asList(diff.content())) {
      if (current.ab() != null) {
        mapper.appendCommon(current.ab().length());
      } else if (current.skip() > 0) {
        mapper.appendCommon(current.skip());
      } else if (current.common()) {
        mapper.appendCommon(current.b().length());
      } else {
        render(current, diffColor);
      }
    }

    if (paddingDivs.isEmpty()) {
      paddingDivs = null;
    }
  }

  void adjustPadding() {
    if (paddingDivs != null) {
      double h = host.getLineHeightPx();
      for (Element div : paddingDivs) {
        int lines = div.getPropertyInt(DATA_LINES);
        div.getStyle().setHeight(lines * h, Unit.PX);
      }
      for (LineWidget w : padding) {
        w.changed();
      }
      paddingDivs = null;
      guessedLineHeightPx = h;
    }
  }

  private void render(Region region, String diffColor) {
    int startA = mapper.getLineA();
    int startB = mapper.getLineB();

    JsArrayString a = region.a();
    JsArrayString b = region.b();
    int aLen = a != null ? a.length() : 0;
    int bLen = b != null ? b.length() : 0;

    String color = a == null || b == null
        ? diffColor
        : DiffTable.style.intralineBg();

    colorLines(cmA, color, startA, aLen);
    colorLines(cmB, color, startB, bLen);
    markEdit(cmA, startA, a, region.edit_a());
    markEdit(cmB, startB, b, region.edit_b());
    addPadding(cmA, startA + aLen - 1, bLen - aLen);
    addPadding(cmB, startB + bLen - 1, aLen - bLen);
    addGutterTag(region, startA, startB);
    mapper.appendReplace(aLen, bLen);

    int endA = mapper.getLineA() - 1;
    int endB = mapper.getLineB() - 1;
    if (aLen > 0) {
      addDiffChunk(cmB, endB, endA, aLen, bLen > 0);
    }
    if (bLen > 0) {
      addDiffChunk(cmA, endA, endB, bLen, aLen > 0);
    }
  }

  private void addGutterTag(Region region, int startA, int startB) {
    if (region.a() == null) {
      sidePanel.add(cmB, startB, region.b().length(), INSERT);
    } else if (region.b() == null) {
      sidePanel.add(cmA, startA, region.a().length(), DELETE);
    } else {
      sidePanel.add(cmB, startB, region.b().length(), EDIT);
    }
  }

  private void markEdit(CodeMirror cm, int startLine,
      JsArrayString lines, JsArray<Span> edits) {
    if (lines == null || edits == null) {
      return;
    }

    EditIterator iter = new EditIterator(lines, startLine);
    Configuration bg = Configuration.create()
        .set("className", DiffTable.style.intralineBg())
        .set("readOnly", true);

    Configuration diff = Configuration.create()
        .set("className", DiffTable.style.diff())
        .set("readOnly", true);

    LineCharacter last = CodeMirror.pos(0, 0);
    for (Span span : Natives.asList(edits)) {
      LineCharacter from = iter.advance(span.skip());
      LineCharacter to = iter.advance(span.mark());
      if (from.getLine() == last.getLine()) {
        markers.add(cm.markText(last, from, bg));
      } else {
        markers.add(cm.markText(CodeMirror.pos(from.getLine(), 0), from, bg));
      }
      markers.add(cm.markText(from, to, diff));
      last = to;
      colorLines(cm, LineClassWhere.BACKGROUND,
          DiffTable.style.diff(),
          from.getLine(), to.getLine());
    }
  }

  private void colorLines(CodeMirror cm, String color, int line, int cnt) {
    colorLines(cm, LineClassWhere.WRAP, color, line, line + cnt);
  }

  private void colorLines(final CodeMirror cm, final LineClassWhere where,
      final String className, final int start, final int end) {
    if (start < end) {
      for (int line = start; line < end; line++) {
        cm.addLineClass(line, where, className);
      }
      undo.add(new Runnable() {
        @Override
        public void run() {
          for (int line = start; line < end; line++) {
            cm.removeLineClass(line, where, className);
          }
        }
      });
    }
  }

  /**
   * Insert a new padding div below the given line.
   *
   * @param cm parent CodeMirror to add extra space into.
   * @param line line to put the padding below.
   * @param len number of lines to pad. Padding is inserted only if
   *        {@code len >= 1}.
   */
  private void addPadding(CodeMirror cm, int line, final int len) {
    if (0 < len) {
      Element pad = DOM.createDiv();
      pad.setClassName(DiffTable.style.padding());
      pad.setPropertyInt(DATA_LINES, len);
      pad.getStyle().setHeight(guessedLineHeightPx * len, Unit.PX);
      focusOnClick(pad, cm.side());
      paddingDivs.add(pad);
      padding.add(cm.addLineWidget(
        line == -1 ? 0 : line,
        pad,
        Configuration.create()
          .set("coverGutter", true)
          .set("noHScroll", true)
          .set("above", line == -1)));
    }
  }

  private void addDiffChunk(CodeMirror cmToPad, int lineToPad,
      int lineOnOther, int chunkSize, boolean edit) {
    chunks.add(new DiffChunkInfo(host.otherCm(cmToPad).side(),
        lineOnOther - chunkSize + 1, lineOnOther, edit));
  }

  Runnable diffChunkNav(final CodeMirror cm, final Direction dir) {
    return new Runnable() {
      @Override
      public void run() {
        int line = cm.hasActiveLine() ? cm.getLineNumber(cm.getActiveLine()) : 0;
        int res = Collections.binarySearch(
                chunks,
                new DiffChunkInfo(cm.side(), line, 0, false),
                getDiffChunkComparator());
        if (res < 0) {
          res = -res - (dir == Direction.PREV ? 1 : 2);
        }
        res = res + (dir == Direction.PREV ? -1 : 1);
        if (res < 0 || chunks.size() <= res) {
          return;
        }

        DiffChunkInfo lookUp = chunks.get(res);
        // If edit, skip the deletion chunk and set focus on the insertion one.
        if (lookUp.isEdit() && lookUp.getSide() == A) {
          res = res + (dir == Direction.PREV ? -1 : 1);
          if (res < 0 || chunks.size() <= res) {
            return;
          }
        }

        DiffChunkInfo target = chunks.get(res);
        CodeMirror targetCm = host.getCmFromSide(target.getSide());
        targetCm.setCursor(LineCharacter.create(target.getStart()));
        targetCm.focus();
        targetCm.scrollToY(
            targetCm.heightAtLine(target.getStart(), "local") -
            0.5 * cmB.getScrollbarV().getClientHeight());
      }
    };
  }

  private Comparator<DiffChunkInfo> getDiffChunkComparator() {
    // Chunks are ordered by their starting line. If it's a deletion,
    // use its corresponding line on the revision side for comparison.
    // In the edit case, put the deletion chunk right before the
    // insertion chunk. This placement guarantees well-ordering.
    return new Comparator<DiffChunkInfo>() {
      @Override
      public int compare(DiffChunkInfo a, DiffChunkInfo b) {
        if (a.getSide() == b.getSide()) {
          return a.getStart() - b.getStart();
        } else if (a.getSide() == A) {
          int comp = mapper.lineOnOther(a.getSide(), a.getStart())
              .getLine() - b.getStart();
          return comp == 0 ? -1 : comp;
        } else {
          int comp = a.getStart() -
              mapper.lineOnOther(b.getSide(), b.getStart()).getLine();
          return comp == 0 ? 1 : comp;
        }
      }
    };
  }

  DiffChunkInfo getDiffChunk(DisplaySide side, int line) {
    int res = Collections.binarySearch(
        chunks,
        new DiffChunkInfo(side, line, 0, false), // Dummy DiffChunkInfo
        getDiffChunkComparator());
    if (res >= 0) {
      return chunks.get(res);
    } else { // The line might be within a DiffChunk
      res = -res - 1;
      if (res > 0) {
        DiffChunkInfo info = chunks.get(res - 1);
        if (info.getSide() == side && info.getStart() <= line &&
            line <= info.getEnd()) {
          return info;
        }
      }
    }
    return null;
  }
}
