// Copyright (C) 2008 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.patches;

import static com.google.gerrit.client.patches.PatchLine.Type.CONTEXT;
import static com.google.gerrit.client.patches.PatchLine.Type.DELETE;
import static com.google.gerrit.client.patches.PatchLine.Type.INSERT;
import static com.google.gerrit.client.patches.PatchLine.Type.REPLACE;

import com.google.gerrit.client.Gerrit;
import com.google.gerrit.common.data.CommentDetail;
import com.google.gerrit.common.data.PatchScript;
import com.google.gerrit.common.data.PatchScript.DisplayMethod;
import com.google.gerrit.common.data.PatchScript.FileMode;
import com.google.gerrit.common.data.PatchSetDetail;
import com.google.gerrit.prettify.client.SparseHtmlFile;
import com.google.gerrit.prettify.common.EditList;
import com.google.gerrit.reviewdb.client.PatchLineComment;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.UIObject;
import com.google.gwtexpui.safehtml.client.SafeHtml;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
import org.eclipse.jgit.diff.Edit;

import java.util.ArrayList;
import java.util.Iterator;

public class SideBySideTable extends AbstractPatchContentTable {
  private static final int A = 2;
  private static final int B = 3;
  private static final int NUM_ROWS_TO_EXPAND = 10;

  private SparseHtmlFile a;
  private SparseHtmlFile b;
  private boolean isHugeFile;
  protected boolean isFileCommentBorderRowExist;

  protected void createFileCommentEditorOnSideA() {
    createCommentEditor(R_HEAD + 1, A, R_HEAD, FILE_SIDE_A);
    return;
  }

  protected void createFileCommentEditorOnSideB() {
    createCommentEditor(R_HEAD + 1, B, R_HEAD, FILE_SIDE_B);
    return;
  }

  @Override
  protected void onCellDoubleClick(final int row, int column) {
    if (column > C_ARROW && getRowItem(row) instanceof PatchLine) {
      final PatchLine line = (PatchLine) getRowItem(row);
      if (column == 1 || column == A) {
        createCommentEditor(row + 1, A, line.getLineA(), (short) 0);
      } else if (column == B || column == 4) {
        createCommentEditor(row + 1, B, line.getLineB(), (short) 1);
      }
    }
  }

  @Override
  protected void onCellSingleClick(int row, int column) {
    super.onCellSingleClick(row, column);
    if (column == 1 || column == 4) {
      onCellDoubleClick(row, column);
    }
  }

  @Override
  protected void onInsertComment(final PatchLine line) {
    final int row = getCurrentRow();
    createCommentEditor(row + 1, B, line.getLineB(), (short) 1);
  }

