//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 com.google.gerrit.client.FormatUtil;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.account.AccountInfo;
import com.google.gerrit.client.changes.CommentApi;
import com.google.gerrit.client.changes.CommentInfo;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.ui.CommentLinkProcessor;
import com.google.gerrit.client.ui.CommentPanel;
import com.google.gerrit.client.ui.NavigationTable;
import com.google.gerrit.client.ui.NeedsSignInKeyCommand;
import com.google.gerrit.common.data.AccountInfoCache;
import com.google.gerrit.common.data.CommentDetail;
import com.google.gerrit.common.data.PatchScript;
import com.google.gerrit.common.data.PatchSetDetail;
import com.google.gerrit.prettify.client.ClientSideFormatter;
import com.google.gerrit.prettify.client.PrettyFormatter;
import com.google.gerrit.prettify.client.SparseHtmlFile;
import com.google.gerrit.prettify.common.SparseFileContent;
import com.google.gerrit.reviewdb.client.AccountDiffPreference;
import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.PatchLineComment;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.DoubleClickEvent;
import com.google.gwt.event.dom.client.DoubleClickHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Focusable;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.UIObject;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwtexpui.globalkey.client.GlobalKey;
import com.google.gwtexpui.globalkey.client.KeyCommand;
import com.google.gwtexpui.globalkey.client.KeyCommandSet;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
import com.google.gwtorm.client.KeyUtil;

import org.eclipse.jgit.diff.Edit;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

