//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.Dispatcher;
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.PatchTable;
import com.google.gerrit.client.changes.Util;
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.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.Element;
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;

public 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()));
      keysAction.add(new PublishCommentsKeyCommand(0, 'r', Util.C
          .keyPublishComments()));

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

  abstract PatchScreen.Type getPatchScreenType();

  protected void initHeaders(PatchScript script, PatchSetDetail detail) {
    PatchScreen.Type type = getPatchScreenType();
    headerSideA = new PatchSetSelectBox(PatchSetSelectBox.Side.A, type);
    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, type);
    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());
    }
  }

  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, final boolean isLast, 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<PatchLineComment>();
    final List<PublishedCommentPanel> panels =
        new ArrayList<PublishedCommentPanel>();
  }

  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 PublishCommentsKeyCommand extends NeedsSignInKeyCommand {
    public PublishCommentsKeyCommand(int mask, char key, String help) {
      super(mask, key, help);
    }

    @Override
    public void onKeyPress(final KeyPressEvent event) {
      final PatchSet.Id id = patchKey.getParentKey();
      Gerrit.display(Dispatcher.toPublish(id));
    }
  }

  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);
        PatchUtil.DETAIL_SVC.saveDraft(newComment,
            new GerritCallback<PatchLineComment>() {
              @Override
              public void onSuccess(final PatchLineComment result) {
                enableButtons(true);
                notifyDraftDelta(1);
                findOrCreateEditor(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;
    }
  }
}