  @Override
  protected void render(final PatchScript script, final PatchSetDetail detail) {
    final ArrayList<Object> lines = new ArrayList<Object>();
    final SafeHtmlBuilder nc = new SafeHtmlBuilder();
    isHugeFile = script.isHugeFile();
    allocateTableHeader(script, nc);
    lines.add(null);
    if (!isDisplayBinary) {
      if (script.getFileModeA() != FileMode.FILE
          || script.getFileModeB() != FileMode.FILE) {
        openLine(nc);
        appendModeLine(nc, script.getFileModeA());
        appendModeLine(nc, script.getFileModeB());
        closeLine(nc);
        lines.add(null);
      }

      if (hasDifferences(script)) {
        int lastA = 0;
        int lastB = 0;
        final boolean ignoreWS = script.isIgnoreWhitespace();
        a = getSparseHtmlFileA(script);
        b = getSparseHtmlFileB(script);
        final boolean intraline =
            script.getDiffPrefs().isIntralineDifference()
                && script.hasIntralineDifference();
        for (final EditList.Hunk hunk : script.getHunks()) {
          if (!hunk.isStartOfFile()) {
            appendSkipLine(nc, hunk.getCurB() - lastB);
            lines.add(new SkippedLine(lastA, lastB, hunk.getCurB() - lastB));
          }

          while (hunk.next()) {
            if (hunk.isContextLine()) {
              openLine(nc);
              final SafeHtml ctx = a.getSafeHtmlLine(hunk.getCurA());
              appendLineNumber(nc, hunk.getCurA(), false);
              appendLineText(nc, CONTEXT, ctx, false, false);
              if (ignoreWS && b.contains(hunk.getCurB())) {
                appendLineText(nc, CONTEXT, b, hunk.getCurB(), false);
              } else {
                appendLineText(nc, CONTEXT, ctx, false, false);
              }
              appendLineNumber(nc, hunk.getCurB(), true);
              closeLine(nc);
              hunk.incBoth();
              lines.add(new PatchLine(CONTEXT, hunk.getCurA(), hunk.getCurB()));

            } else if (hunk.isModifiedLine()) {
              final boolean del = hunk.isDeletedA();
              final boolean ins = hunk.isInsertedB();
              final boolean full =
                  intraline && hunk.getCurEdit().getType() != Edit.Type.REPLACE;
              openLine(nc);

              if (del) {
                appendLineNumber(nc, hunk.getCurA(), false);
                appendLineText(nc, DELETE, a, hunk.getCurA(), full);
                hunk.incA();
              } else if (hunk.getCurEdit().getType() == Edit.Type.REPLACE) {
                appendLineNumber(nc, false);
                appendLineNone(nc, DELETE);
              } else {
                appendLineNumber(nc, false);
                appendLineNone(nc, CONTEXT);
              }

              if (ins) {
                appendLineText(nc, INSERT, b, hunk.getCurB(), full);
                appendLineNumber(nc, hunk.getCurB(), true);
                hunk.incB();
              } else if (hunk.getCurEdit().getType() == Edit.Type.REPLACE) {
                appendLineNone(nc, INSERT);
                appendLineNumber(nc, true);
              } else {
                appendLineNone(nc, CONTEXT);
                appendLineNumber(nc, true);
              }

              closeLine(nc);

              if (del && ins) {
                lines.add(new PatchLine(REPLACE, hunk.getCurA(), hunk.getCurB()));
              } else if (del) {
                lines.add(new PatchLine(DELETE, hunk.getCurA(), -1));
              } else if (ins) {
                lines.add(new PatchLine(INSERT, -1, hunk.getCurB()));
              }
            }
          }
          lastA = hunk.getCurA();
          lastB = hunk.getCurB();
        }
        if (lastB != b.size()) {
          appendSkipLine(nc, b.size() - lastB);
          lines.add(new SkippedLine(lastA, lastB, b.size() - lastB));
        }
      }
    } else {
      // Display the patch header for binary
      for (final String line : script.getPatchHeader()) {
        appendFileHeader(nc, line);
      }
      // If there is a safe picture involved, we show it
      if (script.getDisplayMethodA() == DisplayMethod.IMG
          || script.getDisplayMethodB() == DisplayMethod.IMG) {
        appendImageLine(script, nc);
      }
    }
    if (!hasDifferences(script)) {
      appendNoDifferences(nc);
    }
    resetHtml(nc);
    populateTableHeader(script, detail);
    if (hasDifferences(script)) {
      initScript(script);
      if (!isDisplayBinary) {
        for (int row = 0; row < lines.size(); row++) {
          setRowItem(row, lines.get(row));
          if (lines.get(row) instanceof SkippedLine) {
            createSkipLine(row, (SkippedLine) lines.get(row), isHugeFile);
          }
        }
      }
    }
  }

  private SafeHtml createImage(String url) {
    SafeHtmlBuilder m = new SafeHtmlBuilder();
    m.openElement("img");
    m.setAttribute("src", url);
    m.closeElement("img");
    return m.toSafeHtml();
  }

