// 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 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.PatchSetDetail;
import com.google.gerrit.prettify.client.SparseHtmlFile;
import com.google.gerrit.prettify.common.EditList;
import com.google.gerrit.prettify.common.EditList.Hunk;
import com.google.gerrit.reviewdb.client.PatchLineComment;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
import com.google.gwt.user.client.ui.UIObject;
import com.google.gwtexpui.safehtml.client.SafeHtml;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;

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

public class UnifiedDiffTable extends AbstractPatchContentTable {
  private static final int PC = 3;
  private static final Comparator<PatchLineComment> BY_DATE =
      new Comparator<PatchLineComment>() {
        public int compare(final PatchLineComment o1, final PatchLineComment o2) {
          return o1.getWrittenOn().compareTo(o2.getWrittenOn());
        }
      };

  protected boolean isFileCommentBorderRowExist;
  // Cursors.
  protected int rowOfTableHeaderB;
  protected int borderRowOfFileComment;

  @Override
  protected void onCellDoubleClick(final int row, final int column) {
    if (column > C_ARROW && getRowItem(row) instanceof PatchLine) {
      final PatchLine pl = (PatchLine) getRowItem(row);
      switch (pl.getType()) {
        case DELETE:
        case CONTEXT:
          createCommentEditor(row + 1, PC, pl.getLineA(), (short) 0);
          break;
        case INSERT:
          createCommentEditor(row + 1, PC, pl.getLineB(), (short) 1);
          break;
        case REPLACE:
          break;
      }
    }
  }

  @Override
  protected void updateCursor(final PatchLineComment newComment) {
    if (newComment.getLine() == R_HEAD) {
      final PatchSet.Id psId =
          newComment.getKey().getParentKey().getParentKey();
      switch (newComment.getSide()) {
        case FILE_SIDE_A:
          if (idSideA == null && idSideB.equals(psId)) {
            rowOfTableHeaderB++;
            borderRowOfFileComment++;
            return;
          }
          break;
        case FILE_SIDE_B:
          if (idSideA != null && idSideA.equals(psId)) {
            rowOfTableHeaderB++;
            borderRowOfFileComment++;
            return;
          }
          if (idSideB.equals(psId)) {
            borderRowOfFileComment++;
            return;
          }
      }
    }
  }

  @Override
  protected void onCellSingleClick(int row, int column) {
    super.onCellSingleClick(row, column);
    if (column == 1 || column == 2) {
      if (!"".equals(table.getText(row, column))) {
        onCellDoubleClick(row, column);
      }
    }
  }

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

  @Override
  public void remove(CommentEditorPanel panel) {
    super.remove(panel);
    if (panel.getComment().getLine() == AbstractPatchContentTable.R_HEAD) {
      final PatchSet.Id psId =
          panel.getComment().getKey().getParentKey().getParentKey();
      switch (panel.getComment().getSide()) {
        case FILE_SIDE_A:
          if (idSideA == null && idSideB.equals(psId)) {
            rowOfTableHeaderB--;
            borderRowOfFileComment--;
            return;
          }
          break;
        case FILE_SIDE_B:
          if (idSideA != null && idSideA.equals(psId)) {
            rowOfTableHeaderB--;
            borderRowOfFileComment--;
            return;
          }
          if (idSideB.equals(psId)) {
            borderRowOfFileComment--;
            return;
          }
      }
    }
  }

  @Override
  protected void onInsertComment(final PatchLine pl) {
    final int row = getCurrentRow();
    switch (pl.getType()) {
      case DELETE:
      case CONTEXT:
        createCommentEditor(row + 1, PC, pl.getLineA(), (short) 0);
        break;
      case INSERT:
        createCommentEditor(row + 1, PC, pl.getLineB(), (short) 1);
        break;
      case REPLACE:
        break;
    }
  }

  private void appendImgTag(SafeHtmlBuilder nc, String url) {
    nc.openElement("img");
    nc.setAttribute("src", url);
    nc.closeElement("img");
  }

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

