// 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.prettify.common.EditList;
import com.google.gerrit.prettify.common.SparseHtmlFile;
import com.google.gerrit.reviewdb.Patch;
import com.google.gerrit.reviewdb.PatchLineComment;
import com.google.gerrit.reviewdb.Patch.ChangeType;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
import com.google.gwtexpui.safehtml.client.SafeHtml;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
import com.google.gwtorm.client.KeyUtil;

import org.eclipse.jgit.diff.Edit;

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

public class SideBySideTable extends AbstractPatchContentTable {
  private static final int COL_A = 2;
  private static final int COL_B = 4;

  @Override
  protected void onCellDoubleClick(final int row, int column) {
    if (column > 0 && getRowItem(row) instanceof PatchLine) {
      final PatchLine line = (PatchLine) getRowItem(row);
      final short file = (short) ((column - 1) / 2);
      if (column < (1 + file * 2 + 1)) {
        column++;
      }
      switch (file) {
        case 0:
          createCommentEditor(row + 1, column, line.getLineA(), file);
          break;
        case 1:
          createCommentEditor(row + 1, column, line.getLineB(), file);
          break;
      }
    }
  }

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

  @Override
  protected void render(final PatchScript script) {
    final SparseHtmlFile a = script.getSparseHtmlFileA();
    final SparseHtmlFile b = script.getSparseHtmlFileB();
    final ArrayList<PatchLine> lines = new ArrayList<PatchLine>();
    final SafeHtmlBuilder nc = new SafeHtmlBuilder();
    final boolean intraline =
        script.getDiffPrefs().isIntralineDifference()
            && script.hasIntralineDifference();

    appendHeader(script, nc);
    lines.add(null);

    if(script.getFileModeA()!=FileMode.FILE||script.getFileModeB()!=FileMode.FILE){
      openLine(nc);
      appendModeLine(nc, script.getFileModeA());
      appendModeLine(nc, script.getFileModeB());
      closeLine(nc);
      lines.add(null);
    }

    int lastB = 0;
    final boolean ignoreWS = script.isIgnoreWhitespace();
    for (final EditList.Hunk hunk : script.getHunks()) {
      if (!hunk.isStartOfFile()) {
        appendSkipLine(nc, hunk.getCurB() - lastB);
        lines.add(null);
      }

      while (hunk.next()) {
        if (hunk.isContextLine()) {
          openLine(nc);
          final SafeHtml ctx = a.getSafeHtmlLine(hunk.getCurA());
          appendLineText(nc, hunk.getCurA(), CONTEXT, ctx, false, false);
          if (ignoreWS && b.contains(hunk.getCurB())) {
            appendLineText(nc, hunk.getCurB(), CONTEXT, b, hunk.getCurB(),
                false);
          } else {
            appendLineText(nc, hunk.getCurB(), CONTEXT, ctx, false, false);
          }
          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) {
            appendLineText(nc, hunk.getCurA(), DELETE, a, hunk.getCurA(), full);
            hunk.incA();
          } else if (hunk.getCurEdit().getType() == Edit.Type.REPLACE) {
            appendLineNone(nc, DELETE);
          } else {
            appendLineNone(nc, CONTEXT);
          }

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

          closeLine(nc);

          if (del && ins) {
            lines.add(new PatchLine(REPLACE, hunk.getCurA(), hunk.getCurB()));
          } else if (del) {
            lines.add(new PatchLine(DELETE, hunk.getCurA(), 0));
          } else if (ins) {
            lines.add(new PatchLine(INSERT, 0, hunk.getCurB()));
          }
        }
      }
      lastB = hunk.getCurB();
    }
    if (lastB != b.size()) {
      appendSkipLine(nc, b.size() - lastB);
    }
    resetHtml(nc);
    initScript(script);

