// 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.dom.client.Element;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
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>() {
        @Override
        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++;
          } else if (idSideB.equals(psId)) {
            borderRowOfFileComment++;
          }
      }
    }
  }

  @Override
  protected void onCellSingleClick(Event event, int row, int column) {
    super.onCellSingleClick(event, 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--;
          } else if (idSideB.equals(psId)) {
            borderRowOfFileComment--;
          }
      }
    }
  }

  @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");
  }

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

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

    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().syntaxHighlighting;
    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().syntaxHighlighting;
    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 == null || cd.isEmpty()) {
      return;
    }
    setAccountInfoCache(cd.getAccounts());

    final ArrayList<PatchLineComment> all = new ArrayList<>();
    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);
        }
        rowOfTableHeaderB = row;
        borderRowOfFileComment = row + 1;
        if (!forb.isEmpty()) {
          row++;// Skip the Header of sideB.
          row = insert(forb, row);
          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);

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

        } else if (!forb.isEmpty()) {
          row = insert(forb, row);
        }
      } 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);
  }

  private int insert(final List<PatchLineComment> in, int row) {
    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());
      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();
  }
}