  protected void createFileCommentEditorOnSideB() {
    createCommentEditor(rowOfTableHeaderB + 1, PC, R_HEAD, FILE_SIDE_B);
    createFileCommentBorderRow();
  }

  private void populateTableHeader(final PatchScript script,
      final PatchSetDetail detail) {
    initHeaders(script, detail);
    table.setWidget(R_HEAD, PC, headerSideA);
    table.setWidget(rowOfTableHeaderB, PC, headerSideB);
    table.getFlexCellFormatter().addStyleName(R_HEAD, PC,
        Gerrit.RESOURCES.css().unifiedTableHeader());
    table.getFlexCellFormatter().addStyleName(rowOfTableHeaderB, PC,
        Gerrit.RESOURCES.css().unifiedTableHeader());

    // Add icons to lineNumber column header
    if (headerSideA.isFileOrCommitMessage()) {
      table.setWidget(R_HEAD, 1, iconA);
    }
    if (headerSideB.isFileOrCommitMessage()) {
      table.setWidget(rowOfTableHeaderB, 2, iconB);
    }
  }

  private void allocateTableHeader(SafeHtmlBuilder nc) {
    rowOfTableHeaderB = 1;
    borderRowOfFileComment = 2;
    for (int i = R_HEAD; i < borderRowOfFileComment; i++) {
      openTableHeaderLine(nc);
      padLineNumberOnTableHeaderForSideA(nc);
      padLineNumberOnTableHeaderForSideB(nc);
      nc.openTd();
      nc.setStyleName(Gerrit.RESOURCES.css().fileLine());
      nc.addStyleName(Gerrit.RESOURCES.css().fileColumnHeader());
      nc.closeTd();
      closeLine(nc);
    }
  }

  @Override
  protected void render(final PatchScript script, final PatchSetDetail detail) {
    final SafeHtmlBuilder nc = new SafeHtmlBuilder();
    allocateTableHeader(nc);

    // Display the patch header
    for (final String line : script.getPatchHeader()) {
      appendFileHeader(nc, line);
    }
    final ArrayList<PatchLine> lines = new ArrayList<PatchLine>();

    if (hasDifferences(script)) {
      if (script.getDisplayMethodA() == DisplayMethod.IMG
          || script.getDisplayMethodB() == DisplayMethod.IMG) {
        appendImageDifferences(script, nc);
      } else if (!isDisplayBinary) {
        appendTextDifferences(script, nc, lines);
      }
    } else {
      appendNoDifferences(nc);
    }

    resetHtml(nc);
    populateTableHeader(script, detail);
    if (hasDifferences(script)) {
      initScript(script);
      if (!isDisplayBinary) {
        int row = script.getPatchHeader().size();
        final CellFormatter fmt = table.getCellFormatter();
        final Iterator<PatchLine> iLine = lines.iterator();
        while (iLine.hasNext()) {
          final PatchLine l = iLine.next();
          final String n;
          switch (l.getType()) {
            case CONTEXT:
              n = Gerrit.RESOURCES.css().diffTextCONTEXT();
              break;
            case DELETE:
              n = Gerrit.RESOURCES.css().diffTextDELETE();
              break;
            case INSERT:
              n = Gerrit.RESOURCES.css().diffTextINSERT();
              break;
            default:
              continue;
          }
          while (!fmt.getStyleName(row, PC).contains(n)) {
            row++;
          }
          setRowItem(row++, l);
        }
      }
    }
  }

  private void appendImageLine(final SafeHtmlBuilder nc, final String url,
      final boolean syntaxHighlighting, final boolean isInsert) {
    nc.openTr();
    nc.setAttribute("valign", "center");
    nc.setAttribute("align", "center");

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

    padLineNumberForSideA(nc);
    padLineNumberForSideB(nc);

    nc.openTd();
    nc.setStyleName(Gerrit.RESOURCES.css().fileLine());
    if (isInsert) {
      setStyleInsert(nc, syntaxHighlighting);
    } else {
      setStyleDelete(nc, syntaxHighlighting);
    }
    appendImgTag(nc, url);
    nc.closeTd();

    nc.closeTr();
  }