  private void appendImageLine(final PatchScript script,
      final SafeHtmlBuilder m) {
    m.openTr();
    m.setAttribute("valign", "center");
    m.setAttribute("align", "center");

    m.openTd();
    m.setStyleName(Gerrit.RESOURCES.css().iconCell());
    m.closeTd();

    appendLineNumber(m, false);
    if (script.getDisplayMethodA() == DisplayMethod.IMG) {
      final String url = getUrlA();
      appendLineText(m, DELETE, createImage(url), false, true);
    } else {
      appendLineNone(m, DELETE);
    }
    if (script.getDisplayMethodB() == DisplayMethod.IMG) {
      final String url = getUrlB();
      appendLineText(m, INSERT, createImage(url), false, true);
    } else {
      appendLineNone(m, INSERT);
    }

    appendLineNumber(m, true);
    m.closeTr();
  }

  private void populateTableHeader(final PatchScript script,
      final PatchSetDetail detail) {
    initHeaders(script, detail);
    table.setWidget(R_HEAD, A, headerSideA);
    table.setWidget(R_HEAD, B, headerSideB);

    // Populate icons to lineNumber column header.
    if (headerSideA.isFileOrCommitMessage()) {
      table.setWidget(R_HEAD, A - 1, iconA);
    }
    if (headerSideB.isFileOrCommitMessage()) {
      table.setWidget(R_HEAD, B + 1, iconB);
    }
  }

  private void appendModeLine(final SafeHtmlBuilder nc, final FileMode mode) {
    nc.openTd();
    nc.setStyleName(Gerrit.RESOURCES.css().lineNumber());
    nc.nbsp();
    nc.closeTd();

    nc.openTd();
    nc.addStyleName(Gerrit.RESOURCES.css().fileLine());
    nc.addStyleName(Gerrit.RESOURCES.css().fileLineMode());
    switch(mode){
      case FILE:
        nc.nbsp();
        break;
      case SYMLINK:
        nc.append(PatchUtil.C.fileTypeSymlink());
        break;
      case GITLINK:
        nc.append(PatchUtil.C.fileTypeGitlink());
        break;
    }
    nc.closeTd();
  }

  @Override
  protected PatchScreen.Type getPatchScreenType() {
    return PatchScreen.Type.SIDE_BY_SIDE;
  }

  @Override
  public void display(final CommentDetail cd, boolean expandComments) {
    if (cd.isEmpty()) {
      return;
    }
    setAccountInfoCache(cd.getAccounts());

    for (int row = 0; row < table.getRowCount();) {
      final Iterator<PatchLineComment> ai;
      final Iterator<PatchLineComment> bi;

      if (row == R_HEAD) {
        ai = cd.getForA(R_HEAD).iterator();
        bi = cd.getForB(R_HEAD).iterator();
      } else if (getRowItem(row) instanceof PatchLine) {
        final PatchLine pLine = (PatchLine) getRowItem(row);
        ai = cd.getForA(pLine.getLineA()).iterator();
        bi = cd.getForB(pLine.getLineB()).iterator();
      } else {
        row++;
        continue;
      }

      row++;
      while (ai.hasNext() && bi.hasNext()) {
        final PatchLineComment ac = ai.next();
        final PatchLineComment bc = bi.next();
        if (ac.getLine() == R_HEAD) {
          insertFileCommentRow(row);
        } else {
          insertRow(row);
        }
        bindComment(row, A, ac, !ai.hasNext(), expandComments);
        bindComment(row, B, bc, !bi.hasNext(), expandComments);
        row++;
      }

      row = finish(ai, row, A, expandComments);
      row = finish(bi, row, B, expandComments);
    }
  }

  private void defaultStyle(final int row, final CellFormatter fmt) {
    fmt.addStyleName(row, A - 1, Gerrit.RESOURCES.css().lineNumber());
    fmt.addStyleName(row, A, Gerrit.RESOURCES.css().diffText());
    if (isDisplayBinary) {
      fmt.addStyleName(row, A, Gerrit.RESOURCES.css().diffTextForBinaryInSideBySide());
    }
    fmt.addStyleName(row, B, Gerrit.RESOURCES.css().diffText());
    fmt.addStyleName(row, B + 1, Gerrit.RESOURCES.css().lineNumber());
    fmt.addStyleName(row, B + 1, Gerrit.RESOURCES.css().rightmost());
  }

