// 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.FileMode;
import com.google.gerrit.common.data.PatchSetDetail;
import com.google.gerrit.prettify.common.EditList;
import com.google.gerrit.prettify.common.SparseHtmlFile;
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;
  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();
    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 (!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));
          }
        }
      }
    }
  }

  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();

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

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

    m.openTd();
    m.nbsp();
    m.closeTd();

    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);
    } else if (numRows < 0) {
      line.reduceSize(-numRows);
      createSkipLine(row, line);
    } else {
      table.removeRow(row + loopTo);
    }
  }

  private void createSkipLine(int row, SkippedLine line) {
    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);
      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;
    }
  }
}