  private void appendImageDifferences(final PatchScript script,
      final SafeHtmlBuilder nc) {
    final boolean syntaxHighlighting =
        script.getDiffPrefs().isSyntaxHighlighting();
    if (script.getDisplayMethodA() == DisplayMethod.IMG) {
      final String url = getUrlA();
      appendImageLine(nc, url, syntaxHighlighting, false);
    }
    if (script.getDisplayMethodB() == DisplayMethod.IMG) {
      final String url = getUrlB();
      appendImageLine(nc, url, syntaxHighlighting, true);
    }
  }

  private void appendTextDifferences(final PatchScript script,
      final SafeHtmlBuilder nc, final ArrayList<PatchLine> lines) {
    final SparseHtmlFile a = getSparseHtmlFileA(script);
    final SparseHtmlFile b = getSparseHtmlFileB(script);
    final boolean syntaxHighlighting =
        script.getDiffPrefs().isSyntaxHighlighting();
    for (final EditList.Hunk hunk : script.getHunks()) {
      appendHunkHeader(nc, hunk);
      while (hunk.next()) {
        if (hunk.isContextLine()) {
          openLine(nc);
          appendLineNumberForSideA(nc, hunk.getCurA());
          appendLineNumberForSideB(nc, hunk.getCurB());
          appendLineText(nc, false, CONTEXT, a, hunk.getCurA());
          closeLine(nc);
          hunk.incBoth();
          lines.add(new PatchLine(CONTEXT, hunk.getCurA(), hunk.getCurB()));

        } else if (hunk.isDeletedA()) {
          openLine(nc);
          appendLineNumberForSideA(nc, hunk.getCurA());
          padLineNumberForSideB(nc);
          appendLineText(nc, syntaxHighlighting, DELETE, a, hunk.getCurA());
          closeLine(nc);
          hunk.incA();
          lines.add(new PatchLine(DELETE, hunk.getCurA(), -1));
          if (a.size() == hunk.getCurA()
              && script.getA().isMissingNewlineAtEnd()) {
            appendNoLF(nc);
          }

        } else if (hunk.isInsertedB()) {
          openLine(nc);
          padLineNumberForSideA(nc);
          appendLineNumberForSideB(nc, hunk.getCurB());
          appendLineText(nc, syntaxHighlighting, INSERT, b, hunk.getCurB());
          closeLine(nc);
          hunk.incB();
          lines.add(new PatchLine(INSERT, -1, hunk.getCurB()));
          if (b.size() == hunk.getCurB()
              && script.getB().isMissingNewlineAtEnd()) {
            appendNoLF(nc);
          }
        }
      }
    }
  }

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