  @Override
  protected void insertRow(final int row) {
    super.insertRow(row);
    final CellFormatter fmt = table.getCellFormatter();
    defaultStyle(row, fmt);
  }

  @Override
  protected void insertFileCommentRow(final int row) {
    table.insertRow(row);
    final CellFormatter fmt = table.getCellFormatter();
    fmt.addStyleName(row, C_ARROW, Gerrit.RESOURCES.css().iconCellOfFileCommentRow());
    defaultStyle(row, fmt);

    fmt.addStyleName(row, C_ARROW, //
        Gerrit.RESOURCES.css().cellsNextToFileComment());
    fmt.addStyleName(row, A - 1, //
        Gerrit.RESOURCES.css().cellsNextToFileComment());
    fmt.addStyleName(row, B + 1, //
        Gerrit.RESOURCES.css().cellsNextToFileComment());
    createFileCommentBorderRow(row);
  }

  private void createFileCommentBorderRow(final int row) {
    if (row == 1 && !isFileCommentBorderRowExist) {
      isFileCommentBorderRowExist = true;
      table.insertRow(R_HEAD + 2);

      final CellFormatter fmt = table.getCellFormatter();

      fmt.addStyleName(R_HEAD + 2, C_ARROW, //
          Gerrit.RESOURCES.css().iconCellOfFileCommentRow());
      defaultStyle(R_HEAD + 2, fmt);

      final Element iconCell = fmt.getElement(R_HEAD + 2, C_ARROW);
      UIObject.setStyleName(DOM.getParent(iconCell), Gerrit.RESOURCES.css()
          .fileCommentBorder(), true);
    }
  }

  private int finish(final Iterator<PatchLineComment> i, int row, final int col, boolean expandComment) {
    while (i.hasNext()) {
      final PatchLineComment c = i.next();
      if (c.getLine() == R_HEAD) {
        insertFileCommentRow(row);
      } else {
        insertRow(row);
      }
      bindComment(row, col, c, !i.hasNext(), expandComment);
      row++;
    }
    return row;
  }

  private void allocateTableHeader(PatchScript script, final SafeHtmlBuilder m) {
    m.openTr();

    m.openTd();
    m.addStyleName(Gerrit.RESOURCES.css().iconCell());
    m.addStyleName(Gerrit.RESOURCES.css().fileColumnHeader());
    m.closeTd();

    m.openTd();
    m.setStyleName(Gerrit.RESOURCES.css().lineNumber());
    m.addStyleName(Gerrit.RESOURCES.css().fileColumnHeader());
    m.nbsp();
    m.closeTd();

    m.openTd();
    m.setStyleName(Gerrit.RESOURCES.css().fileColumnHeader());
    m.addStyleName(Gerrit.RESOURCES.css().fileLine());
    m.closeTd();

    m.openTd();
    m.setStyleName(Gerrit.RESOURCES.css().fileColumnHeader());
    m.addStyleName(Gerrit.RESOURCES.css().fileLine());
    m.closeTd();

    m.openTd();
    m.setStyleName(Gerrit.RESOURCES.css().lineNumber());
    m.addStyleName(Gerrit.RESOURCES.css().fileColumnHeader());
    m.addStyleName(Gerrit.RESOURCES.css().rightmost());
    m.closeTd();

    m.closeTr();
  }

  private void appendFileHeader(final SafeHtmlBuilder m, final String line) {
    m.openTr();

    m.openTd();
    m.addStyleName(Gerrit.RESOURCES.css().iconCell());
    m.closeTd();

    appendLineNumber(m, false);

    m.openTd();
    m.setStyleName(Gerrit.RESOURCES.css().sideBySideTableBinaryHeader());
    m.setAttribute("colspan", 2);
    m.append(line);
    m.closeTd();

    appendLineNumber(m, true);

    m.closeTr();
  }