    for (int row = 0; row < lines.size(); row++) {
      setRowItem(row, lines.get(row));
    }
  }

  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
  public void display(final CommentDetail cd) {
    if (cd.isEmpty()) {
      return;
    }
    setAccountInfoCache(cd.getAccounts());

    for (int row = 0; row < table.getRowCount();) {
      if (getRowItem(row) instanceof PatchLine) {
        final PatchLine pLine = (PatchLine) getRowItem(row);
        final List<PatchLineComment> fora = cd.getForA(pLine.getLineA());
        final List<PatchLineComment> forb = cd.getForB(pLine.getLineB());
        row++;

        final Iterator<PatchLineComment> ai = fora.iterator();
        final Iterator<PatchLineComment> bi = forb.iterator();
        while (ai.hasNext() && bi.hasNext()) {
          final PatchLineComment ac = ai.next();
          final PatchLineComment bc = bi.next();
          insertRow(row);
          bindComment(row, COL_A, ac, !ai.hasNext());
          bindComment(row, COL_B, bc, !bi.hasNext());
          row++;
        }

        row = finish(ai, row, COL_A);
        row = finish(bi, row, COL_B);
      } else {
        row++;
      }
    }
  }

  @Override
  protected void insertRow(final int row) {
    super.insertRow(row);
    final CellFormatter fmt = table.getCellFormatter();
    fmt.addStyleName(row, COL_A - 1, Gerrit.RESOURCES.css().lineNumber());
    fmt.addStyleName(row, COL_A, Gerrit.RESOURCES.css().diffText());
    fmt.addStyleName(row, COL_B - 1, Gerrit.RESOURCES.css().lineNumber());
    fmt.addStyleName(row, COL_B, Gerrit.RESOURCES.css().diffText());
  }

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

  private void appendHeader(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.addStyleName(Gerrit.RESOURCES.css().fileColumnHeader());
    m.addStyleName(Gerrit.RESOURCES.css().lineNumber());
    m.closeTd();

    m.openTd();
    m.setStyleName(Gerrit.RESOURCES.css().fileColumnHeader());
    m.setAttribute("width", "50%");
    if (script.getChangeType() == ChangeType.RENAMED
        || script.getChangeType() == ChangeType.COPIED) {
      m.append(script.getOldName());
    } else {
      m.append(PatchUtil.C.patchHeaderOld());
    }
    m.br();
    if (0 < script.getA().size()) {
      if (idSideA == null) {
        downloadLink(m, patchKey, "1");
      } else {
        downloadLink(m, new Patch.Key(idSideA, patchKey.get()), "0");
      }
    }
    m.closeTd();

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

    m.openTd();
    m.setStyleName(Gerrit.RESOURCES.css().fileColumnHeader());
    m.setAttribute("width", "50%");
    m.append(PatchUtil.C.patchHeaderNew());
    m.br();
    if (0 < script.getB().size()) {
      downloadLink(m, new Patch.Key(idSideB, patchKey.get()), "0");
    }
    m.closeTd();

    m.closeTr();
  }

  private void downloadLink(final SafeHtmlBuilder m, final Patch.Key key,
      final String side) {
    final String base = GWT.getHostPageBaseURL() + "cat/";
    m.openAnchor();
    m.setAttribute("href", base + KeyUtil.encode(key.toString()) + "^" + side);
    m.append(PatchUtil.C.download());
    m.closeAnchor();
  }

  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.append(PatchUtil.M.patchSkipRegion(skipCnt));
    m.closeTd();
    m.closeTr();
  }

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

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

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

  private void appendLineText(final SafeHtmlBuilder m,
      final int lineNumberMinusOne, final PatchLine.Type type,
      final SafeHtml lineHtml, final boolean trailingEdit,
      final boolean fullBlock) {
    m.openTd();
    m.setStyleName(Gerrit.RESOURCES.css().lineNumber());
    m.append(lineNumberMinusOne + 1);
    m.closeTd();

    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;
    }
    m.append(lineHtml);
    m.closeTd();
  }

  private void appendLineNone(final SafeHtmlBuilder m, final PatchLine.Type type) {
    m.openTd();
    m.setStyleName(Gerrit.RESOURCES.css().lineNumber());
    m.closeTd();

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