abstract class AbstractPatchContentTable extends NavigationTable<Object>
    implements CommentEditorContainer, FocusHandler, BlurHandler {
  public static final int R_HEAD = 0;
  static final short FILE_SIDE_A = (short) 0;
  static final short FILE_SIDE_B = (short) 1;
  protected PatchTable fileList;
  protected AccountInfoCache accountCache = AccountInfoCache.empty();
  protected Patch.Key patchKey;
  protected PatchSet.Id idSideA;
  protected PatchSet.Id idSideB;
  protected boolean onlyOneHunk;
  protected PatchSetSelectBox headerSideA;
  protected PatchSetSelectBox headerSideB;
  protected Image iconA;
  protected Image iconB;

  private final KeyCommandSet keysComment;
  private HandlerRegistration regComment;
  private final KeyCommandSet keysOpenByEnter;
  private HandlerRegistration regOpenByEnter;
  private CommentLinkProcessor commentLinkProcessor;
  boolean isDisplayBinary;

  protected AbstractPatchContentTable() {
    keysNavigation.add(new PrevKeyCommand(0, 'k', PatchUtil.C.linePrev()));
    keysNavigation.add(new NextKeyCommand(0, 'j', PatchUtil.C.lineNext()));
    keysNavigation.add(new PrevChunkKeyCmd(0, 'p', PatchUtil.C.chunkPrev()));
    keysNavigation.add(new NextChunkKeyCmd(0, 'n', PatchUtil.C.chunkNext()));
    keysNavigation.add(new PrevCommentCmd(0, 'P', PatchUtil.C.commentPrev()));
    keysNavigation.add(new NextCommentCmd(0, 'N', PatchUtil.C.commentNext()));

    keysAction.add(new OpenKeyCommand(0, 'o', PatchUtil.C.expandComment()));
    keysOpenByEnter = new KeyCommandSet(Gerrit.C.sectionNavigation());
    keysOpenByEnter.add(new OpenKeyCommand(0, KeyCodes.KEY_ENTER, PatchUtil.C.expandComment()));

    if (Gerrit.isSignedIn()) {
      keysAction.add(new InsertCommentCommand(0, 'c', PatchUtil.C
          .commentInsert()));

      // See CommentEditorPanel
      //
      keysComment = new KeyCommandSet(PatchUtil.C.commentEditorSet());
      keysComment.add(new NoOpKeyCommand(KeyCommand.M_CTRL, 's', PatchUtil.C
          .commentSaveDraft()));
      keysComment.add(new NoOpKeyCommand(0, KeyCodes.KEY_ESCAPE, PatchUtil.C
          .commentCancelEdit()));
    } else {
      keysComment = null;
    }

    table.setStyleName(Gerrit.RESOURCES.css().patchContentTable());
  }

  abstract void createFileCommentEditorOnSideA();

  abstract void createFileCommentEditorOnSideB();

  protected void initHeaders(PatchScript script, PatchSetDetail detail) {
    headerSideA = new PatchSetSelectBox(PatchSetSelectBox.Side.A);
    headerSideA.display(detail, script, patchKey, idSideA, idSideB);
    headerSideA.addDoubleClickHandler(new DoubleClickHandler() {
      @Override
      public void onDoubleClick(DoubleClickEvent event) {
        if (headerSideA.isFileOrCommitMessage()) {
          createFileCommentEditorOnSideA();
        }
      }
    });
    headerSideB = new PatchSetSelectBox(PatchSetSelectBox.Side.B);
    headerSideB.display(detail, script, patchKey, idSideA, idSideB);
    headerSideB.addDoubleClickHandler(new DoubleClickHandler() {
      @Override
      public void onDoubleClick(DoubleClickEvent event) {
        if (headerSideB.isFileOrCommitMessage()) {
          createFileCommentEditorOnSideB();
        }
      }
    });

    // Prepare icons.
    iconA = new Image(Gerrit.RESOURCES.addFileComment());
    iconA.setTitle(PatchUtil.C.addFileCommentToolTip());
    iconA.addStyleName(Gerrit.RESOURCES.css().link());
    iconA.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(ClickEvent event) {
        createFileCommentEditorOnSideA();
      }
    });
    iconB = new Image(Gerrit.RESOURCES.addFileComment());
    iconB.setTitle(PatchUtil.C.addFileCommentToolTip());
    iconB.addStyleName(Gerrit.RESOURCES.css().link());
    iconB.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(ClickEvent event) {
        createFileCommentEditorOnSideB();
      }
    });
  }

  @Override
  public void notifyDraftDelta(final int delta) {
    if (fileList != null) {
      fileList.notifyDraftDelta(patchKey, delta);
    }

    Widget p = getParent();
    while (p != null) {
      if (p instanceof CommentEditorContainer) {
        ((CommentEditorContainer) p).notifyDraftDelta(delta);
        break;
      }
      p = p.getParent();
    }
  }

  @Override
  public void remove(CommentEditorPanel panel) {
    final int nRows = table.getRowCount();
    for (int row = 0; row < nRows; row++) {
      final int nCells = table.getCellCount(row);
      for (int cell = 0; cell < nCells; cell++) {
        if (table.getWidget(row, cell) == panel) {
          destroyEditor(row, cell);
          Widget p = table;
          while (p != null) {
            if (p instanceof Focusable) {
              ((Focusable) p).setFocus(true);
              break;
            }
            p = p.getParent();
          }

          if (table.getCellFormatter().getStyleName(row - 1, cell)
              .contains(Gerrit.RESOURCES.css().commentHolder())) {
            table.getCellFormatter().addStyleName(row - 1, cell,
                Gerrit.RESOURCES.css().commentPanelLast());
          }
          return;
        }
      }
    }
  }

  @Override
  public void setRegisterKeys(final boolean on) {
    super.setRegisterKeys(on);
    if (on && keysComment != null && regComment == null) {
      regComment = GlobalKey.add(this, keysComment);
    } else if (!on && regComment != null) {
      regComment.removeHandler();
      regComment = null;
    }

    if (on && keysOpenByEnter != null && regOpenByEnter == null) {
      regOpenByEnter = GlobalKey.add(this, keysOpenByEnter);
    } else if (!on && regOpenByEnter != null) {
      regOpenByEnter.removeHandler();
      regOpenByEnter = null;
    }
  }

  public void display(final Patch.Key k, final PatchSet.Id a,
      final PatchSet.Id b, final PatchScript s, final PatchSetDetail d) {
    patchKey = k;
    idSideA = a;
    idSideB = b;

    render(s, d);
  }

  void setCommentLinkProcessor(CommentLinkProcessor commentLinkProcessor) {
    this.commentLinkProcessor = commentLinkProcessor;
  }

  protected boolean hasDifferences(PatchScript script) {
    return hasEdits(script) || hasMeta(script) || hasComments(script);
  }

  public boolean isPureMetaChange(PatchScript script) {
    return !hasEdits(script) && hasMeta(script);
  }

  // True if there are differences between the two patch sets
  private boolean hasEdits(PatchScript script) {
    for (Edit e : script.getEdits()) {
      if (e.getType() != Edit.Type.EMPTY) {
        return true;
      }
    }
    return false;
  }

  // True if one of the two patch sets has comments
  private boolean hasComments(PatchScript script) {
    return !script.getCommentDetail().getCommentsA().isEmpty()
        || !script.getCommentDetail().getCommentsB().isEmpty();
  }

  // True if this change is a mode change or a pure rename/copy
  private boolean hasMeta(PatchScript script) {
    return !script.getPatchHeader().isEmpty();
  }

  protected void appendNoDifferences(SafeHtmlBuilder m) {
    m.openTr();
    m.openTd();
    m.setAttribute("colspan", 5);
    m.openDiv();
    m.addStyleName(Gerrit.RESOURCES.css().patchNoDifference());
    m.append(PatchUtil.C.noDifference());
    m.closeDiv();
    m.closeTd();
    m.closeTr();
  }

  protected SparseHtmlFile getSparseHtmlFileA(PatchScript s) {
    AccountDiffPreference dp = new AccountDiffPreference(s.getDiffPrefs());
    dp.setShowWhitespaceErrors(false);

    PrettyFormatter f = ClientSideFormatter.FACTORY.get();
    f.setDiffPrefs(dp);
    f.setFileName(s.getA().getPath());
    f.setEditFilter(PrettyFormatter.A);
    f.setEditList(s.getEdits());
    f.format(s.getA());
    return f;
  }

  protected SparseHtmlFile getSparseHtmlFileB(PatchScript s) {
    AccountDiffPreference dp = new AccountDiffPreference(s.getDiffPrefs());

    SparseFileContent b = s.getB();
    PrettyFormatter f = ClientSideFormatter.FACTORY.get();
    f.setDiffPrefs(dp);
    f.setFileName(b.getPath());
    f.setEditFilter(PrettyFormatter.B);
    f.setEditList(s.getEdits());

    if (s.getA().isWholeFile() && !b.isWholeFile()) {
      b = b.apply(s.getA(), s.getEdits());
    }
    f.format(b);
    return f;
  }

  protected String getUrlA() {
    final String rawBase = GWT.getHostPageBaseURL() + "cat/";
    final String url;
    if (idSideA == null) {
      url = rawBase + KeyUtil.encode(patchKey.toString()) + "^1";
    } else {
      Patch.Key k = new Patch.Key(idSideA, patchKey.get());
      url = rawBase + KeyUtil.encode(k.toString()) + "^0";
    }
    return url;
  }

  protected String getUrlB() {
    final String rawBase = GWT.getHostPageBaseURL() + "cat/";
    return rawBase + KeyUtil.encode(patchKey.toString()) + "^0";
  }

  protected abstract void render(PatchScript script, final PatchSetDetail detail);

  protected abstract void onInsertComment(PatchLine pl);

  public abstract void display(CommentDetail comments, boolean expandComments);

  @Override
  protected Object getRowItemKey(final Object item) {
    return null;
  }

  protected void initScript(final PatchScript script) {
    if (script.getEdits().size() == 1) {
      final SparseFileContent a = script.getA();
      final SparseFileContent b = script.getB();
      onlyOneHunk = a.size() == 0 || b.size() == 0;
    } else {
      onlyOneHunk = false;
    }
  }

  private boolean isChunk(final int row) {
    final Object o = getRowItem(row);
    if (!onlyOneHunk && o instanceof PatchLine) {
      final PatchLine pl = (PatchLine) o;
      switch (pl.getType()) {
        case DELETE:
        case INSERT:
        case REPLACE:
          return true;
        case CONTEXT:
          break;
      }
    } else if (o instanceof CommentList) {
      return true;
    }
    return false;
  }

  private int findChunkStart(int row) {
    while (0 <= row && isChunk(row)) {
      row--;
    }
    return row + 1;
  }

  private int findChunkEnd(int row) {
    final int max = table.getRowCount();
    while (row < max && isChunk(row)) {
      row++;
    }
    return row - 1;
  }

  private static int oneBefore(final int begin) {
    return 1 <= begin ? begin - 1 : begin;
  }

  private int oneAfter(final int end) {
    return end + 1 < table.getRowCount() ? end + 1 : end;
  }

  private void moveToPrevChunk(int row) {
    while (0 <= row && isChunk(row)) {
      row--;
    }
    for (; 0 <= row; row--) {
      if (isChunk(row)) {
        final int start = findChunkStart(row);
        movePointerTo(start, false);
        scrollIntoView(oneBefore(start), oneAfter(row));
        return;
      }
    }

    // No prior hunk found? Try to hit the first line in the file.
    //
    for (row = 0; row < table.getRowCount(); row++) {
      if (getRowItem(row) != null) {
        movePointerTo(row);
        break;
      }
    }
  }

  private void moveToNextChunk(int row) {
    final int max = table.getRowCount();
    while (row < max && isChunk(row)) {
      row++;
    }
    for (; row < max; row++) {
      if (isChunk(row)) {
        movePointerTo(row, false);
        scrollIntoView(oneBefore(row), oneAfter(findChunkEnd(row)));
        return;
      }
    }

    // No next hunk found? Try to hit the last line in the file.
    //
    for (row = max - 1; row >= 0; row--) {
      if (getRowItem(row) != null) {
        movePointerTo(row);
        break;
      }
    }
  }

  private void moveToPrevComment(int row) {
    while (0 <= row && isComment(row)) {
      row--;
    }
    for (; 0 <= row; row--) {
      if (isComment(row)) {
        movePointerTo(row, false);
        scrollIntoView(oneBefore(row), oneAfter(row));
        return;
      }
    }

    // No prior comment found? Try to hit the first line in the file.
    //
    for (row = 0; row < table.getRowCount(); row++) {
      if (getRowItem(row) != null) {
        movePointerTo(row);
        break;
      }
    }
  }

  private void moveToNextComment(int row) {
    final int max = table.getRowCount();
    while (row < max && isComment(row)) {
      row++;
    }
    for (; row < max; row++) {
      if (isComment(row)) {
        movePointerTo(row, false);
        scrollIntoView(oneBefore(row), oneAfter(row));
        return;
      }
    }

    // No next comment found? Try to hit the last line in the file.
    //
    for (row = max - 1; row >= 0; row--) {
      if (getRowItem(row) != null) {
        movePointerTo(row);
        break;
      }
    }
  }

  private boolean isComment(int row) {
    return getRowItem(row) instanceof CommentList;
  }

  /**
   * Invokes createCommentEditor() with an empty string as value for the comment
   * parent UUID. This method is invoked by callers that want to create an
   * editor for a comment that is not a reply.
   */
  protected void createCommentEditor(final int suggestRow, final int column,
      final int line, final short file) {
    if (Gerrit.isSignedIn()) {
      if (R_HEAD <= line) {
        final Patch.Key parentKey;
        final short side;
        switch (file) {
          case 0:
            if (idSideA == null) {
              parentKey = new Patch.Key(idSideB, patchKey.get());
              side = (short) 0;
            } else {
              parentKey = new Patch.Key(idSideA, patchKey.get());
              side = (short) 1;
            }
            break;
          case 1:
            parentKey = new Patch.Key(idSideB, patchKey.get());
            side = (short) 1;
            break;
          default:
            throw new RuntimeException("unexpected file id " + file);
        }

        final PatchLineComment newComment = new PatchLineComment(
            new PatchLineComment.Key(parentKey, null), line,
            Gerrit.getUserAccount().getId(), null,
            new Timestamp(System.currentTimeMillis()));
        newComment.setSide(side);
        newComment.setMessage("");

        findOrCreateCommentEditor(suggestRow, column, newComment, true)
            .setFocus(true);
      }
    } else {
      Gerrit.doSignIn(History.getToken());
    }
  }

  /**
   * Update cursor after selecting a comment.
   *
   * @param newComment comment that was selected.
   */
  protected void updateCursor(final PatchLineComment newComment) {
  }

  abstract void insertFileCommentRow(final int row);

  private CommentEditorPanel findOrCreateCommentEditor(final int suggestRow,
      final int column, final PatchLineComment newComment, final boolean create) {
    int row = suggestRow;
    int spans[] = new int[column + 1];
    FIND_ROW: while (row < table.getRowCount()) {
      int col = 0;
      for (int cell = 0; row < table.getRowCount()
          && cell < table.getCellCount(row); cell++) {
        while (col < column && 0 < spans[col]) {
          spans[col++]--;
        }
        spans[col] = table.getFlexCellFormatter().getRowSpan(row, cell);
        if (col == column) {
          final Widget w = table.getWidget(row, cell);
          if (w instanceof CommentEditorPanel
              && ((CommentEditorPanel) w).getComment().getKey().getParentKey()
                  .equals(newComment.getKey().getParentKey())) {
            // Don't insert two editors on the same position, it doesn't make
            // any sense to the user.
            //
            return ((CommentEditorPanel) w);

          } else if (w instanceof CommentPanel) {
            if (newComment != null && newComment.getParentUuid() != null) {
              // If we are a reply, we were given the exact row to insert
              // ourselves at. We should be before this panel so break.
              //
              break FIND_ROW;
            }
            row++;
            cell--;
          } else {
            break FIND_ROW;
          }
        }
      }
    }

    if (newComment == null || !create) {
      return null;
    }

    final CommentEditorPanel ed =
        new CommentEditorPanel(newComment, commentLinkProcessor);
    ed.addFocusHandler(this);
    ed.addBlurHandler(this);
    boolean isCommentRow = false;
    boolean needInsert = false;
    if (row < table.getRowCount()) {
      for (int cell = 0; cell < table.getCellCount(row); cell++) {
        final Widget w = table.getWidget(row, cell);
        if (w instanceof CommentEditorPanel || w instanceof CommentPanel) {
          if (column == cell) {
            needInsert = true;
          }
          isCommentRow = true;
        }
      }
    }
    if (needInsert || !isCommentRow) {
      if (newComment.getLine() == R_HEAD) {
        insertFileCommentRow(row);
      } else {
        insertRow(row);
      }
      styleCommentRow(row);
    }
    table.setWidget(row, column, ed);
    styleLastCommentCell(row, column);

    int span = 1;
    for (int r = row + 1; r < table.getRowCount(); r++) {
      boolean hasComment = false;
      for (int c = 0; c < table.getCellCount(r); c++) {
        final Widget w = table.getWidget(r, c);
        if (w instanceof CommentPanel || w instanceof CommentEditorPanel) {
          if (c != column) {
            hasComment = true;
            break;
          }
        }
      }
      if (hasComment) {
        table.removeCell(r, column);
        span++;
      } else {
        break;
      }
    }
    if (span > 1) {
      table.getFlexCellFormatter().setRowSpan(row, column, span);
    }

    for (int r = row - 1; r > 0; r--) {
      if (getRowItem(r) instanceof CommentList) {
        continue;
      } else if (getRowItem(r) != null) {
        movePointerTo(r);
        break;
      }
    }

    updateCursor(newComment);
    return ed;
  }

  protected void insertRow(final int row) {
    table.insertRow(row);
    table.getCellFormatter().setStyleName(row, 0,
        Gerrit.RESOURCES.css().iconCell());
  }

  @Override
  protected void onOpenRow(final int row) {
    final Object item = getRowItem(row);
    if (item instanceof CommentList) {
      for (final CommentPanel p : ((CommentList) item).panels) {
        p.setOpen(!p.isOpen());
      }
    }
  }

  public void setAccountInfoCache(final AccountInfoCache aic) {
    assert aic != null;
    accountCache = aic;
  }

  private void destroyEditor(final int row, final int col) {
    table.clearCell(row, col);
    final int span = table.getFlexCellFormatter().getRowSpan(row, col);
    boolean removeRow = true;
    final int nCells = table.getCellCount(row);
    for (int cell = 0; cell < nCells; cell++) {
      if (table.getWidget(row, cell) != null) {
        removeRow = false;
        break;
      }
    }
    if (removeRow) {
      destroyCommentRow(row);
    } else {
      destroyComment(row, col, span);
    }
  }

  protected void destroyCommentRow(int row) {
    for (int r = row - 1; 0 <= r; r--) {
      boolean data = false;
      for (int c = 0; c < table.getCellCount(r); c++) {
        data |= table.getWidget(r, c) != null;
        final int s = table.getFlexCellFormatter().getRowSpan(r, c) - 1;
        if (r + s == row) {
          table.getFlexCellFormatter().setRowSpan(r, c, s);
        }
      }
      if (!data) {
        break;
      }
    }
    table.removeRow(row);
  }

  private void destroyComment(int row, int col, int span) {
    table.getFlexCellFormatter().setStyleName(//
        row, col, Gerrit.RESOURCES.css().diffText());

    if (span != 1) {
      table.getFlexCellFormatter().setRowSpan(row, col, 1);
      for (int r = row + 1; r < row + span; r++) {
        table.insertCell(r, col);

        table.getFlexCellFormatter().setStyleName(//
            r, col, Gerrit.RESOURCES.css().diffText());
      }
    }
  }

  protected void bindComment(final int row, final int col,
      final PatchLineComment line, boolean expandComment) {
    if (line.getStatus() == PatchLineComment.Status.DRAFT) {
      final CommentEditorPanel plc =
          new CommentEditorPanel(line, commentLinkProcessor);
      plc.addFocusHandler(this);
      plc.addBlurHandler(this);
      table.setWidget(row, col, plc);
      styleLastCommentCell(row, col);

    } else {
      final AccountInfo author = FormatUtil.asInfo(accountCache.get(line.getAuthor()));
      final PublishedCommentPanel panel =
          new PublishedCommentPanel(author, line);
      panel.setOpen(expandComment);
      panel.addFocusHandler(this);
      panel.addBlurHandler(this);
      table.setWidget(row, col, panel);
      styleLastCommentCell(row, col);

      CommentList l = (CommentList) getRowItem(row);
      if (l == null) {
        l = new CommentList();
        setRowItem(row, l);
      }
      l.comments.add(line);
      l.panels.add(panel);
    }

    styleCommentRow(row);
  }

  @Override
  public void onFocus(FocusEvent event) {
    // when the comment panel gets focused (actually when a button inside the
    // comment panel gets focused) we have to unregister the key binding for
    // ENTER that expands/collapses the comment panel, if we don't do this the
    // focused button in the comment panel cannot be triggered by pressing ENTER
    // since ENTER would then be already consumed by this key binding
    if (regOpenByEnter != null) {
      regOpenByEnter.removeHandler();
      regOpenByEnter = null;
    }
  }

  @Override
  public void onBlur(BlurEvent event) {
    // when the comment panel gets blurred (actually when a button inside the
    // comment panel gets blurred) we have to re-register the key binding for
    // ENTER that expands/collapses the comment panel
    if (keysOpenByEnter != null && regOpenByEnter == null) {
      regOpenByEnter = GlobalKey.add(this, keysOpenByEnter);
    }
  }

  private void styleCommentRow(final int row) {
    final CellFormatter fmt = table.getCellFormatter();
    final Element iconCell = fmt.getElement(row, 0);
    UIObject.setStyleName(DOM.getParent(iconCell), Gerrit.RESOURCES.css()
        .commentHolder(), true);
  }

  private void styleLastCommentCell(final int row, final int col) {
    final CellFormatter fmt = table.getCellFormatter();
    fmt.removeStyleName(row - 1, col, //
        Gerrit.RESOURCES.css().commentPanelLast());
    fmt.setStyleName(row, col, Gerrit.RESOURCES.css().commentHolder());
    fmt.addStyleName(row, col, Gerrit.RESOURCES.css().commentPanelLast());
    if (!fmt.getStyleName(row, col - 1).contains(Gerrit.RESOURCES.css().commentHolder())) {
      fmt.addStyleName(row, col, Gerrit.RESOURCES.css().commentHolderLeftmost());
    }
  }

  protected static class CommentList {
    final List<PatchLineComment> comments = new ArrayList<>();
    final List<PublishedCommentPanel> panels = new ArrayList<>();
  }

  public static class NoOpKeyCommand extends NeedsSignInKeyCommand {
    public NoOpKeyCommand(int mask, int key, String help) {
      super(mask, key, help);
    }

    @Override
    public void onKeyPress(final KeyPressEvent event) {
    }
  }

  public class InsertCommentCommand extends NeedsSignInKeyCommand {
    public InsertCommentCommand(int mask, int key, String help) {
      super(mask, key, help);
    }

    @Override
    public void onKeyPress(final KeyPressEvent event) {
      ensurePointerVisible();
      for (int row = getCurrentRow(); 0 <= row; row--) {
        final Object item = getRowItem(row);
        if (item instanceof PatchLine) {
          onInsertComment((PatchLine) item);
          return;
        } else if (item instanceof CommentList) {
          continue;
        } else {
          return;
        }
      }
    }
  }

  public class PrevChunkKeyCmd extends KeyCommand {
    public PrevChunkKeyCmd(int mask, int key, String help) {
      super(mask, key, help);
    }

    @Override
    public void onKeyPress(final KeyPressEvent event) {
      ensurePointerVisible();
      moveToPrevChunk(getCurrentRow());
    }
  }

  public class NextChunkKeyCmd extends KeyCommand {
    public NextChunkKeyCmd(int mask, int key, String help) {
      super(mask, key, help);
    }

    @Override
    public void onKeyPress(final KeyPressEvent event) {
      ensurePointerVisible();
      moveToNextChunk(getCurrentRow());
    }
  }

  public class PrevCommentCmd extends KeyCommand {
    public PrevCommentCmd(int mask, int key, String help) {
      super(mask, key, help);
    }

    @Override
    public void onKeyPress(final KeyPressEvent event) {
      ensurePointerVisible();
      moveToPrevComment(getCurrentRow());
    }
  }

  public class NextCommentCmd extends KeyCommand {
    public NextCommentCmd(int mask, int key, String help) {
      super(mask, key, help);
    }

    @Override
    public void onKeyPress(final KeyPressEvent event) {
      ensurePointerVisible();
      moveToNextComment(getCurrentRow());
    }
  }

  private class PublishedCommentPanel extends CommentPanel implements
      ClickHandler {
    final PatchLineComment comment;
    final Button reply;
    final Button replyDone;

    PublishedCommentPanel(final AccountInfo author, final PatchLineComment c) {
      super(author, c.getWrittenOn(), c.getMessage(), commentLinkProcessor);
      this.comment = c;

      reply = new Button(PatchUtil.C.buttonReply());
      reply.addClickHandler(this);
      addButton(reply);

      replyDone = new Button(PatchUtil.C.buttonReplyDone());
      replyDone.addClickHandler(this);
      addButton(replyDone);
    }

    @Override
    public void onClick(final ClickEvent event) {
      if (Gerrit.isSignedIn()) {
        if (reply == event.getSource()) {
          createReplyEditor();
        } else if (replyDone == event.getSource()) {
          cannedReply(PatchUtil.C.cannedReplyDone());
        }

      } else {
        Gerrit.doSignIn(History.getToken());
      }
    }

    private void createReplyEditor() {
      final PatchLineComment newComment = newComment();
      newComment.setMessage("");
      findOrCreateEditor(newComment, true).setFocus(true);
    }

    private void cannedReply(String message) {
      final PatchLineComment newComment = newComment();
      newComment.setMessage(message);
      CommentEditorPanel p = findOrCreateEditor(newComment, false);
      if (p == null) {
        enableButtons(false);
        final PatchSet.Id psId = newComment.getKey().getParentKey().getParentKey();
        CommentInfo in = CommentEditorPanel.toInput(newComment);
        CommentApi.createDraft(psId, in,
            new GerritCallback<CommentInfo>() {
              @Override
              public void onSuccess(CommentInfo result) {
                enableButtons(true);
                notifyDraftDelta(1);
                findOrCreateEditor(CommentEditorPanel.toComment(
                    psId, newComment.getKey().getParentKey().get(), result),
                  true).setOpen(false);
              }

              @Override
              public void onFailure(Throwable caught) {
                enableButtons(true);
                super.onFailure(caught);
              }
            });
      } else {
        if (!p.isOpen()) {
          p.setOpen(true);
        }
        p.setFocus(true);
      }
    }

    private CommentEditorPanel findOrCreateEditor(
        PatchLineComment newComment, boolean create) {
      int row = rowOf(getElement());
      int column = columnOf(getElement());
      return findOrCreateCommentEditor(row + 1, column, newComment, create);
    }

    private PatchLineComment newComment() {
      PatchLineComment newComment =
          new PatchLineComment(new PatchLineComment.Key(comment.getKey()
              .getParentKey(), null), comment.getLine(), Gerrit
              .getUserAccount().getId(), comment.getKey().get(),
              new Timestamp(System.currentTimeMillis()));
      newComment.setSide(comment.getSide());
      return newComment;
    }
  }
}
