// 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), script.getA().isWholeFile());
          }
        }
      }
    }
  }

  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);
      // If we got here, we must have the whole file anyway.
      createSkipLine(row + loopTo, line, true);
    } else if (numRows < 0) {
      line.reduceSize(-numRows);
      // If we got here, we must have the whole file anyway.
      createSkipLine(row, line, true);
    } else {
      table.removeRow(row + loopTo);
    }
  }

  private void createSkipLine(int row, SkippedLine line, boolean isWholeFile) {
    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 && isWholeFile) {
      // 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 if (isWholeFile) {
      p.add(l1);
      p.add(all);
      p.add(l2);
    } else {
      p.add(l1);
      p.add(new InlineLabel(" " + line.getSize() + " "));
      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;
    }
  }
}