  private void appendSkipLine(final SafeHtmlBuilder m, final int skipCnt) {
    m.openTr();

    m.openTd();
    m.setStyleName(Gerrit.RESOURCES.css().iconCell());
    m.addStyleName(Gerrit.RESOURCES.css().skipLine());
    m.closeTd();

    m.openTd();
    m.setStyleName(Gerrit.RESOURCES.css().skipLine());
    m.setAttribute("colspan", 4);
    m.closeTd();
    m.closeTr();
  }

  private ClickHandler expandAllListener = new ClickHandler() {
    @Override
    public void onClick(ClickEvent event) {
      expand(event, 0);
    }
  };

  private ClickHandler expandBeforeListener = new ClickHandler() {
    @Override
    public void onClick(ClickEvent event) {
      expand(event, NUM_ROWS_TO_EXPAND);
    }
  };

  private ClickHandler expandAfterListener = new ClickHandler() {
    @Override
    public void onClick(ClickEvent event) {
      expand(event, -NUM_ROWS_TO_EXPAND);
    }
  };

  private void expand(ClickEvent event, final int numRows) {
    int row = table.getCellForEvent(event).getRowIndex();
    if (!(getRowItem(row) instanceof SkippedLine)) {
      return;
    }

    SkippedLine line = (SkippedLine) getRowItem(row);
    int loopTo = numRows;
    if (numRows == 0) {
      loopTo = line.getSize();
    } else if (numRows < 0) {
      loopTo = -numRows;
    }
    int offset = 0;
    if (numRows < 0) {
      offset = 1;
    }

    CellFormatter fmt = table.getCellFormatter();
    for (int i = 0 + offset; i < loopTo + offset; i++) {
      insertRow(row + i);
      table.getRowFormatter().setVerticalAlign(row + i,
          HasVerticalAlignment.ALIGN_TOP);
      int lineA = line.getStartA() + i;
      int lineB = line.getStartB() + i;
      if (numRows < 0) {
        lineA = line.getStartA() + line.getSize() + numRows + i - offset;
        lineB = line.getStartB() + line.getSize() + numRows + i - offset;
      }

      table.setHTML(row + i, A - 1, "<a href=\"javascript:;\">" + (lineA + 1) + "</a>");
      fmt.addStyleName(row + i, A - 1, Gerrit.RESOURCES.css().lineNumber());

      table.setHTML(row + i, A, a.getSafeHtmlLine(lineA).asString());
      fmt.addStyleName(row + i, A, Gerrit.RESOURCES.css().fileLine());
      fmt.addStyleName(row + i, A, Gerrit.RESOURCES.css().fileLineCONTEXT());

      table.setHTML(row + i, B, b.getSafeHtmlLine(lineB).asString());
      fmt.addStyleName(row + i, B, Gerrit.RESOURCES.css().fileLine());
      fmt.addStyleName(row + i, B, Gerrit.RESOURCES.css().fileLineCONTEXT());

      table.setHTML(row + i, B + 1, "<a href=\"javascript:;\">" + (lineB + 1) + "</a>");
      fmt.addStyleName(row + i, B + 1, Gerrit.RESOURCES.css().lineNumber());

      setRowItem(row + i, new PatchLine(CONTEXT, lineA, lineB));
    }

    if (numRows > 0) {
      line.incrementStart(numRows);
      createSkipLine(row + loopTo, line, isHugeFile);
    } else if (numRows < 0) {
      line.reduceSize(-numRows);
      createSkipLine(row, line, isHugeFile);
    } else {
      table.removeRow(row + loopTo);
    }
  }