    final ArrayList<PatchLineComment> all = new ArrayList<PatchLineComment>();
    for (int row = 0; row < table.getRowCount();) {
      final List<PatchLineComment> fora;
      final List<PatchLineComment> forb;
      if (row == R_HEAD) {
        fora = cd.getForA(R_HEAD);
        forb = cd.getForB(R_HEAD);
        row++;

        if (!fora.isEmpty()) {
          row = insert(fora, row, expandComments);
        }
        rowOfTableHeaderB = row;
        borderRowOfFileComment = row + 1;
        if (!forb.isEmpty()) {
          row++;// Skip the Header of sideB.
          row = insert(forb, row, expandComments);
          borderRowOfFileComment = row;
          createFileCommentBorderRow();
        }
      } else if (getRowItem(row) instanceof PatchLine) {
        final PatchLine pLine = (PatchLine) getRowItem(row);
        fora = cd.getForA(pLine.getLineA());
        forb = cd.getForB(pLine.getLineB());
        row++;

        if (!fora.isEmpty() && !forb.isEmpty()) {
          all.clear();
          all.addAll(fora);
          all.addAll(forb);
          Collections.sort(all, BY_DATE);
          row = insert(all, row, expandComments);

        } else if (!fora.isEmpty()) {
          row = insert(fora, row, expandComments);

        } else if (!forb.isEmpty()) {
          row = insert(forb, row, expandComments);
        }
      } else {
        row++;
        continue;
      }
    }
  }

  private void defaultStyle(final int row, final CellFormatter fmt) {
    fmt.addStyleName(row, PC - 2, Gerrit.RESOURCES.css().lineNumber());
    fmt.addStyleName(row, PC - 2, Gerrit.RESOURCES.css().rightBorder());
    fmt.addStyleName(row, PC - 1, Gerrit.RESOURCES.css().lineNumber());
    fmt.addStyleName(row, PC, Gerrit.RESOURCES.css().diffText());
  }

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

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

  private int insert(final List<PatchLineComment> in, int row, boolean expandComment) {
    for (Iterator<PatchLineComment> ci = in.iterator(); ci.hasNext();) {
      final PatchLineComment c = ci.next();
      if (c.getLine() == R_HEAD) {
        insertFileCommentRow(row);
      } else {
        insertRow(row);
      }
      bindComment(row, PC, c, !ci.hasNext(), expandComment);
      row++;
    }
    return row;
  }

  @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, PC - 2, //
        Gerrit.RESOURCES.css().cellsNextToFileComment());
    fmt.addStyleName(row, PC - 1, //
        Gerrit.RESOURCES.css().cellsNextToFileComment());
  }

  private void createFileCommentBorderRow() {
    if (!isFileCommentBorderRowExist) {
      isFileCommentBorderRowExist = true;
      table.insertRow(borderRowOfFileComment);
      final CellFormatter fmt = table.getCellFormatter();
      fmt.addStyleName(borderRowOfFileComment, C_ARROW, //
          Gerrit.RESOURCES.css().iconCellOfFileCommentRow());
      defaultStyle(borderRowOfFileComment, fmt);

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

  private void appendFileHeader(final SafeHtmlBuilder m, final String line) {
    openLine(m);
    padLineNumberForSideA(m);
    padLineNumberForSideB(m);

    m.openTd();
    m.setStyleName(Gerrit.RESOURCES.css().fileLine());
    m.addStyleName(Gerrit.RESOURCES.css().diffText());
    m.addStyleName(Gerrit.RESOURCES.css().diffTextFileHeader());
    m.append(line);
    m.closeTd();
    closeLine(m);
  }

  private void appendHunkHeader(final SafeHtmlBuilder m, final Hunk hunk) {
    openLine(m);
    padLineNumberForSideA(m);
    padLineNumberForSideB(m);

    m.openTd();
    m.setStyleName(Gerrit.RESOURCES.css().fileLine());
    m.addStyleName(Gerrit.RESOURCES.css().diffText());
    m.addStyleName(Gerrit.RESOURCES.css().diffTextHunkHeader());
    m.append("@@ -");
    appendRange(m, hunk.getCurA() + 1, hunk.getEndA() - hunk.getCurA());
    m.append(" +");
    appendRange(m, hunk.getCurB() + 1, hunk.getEndB() - hunk.getCurB());
    m.append(" @@");
    m.closeTd();

    closeLine(m);
  }

  private void appendRange(final SafeHtmlBuilder m, final int begin,
      final int cnt) {
    switch (cnt) {
      case 0:
        m.append(begin - 1);
        m.append(",0");
        break;

      case 1:
        m.append(begin);
        break;

      default:
        m.append(begin);
        m.append(',');
        m.append(cnt);
        break;
    }
  }

  private void setStyleDelete(final SafeHtmlBuilder m,
      boolean syntaxHighlighting) {
    m.addStyleName(Gerrit.RESOURCES.css().diffTextDELETE());
    if (syntaxHighlighting) {
      m.addStyleName(Gerrit.RESOURCES.css().fileLineDELETE());
    }
  }

  private void setStyleInsert(final SafeHtmlBuilder m,
      boolean syntaxHighlighting) {
    m.addStyleName(Gerrit.RESOURCES.css().diffTextINSERT());
    if (syntaxHighlighting) {
      m.addStyleName(Gerrit.RESOURCES.css().fileLineINSERT());
    }
  }

  private void appendLineText(final SafeHtmlBuilder m,
      boolean syntaxHighlighting, final PatchLine.Type type,
      final SparseHtmlFile src, final int i) {
    final SafeHtml text = src.getSafeHtmlLine(i);
    m.openTd();
    m.setStyleName(Gerrit.RESOURCES.css().fileLine());
    m.addStyleName(Gerrit.RESOURCES.css().diffText());
    switch (type) {
      case CONTEXT:
        m.addStyleName(Gerrit.RESOURCES.css().diffTextCONTEXT());
        m.nbsp();
        m.append(text);
        break;
      case DELETE:
        setStyleDelete(m, syntaxHighlighting);
        m.append("-");
        m.append(text);
        break;
      case INSERT:
        setStyleInsert(m, syntaxHighlighting);
        m.append("+");
        m.append(text);
        break;
      case REPLACE:
        break;
    }
    m.closeTd();
  }

  private void appendNoLF(final SafeHtmlBuilder m) {
    openLine(m);
    padLineNumberForSideA(m);
    padLineNumberForSideB(m);
    m.openTd();
    m.addStyleName(Gerrit.RESOURCES.css().diffText());
    m.addStyleName(Gerrit.RESOURCES.css().diffTextNoLF());
    m.append("\\ No newline at end of file");
    m.closeTd();
    closeLine(m);
  }

  private void openLine(final SafeHtmlBuilder m) {
    m.openTr();
    m.setAttribute("valign", "top");
    m.openTd();
    m.setStyleName(Gerrit.RESOURCES.css().iconCell());
    m.closeTd();
  }

  private void openTableHeaderLine(final SafeHtmlBuilder m) {
    m.openTr();
    m.openTd();
    m.setStyleName(Gerrit.RESOURCES.css().iconCell());
    m.addStyleName(Gerrit.RESOURCES.css().fileColumnHeader());
    m.closeTd();
  }

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

  private void padLineNumberForSideB(final SafeHtmlBuilder m) {
    m.openTd();
    m.setStyleName(Gerrit.RESOURCES.css().lineNumber());
    m.closeTd();
  }

  private void padLineNumberForSideA(final SafeHtmlBuilder m) {
    m.openTd();
    m.setStyleName(Gerrit.RESOURCES.css().lineNumber());
    m.addStyleName(Gerrit.RESOURCES.css().rightBorder());
    m.closeTd();
  }

  private void appendLineNumberForSideB(final SafeHtmlBuilder m, final int idx) {
    m.openTd();
    m.setStyleName(Gerrit.RESOURCES.css().lineNumber());
    m.append(SafeHtml.asis("<a href=\"javascript:void(0)\">"+ (idx + 1) + "</a>"));
    m.closeTd();
  }

  private void appendLineNumberForSideA(final SafeHtmlBuilder m, final int idx) {
    m.openTd();
    m.setStyleName(Gerrit.RESOURCES.css().lineNumber());
    m.addStyleName(Gerrit.RESOURCES.css().rightBorder());
    m.append(SafeHtml.asis("<a href=\"javascript:void(0)\">"+ (idx + 1) + "</a>"));
    m.closeTd();
  }

  private void padLineNumberOnTableHeaderForSideB(final SafeHtmlBuilder m) {
    m.openTd();
    m.setStyleName(Gerrit.RESOURCES.css().lineNumber());
    m.addStyleName(Gerrit.RESOURCES.css().fileColumnHeader());
    m.closeTd();
  }

  private void padLineNumberOnTableHeaderForSideA(final SafeHtmlBuilder m) {
    m.openTd();
    m.setStyleName(Gerrit.RESOURCES.css().lineNumber());
    m.addStyleName(Gerrit.RESOURCES.css().fileColumnHeader());
    m.addStyleName(Gerrit.RESOURCES.css().rightBorder());
    m.closeTd();
  }
}