  private void createSkipLine(int row, SkippedLine line, boolean isHugeFile) {
    FlowPanel p = new FlowPanel();
    InlineLabel l1 = new InlineLabel(" " + PatchUtil.C.patchSkipRegionStart() + " ");
    InlineLabel l2 = new InlineLabel(" " + PatchUtil.C.patchSkipRegionEnd() + " ");

    Anchor all = new Anchor(String.valueOf(line.getSize()));
    all.addClickHandler(expandAllListener);
    all.setStyleName(Gerrit.RESOURCES.css().skipLine());

    if (line.getSize() > 30) {
      // Only show the expand before/after if skipped more than 30 lines.
      Anchor b = new Anchor(PatchUtil.M.expandBefore(NUM_ROWS_TO_EXPAND), true);
      Anchor a = new Anchor(PatchUtil.M.expandAfter(NUM_ROWS_TO_EXPAND), true);

      b.addClickHandler(expandBeforeListener);
      a.addClickHandler(expandAfterListener);

      b.setStyleName(Gerrit.RESOURCES.css().skipLine());
      a.setStyleName(Gerrit.RESOURCES.css().skipLine());

      p.add(b);
      p.add(l1);
      if (isHugeFile) {
        p.add(new InlineLabel(" " + line.getSize() + " "));
      } else {
        p.add(all);
      }
      p.add(l2);
      p.add(a);
    } else {
      p.add(l1);
      p.add(all);
      p.add(l2);
    }
    table.setWidget(row, 1, p);
  }

  private void openLine(final SafeHtmlBuilder m) {
    m.openTr();
    m.setAttribute("valign", "top");

    m.openTd();
    m.setStyleName(Gerrit.RESOURCES.css().iconCell());
    m.closeTd();
  }

  private void appendLineNumber(SafeHtmlBuilder m, boolean right) {
    m.openTd();
    m.setStyleName(Gerrit.RESOURCES.css().lineNumber());
    if (right) {
      m.addStyleName(Gerrit.RESOURCES.css().rightmost());
    }
    m.closeTd();
  }

  private void appendLineNumber(SafeHtmlBuilder m, int lineNumberMinusOne, boolean right) {
    m.openTd();
    m.setStyleName(Gerrit.RESOURCES.css().lineNumber());
    if (right) {
      m.addStyleName(Gerrit.RESOURCES.css().rightmost());
    }
    m.append(SafeHtml.asis("<a href=\"javascript:;\">"+ (lineNumberMinusOne + 1) + "</a>"));
    m.closeTd();
  }

  private void appendLineText(final SafeHtmlBuilder m,
      final PatchLine.Type type, final SparseHtmlFile src, final int i,
      final boolean fullBlock) {
    appendLineText(m, type, src.getSafeHtmlLine(i), src.hasTrailingEdit(i), fullBlock);
  }

  private void appendLineText(final SafeHtmlBuilder m,
      final PatchLine.Type type, final SafeHtml lineHtml,
      final boolean trailingEdit, final boolean fullBlock) {
    m.openTd();
    m.addStyleName(Gerrit.RESOURCES.css().fileLine());
    switch (type) {
      case CONTEXT:
        m.addStyleName(Gerrit.RESOURCES.css().fileLineCONTEXT());
        break;
      case DELETE:
        m.addStyleName(Gerrit.RESOURCES.css().fileLineDELETE());
        if (trailingEdit || fullBlock) {
          m.addStyleName("wdd");
        }
        break;
      case INSERT:
        m.addStyleName(Gerrit.RESOURCES.css().fileLineINSERT());
        if (trailingEdit || fullBlock) {
          m.addStyleName("wdi");
        }
        break;
      case REPLACE:
        break;
    }
    m.append(lineHtml);
    m.closeTd();
  }

  private void appendLineNone(final SafeHtmlBuilder m, final PatchLine.Type type) {
    m.openTd();
    m.addStyleName(Gerrit.RESOURCES.css().fileLine());
    switch (type != null ? type : PatchLine.Type.CONTEXT) {
      case DELETE:
        m.addStyleName(Gerrit.RESOURCES.css().fileLineDELETE());
        break;
      case INSERT:
        m.addStyleName(Gerrit.RESOURCES.css().fileLineINSERT());
        break;
      default:
        m.addStyleName(Gerrit.RESOURCES.css().fileLineNone());
        break;
    }
    m.closeTd();
  }

  private void closeLine(final SafeHtmlBuilder m) {
    m.closeTr();
  }

  @Override
  protected void destroyCommentRow(final int row) {
    super.destroyCommentRow(row);
    if (row == R_HEAD + 1) {
      table.removeRow(row);
      isFileCommentBorderRowExist = false;
    }
  }
}
