// Copyright (C) 2013 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 impl ied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.client.diff;

import static com.google.gerrit.extensions.client.DiffPreferencesInfo.WHOLE_FILE_CONTEXT;
import static java.lang.Double.POSITIVE_INFINITY;

import com.google.gerrit.client.DiffObject;
import com.google.gerrit.client.Dispatcher;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.account.DiffPreferences;
import com.google.gerrit.client.change.ChangeScreen;
import com.google.gerrit.client.change.FileTable;
import com.google.gerrit.client.changes.ChangeApi;
import com.google.gerrit.client.changes.ChangeList;
import com.google.gerrit.client.diff.DiffInfo.FileMeta;
import com.google.gerrit.client.diff.LineMapper.LineOnOtherInfo;
import com.google.gerrit.client.info.ChangeInfo;
import com.google.gerrit.client.info.ChangeInfo.CommitInfo;
import com.google.gerrit.client.info.ChangeInfo.EditInfo;
import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
import com.google.gerrit.client.info.FileInfo;
import com.google.gerrit.client.patches.PatchUtil;
import com.google.gerrit.client.projects.ConfigInfoCache;
import com.google.gerrit.client.rpc.CallbackGroup;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.rpc.RestApi;
import com.google.gerrit.client.rpc.ScreenLoadCallback;
import com.google.gerrit.client.ui.Screen;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DiffView;
import com.google.gerrit.extensions.client.ListChangesOption;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
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.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
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.globalkey.client.ShowHelpCommand;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import net.codemirror.lib.CodeMirror;
import net.codemirror.lib.CodeMirror.BeforeSelectionChangeHandler;
import net.codemirror.lib.CodeMirror.GutterClickHandler;
import net.codemirror.lib.CodeMirror.LineHandle;
import net.codemirror.lib.KeyMap;
import net.codemirror.lib.Pos;
import net.codemirror.mode.ModeInfo;
import net.codemirror.mode.ModeInjector;
import net.codemirror.theme.ThemeLoader;

/** Base class for SideBySide and Unified */
abstract class DiffScreen extends Screen {
  private static final KeyMap RENDER_ENTIRE_FILE_KEYMAP =
      KeyMap.create().propagate("Ctrl-F").propagate("Ctrl-G").propagate("Shift-Ctrl-G");

  enum FileSize {
    SMALL(0),
    LARGE(500),
    HUGE(4000);

    final int lines;

    FileSize(int n) {
      this.lines = n;
    }
  }

  private final Change.Id changeId;
  final DiffObject base;
  final PatchSet.Id revision;
  final String path;
  final DiffPreferences prefs;
  final SkipManager skipManager;

  private DisplaySide startSide;
  private int startLine;
  private Change.Status changeStatus;

  private HandlerRegistration resizeHandler;
  private DiffInfo diff;
  private FileSize fileSize;
  private EditInfo edit;

  private KeyCommandSet keysNavigation;
  private KeyCommandSet keysAction;
  private KeyCommandSet keysComment;
  private List<HandlerRegistration> handlers;
  private PreferencesAction prefsAction;
  private int reloadVersionId;
  private int parents;

  @UiField(provided = true)
  Header header;

  DiffScreen(
      DiffObject base,
      DiffObject revision,
      String path,
      DisplaySide startSide,
      int startLine,
      DiffView diffScreenType) {
    this.base = base;
    this.revision = revision.asPatchSetId();
    this.changeId = revision.asPatchSetId().getParentKey();
    this.path = path;
    this.startSide = startSide;
    this.startLine = startLine;

    prefs = DiffPreferences.create(Gerrit.getDiffPreferences());
    handlers = new ArrayList<>(6);
    keysNavigation = new KeyCommandSet(Gerrit.C.sectionNavigation());
    header = new Header(keysNavigation, base, revision, path, diffScreenType, prefs);
    skipManager = new SkipManager(this);
  }

  @Override
  protected void onInitUI() {
    super.onInitUI();
    setHeaderVisible(false);
    setWindowTitle(FileInfo.getFileName(path));
  }

  @Override
  protected void onLoad() {
    super.onLoad();

    CallbackGroup group1 = new CallbackGroup();
    final CallbackGroup group2 = new CallbackGroup();

    CodeMirror.initLibrary(
        group1.add(
            new AsyncCallback<Void>() {
              final AsyncCallback<Void> themeCallback = group2.addEmpty();

              @Override
              public void onSuccess(Void result) {
                // Load theme after CM library to ensure theme can override CSS.
                ThemeLoader.loadTheme(prefs.theme(), themeCallback);
              }

              @Override
              public void onFailure(Throwable caught) {}
            }));

    DiffApi.diff(revision, path)
        .base(base.asPatchSetId())
        .wholeFile()
        .intraline(prefs.intralineDifference())
        .ignoreWhitespace(prefs.ignoreWhitespace())
        .get(
            group1.addFinal(
                new GerritCallback<DiffInfo>() {
                  final AsyncCallback<Void> modeInjectorCb = group2.addEmpty();

                  @Override
                  public void onSuccess(DiffInfo diffInfo) {
                    diff = diffInfo;
                    fileSize = bucketFileSize(diffInfo);

                    if (prefs.syntaxHighlighting()) {
                      if (fileSize.compareTo(FileSize.SMALL) > 0) {
                        modeInjectorCb.onSuccess(null);
                      } else {
                        injectMode(diffInfo, modeInjectorCb);
                      }
                    } else {
                      modeInjectorCb.onSuccess(null);
                    }
                  }
                }));

    if (Gerrit.isSignedIn()) {
      ChangeApi.edit(
          changeId.get(),
          group2.add(
              new AsyncCallback<EditInfo>() {
                @Override
                public void onSuccess(EditInfo result) {
                  edit = result;
                }

                @Override
                public void onFailure(Throwable caught) {}
              }));
    }

    final CommentsCollections comments = new CommentsCollections(base, revision, path);
    comments.load(group2);

    countParents(group2);

    RestApi call = ChangeApi.detail(changeId.get());
    ChangeList.addOptions(call, EnumSet.of(ListChangesOption.ALL_REVISIONS));
    call.get(
        group2.add(
            new AsyncCallback<ChangeInfo>() {
              @Override
              public void onSuccess(ChangeInfo info) {
                changeStatus = info.status();
                info.revisions().copyKeysIntoChildren("name");
                if (edit != null) {
                  edit.setName(edit.commit().commit());
                  info.setEdit(edit);
                  info.revisions().put(edit.name(), RevisionInfo.fromEdit(edit));
                }
                String currentRevision = info.currentRevision();
                boolean current =
                    currentRevision != null
                        && revision.get() == info.revision(currentRevision)._number();
                JsArray<RevisionInfo> list = info.revisions().values();
                RevisionInfo.sortRevisionInfoByNumber(list);
                getDiffTable()
                    .set(
                        prefs,
                        list,
                        parents,
                        diff,
                        edit != null,
                        current,
                        changeStatus.isOpen(),
                        diff.binary());
                header.setChangeInfo(info);
              }

              @Override
              public void onFailure(Throwable caught) {}
            }));

    ConfigInfoCache.get(changeId, group2.addFinal(getScreenLoadCallback(comments)));
  }

  private void countParents(CallbackGroup cbg) {
    ChangeApi.revision(changeId.get(), revision.getId())
        .view("commit")
        .get(
            cbg.add(
                new AsyncCallback<CommitInfo>() {
                  @Override
                  public void onSuccess(CommitInfo info) {
                    parents = info.parents().length();
                  }

                  @Override
                  public void onFailure(Throwable caught) {
                    parents = 0;
                  }
                }));
  }

  @Override
  public void onShowView() {
    super.onShowView();

    Window.enableScrolling(false);
    if (prefs.hideTopMenu()) {
      Gerrit.setHeaderVisible(false);
    }
    resizeHandler =
        Window.addResizeHandler(
            new ResizeHandler() {
              @Override
              public void onResize(ResizeEvent event) {
                resizeCodeMirror();
              }
            });
  }

  KeyCommandSet getKeysNavigation() {
    return keysNavigation;
  }

  KeyCommandSet getKeysAction() {
    return keysAction;
  }

  @Override
  protected void onUnload() {
    super.onUnload();

    removeKeyHandlerRegistrations();
    if (getCommentManager() != null) {
      CallbackGroup group = new CallbackGroup();
      getCommentManager().saveAllDrafts(group);
      group.done();
    }
    if (resizeHandler != null) {
      resizeHandler.removeHandler();
      resizeHandler = null;
    }
    for (CodeMirror cm : getCms()) {
      if (cm != null) {
        cm.getWrapperElement().removeFromParent();
      }
    }
    if (prefsAction != null) {
      prefsAction.hide();
    }

    Window.enableScrolling(true);
    Gerrit.setHeaderVisible(true);
  }

  private void removeKeyHandlerRegistrations() {
    for (HandlerRegistration h : handlers) {
      h.removeHandler();
    }
    handlers.clear();
  }

  void registerCmEvents(CodeMirror cm) {
    cm.on("cursorActivity", updateActiveLine(cm));
    cm.on("focus", updateActiveLine(cm));
    KeyMap keyMap =
        KeyMap.create()
            .on("A", upToChange(true))
            .on("U", upToChange(false))
            .on("'['", header.navigate(Direction.PREV))
            .on("']'", header.navigate(Direction.NEXT))
            .on("R", header.toggleReviewed())
            .on("O", getCommentManager().toggleOpenBox(cm))
            .on("N", maybeNextVimSearch(cm))
            .on("Ctrl-Alt-E", openEditScreen(cm))
            .on("P", getChunkManager().diffChunkNav(cm, Direction.PREV))
            .on("Shift-M", header.reviewedAndNext())
            .on("Shift-N", maybePrevVimSearch(cm))
            .on("Shift-P", getCommentManager().commentNav(cm, Direction.PREV))
            .on("Shift-O", getCommentManager().openCloseAll(cm))
            .on(
                "I",
                () -> {
                  switch (getIntraLineStatus()) {
                    case OFF:
                    case OK:
                      toggleShowIntraline();
                      break;
                    case FAILURE:
                    case TIMEOUT:
                    default:
                      break;
                  }
                })
            .on("','", prefsAction::show)
            .on(
                "Shift-/",
                () -> {
                  new ShowHelpCommand().onKeyPress(null);
                })
            .on(
                "Space",
                () -> {
                  cm.vim().handleKey("<C-d>");
                })
            .on(
                "Shift-Space",
                () -> {
                  cm.vim().handleKey("<C-u>");
                })
            .on(
                "Ctrl-F",
                () -> {
                  cm.execCommand("find");
                })
            .on(
                "Ctrl-G",
                () -> {
                  cm.execCommand("findNext");
                })
            .on("Enter", maybeNextCmSearch(cm))
            .on(
                "Shift-Ctrl-G",
                () -> {
                  cm.execCommand("findPrev");
                })
            .on(
                "Shift-Enter",
                () -> {
                  cm.execCommand("findPrev");
                })
            .on(
                "Esc",
                () -> {
                  cm.setCursor(cm.getCursor());
                  cm.execCommand("clearSearch");
                  cm.vim().handleEx("nohlsearch");
                })
            .on(
                "Ctrl-A",
                () -> {
                  cm.execCommand("selectAll");
                })
            .on(
                "G O",
                () -> {
                  Gerrit.display(PageLinks.toChangeQuery("status:open"));
                })
            .on(
                "G M",
                () -> {
                  Gerrit.display(PageLinks.toChangeQuery("status:merged"));
                })
            .on(
                "G A",
                () -> {
                  Gerrit.display(PageLinks.toChangeQuery("status:abandoned"));
                });
    if (Gerrit.isSignedIn()) {
      keyMap
          .on(
              "G I",
              () -> {
                Gerrit.display(PageLinks.MINE);
              })
          .on(
              "G D",
              () -> {
                Gerrit.display(PageLinks.toChangeQuery("owner:self is:draft"));
              })
          .on(
              "G C",
              () -> {
                Gerrit.display(PageLinks.toChangeQuery("has:draft"));
              })
          .on(
              "G W",
              () -> {
                Gerrit.display(PageLinks.toChangeQuery("is:watched status:open"));
              })
          .on(
              "G S",
              () -> {
                Gerrit.display(PageLinks.toChangeQuery("is:starred"));
              });
    }

    if (revision.get() != 0) {
      cm.on("beforeSelectionChange", onSelectionChange(cm));
      cm.on("gutterClick", onGutterClick(cm));
      keyMap.on("C", getCommentManager().newDraftCallback(cm));
    }
    CodeMirror.normalizeKeyMap(keyMap); // Needed to for multi-stroke keymaps
    cm.addKeyMap(keyMap);
  }

  void maybeRegisterRenderEntireFileKeyMap(CodeMirror cm) {
    if (renderEntireFile()) {
      cm.addKeyMap(RENDER_ENTIRE_FILE_KEYMAP);
    }
  }

  private BeforeSelectionChangeHandler onSelectionChange(final CodeMirror cm) {
    return new BeforeSelectionChangeHandler() {
      private InsertCommentBubble bubble;

      @Override
      public void handle(CodeMirror cm, Pos anchor, Pos head) {
        if (anchor.equals(head)) {
          if (bubble != null) {
            bubble.setVisible(false);
          }
          return;
        } else if (bubble == null) {
          init(anchor);
        } else {
          bubble.setVisible(true);
        }
        bubble.position(cm.charCoords(head, "local"));
      }

      private void init(Pos anchor) {
        bubble = new InsertCommentBubble(getCommentManager(), cm);
        add(bubble);
        cm.addWidget(anchor, bubble.getElement());
      }
    };
  }

  @Override
  public void registerKeys() {
    super.registerKeys();

    keysNavigation.add(new UpToChangeCommand(revision, 0, 'u'));
    keysNavigation.add(
        new NoOpKeyCommand(0, 'j', PatchUtil.C.lineNext()),
        new NoOpKeyCommand(0, 'k', PatchUtil.C.linePrev()));
    keysNavigation.add(
        new NoOpKeyCommand(0, 'n', PatchUtil.C.chunkNext()),
        new NoOpKeyCommand(0, 'p', PatchUtil.C.chunkPrev()));
    keysNavigation.add(
        new NoOpKeyCommand(KeyCommand.M_SHIFT, 'n', PatchUtil.C.commentNext()),
        new NoOpKeyCommand(KeyCommand.M_SHIFT, 'p', PatchUtil.C.commentPrev()));
    keysNavigation.add(new NoOpKeyCommand(KeyCommand.M_CTRL, 'f', Gerrit.C.keySearch()));

    keysAction = new KeyCommandSet(Gerrit.C.sectionActions());
    keysAction.add(new NoOpKeyCommand(0, KeyCodes.KEY_ENTER, PatchUtil.C.expandComment()));
    keysAction.add(new NoOpKeyCommand(0, 'o', PatchUtil.C.expandComment()));
    keysAction.add(
        new NoOpKeyCommand(KeyCommand.M_SHIFT, 'o', PatchUtil.C.expandAllCommentsOnCurrentLine()));
    if (Gerrit.isSignedIn()) {
      keysAction.add(
          new KeyCommand(0, 'r', PatchUtil.C.toggleReviewed()) {
            @Override
            public void onKeyPress(KeyPressEvent event) {
              header.toggleReviewed().run();
            }
          });
      keysAction.add(
          new NoOpKeyCommand(KeyCommand.M_CTRL | KeyCommand.M_ALT, 'e', Gerrit.C.keyEditor()));
    }
    keysAction.add(
        new KeyCommand(KeyCommand.M_SHIFT, 'm', PatchUtil.C.markAsReviewedAndGoToNext()) {
          @Override
          public void onKeyPress(KeyPressEvent event) {
            header.reviewedAndNext().run();
          }
        });
    keysAction.add(
        new KeyCommand(0, 'a', PatchUtil.C.openReply()) {
          @Override
          public void onKeyPress(KeyPressEvent event) {
            upToChange(true).run();
          }
        });
    keysAction.add(
        new KeyCommand(0, ',', PatchUtil.C.showPreferences()) {
          @Override
          public void onKeyPress(KeyPressEvent event) {
            prefsAction.show();
          }
        });
    if (getIntraLineStatus() == DiffInfo.IntraLineStatus.OFF
        || getIntraLineStatus() == DiffInfo.IntraLineStatus.OK) {
      keysAction.add(
          new KeyCommand(0, 'i', PatchUtil.C.toggleIntraline()) {
            @Override
            public void onKeyPress(KeyPressEvent event) {
              toggleShowIntraline();
            }
          });
    }

    if (Gerrit.isSignedIn()) {
      keysAction.add(new NoOpKeyCommand(0, 'c', PatchUtil.C.commentInsert()));
      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;
    }
  }

  void registerHandlers() {
    removeKeyHandlerRegistrations();
    handlers.add(GlobalKey.add(this, keysAction));
    handlers.add(GlobalKey.add(this, keysNavigation));
    if (keysComment != null) {
      handlers.add(GlobalKey.add(this, keysComment));
    }
    handlers.add(ShowHelpCommand.addFocusHandler(getFocusHandler()));
  }

  void setupSyntaxHighlighting() {
    if (prefs.syntaxHighlighting() && fileSize.compareTo(FileSize.SMALL) > 0) {
      Scheduler.get()
          .scheduleFixedDelay(
              new RepeatingCommand() {
                @Override
                public boolean execute() {
                  if (prefs.syntaxHighlighting() && isAttached()) {
                    setSyntaxHighlighting(prefs.syntaxHighlighting());
                  }
                  return false;
                }
              },
              250);
    }
  }

  abstract CodeMirror newCm(DiffInfo.FileMeta meta, String contents, Element parent);

  void render(DiffInfo diff) {
    header.setNoDiff(diff);
    getChunkManager().render(diff);
  }

  void setShowLineNumbers(boolean b) {
    if (b) {
      getDiffTable().addStyleName(Resources.I.diffTableStyle().showLineNumbers());
    } else {
      getDiffTable().removeStyleName(Resources.I.diffTableStyle().showLineNumbers());
    }
  }

  void setShowIntraline(boolean b) {
    if (b && getIntraLineStatus() == DiffInfo.IntraLineStatus.OFF) {
      reloadDiffInfo();
    } else if (b) {
      getDiffTable().removeStyleName(Resources.I.diffTableStyle().noIntraline());
    } else {
      getDiffTable().addStyleName(Resources.I.diffTableStyle().noIntraline());
    }
  }

  private void toggleShowIntraline() {
    prefs.intralineDifference(!Boolean.valueOf(prefs.intralineDifference()));
    setShowIntraline(prefs.intralineDifference());
    prefsAction.update();
  }

  abstract void setSyntaxHighlighting(boolean b);

  void setContext(final int context) {
    operation(
        () -> {
          skipManager.removeAll();
          skipManager.render(context, diff);
          updateRenderEntireFile();
        });
  }

  private int adjustCommitMessageLine(int line) {
    /* When commit messages are shown in the diff screen they include
      a header block that looks like this:

      1 Parent:     deadbeef (Parent commit title)
      2 Author:     A. U. Thor <author@example.com>
      3 AuthorDate: 2015-02-27 19:20:52 +0900
      4 Commit:     A. U. Thor <author@example.com>
      5 CommitDate: 2015-02-27 19:20:52 +0900
      6 [blank line]
      7 Commit message title
      8
      9 Commit message body
     10 ...
     11 ...

    If the commit is a merge commit, both parent commits are listed in the
    first two lines instead of a 'Parent' line:

      1 Merge Of:   deadbeef (Parent 1 commit title)
      2             beefdead (Parent 2 commit title)

    */

    // Offset to compensate for header lines until the blank line
    // after 'CommitDate'
    int offset = 6;

    // Adjust for merge commits, which have two parent lines
    if (diff.textB().startsWith("Merge")) {
      offset += 1;
    }

    // If the cursor is inside the header line, reset to the first line of the
    // commit message. Otherwise if the cursor is on an actual line of the commit
    // message, adjust the line number to compensate for the header lines, so the
    // focus is on the correct line.
    if (line <= offset) {
      return 1;
    }
    return line - offset;
  }

  private Runnable openEditScreen(CodeMirror cm) {
    return () -> {
      LineHandle handle = cm.extras().activeLine();
      int line = cm.getLineNumber(handle) + 1;
      if (Patch.COMMIT_MSG.equals(path)) {
        line = adjustCommitMessageLine(line);
      }
      String token = Dispatcher.toEditScreen(revision, path, line);
      if (!Gerrit.isSignedIn()) {
        Gerrit.doSignIn(token);
      } else {
        Gerrit.display(token);
      }
    };
  }

  void updateRenderEntireFile() {
    boolean entireFile = renderEntireFile();
    for (CodeMirror cm : getCms()) {
      cm.removeKeyMap(RENDER_ENTIRE_FILE_KEYMAP);
      if (entireFile) {
        cm.addKeyMap(RENDER_ENTIRE_FILE_KEYMAP);
      }
      cm.setOption("viewportMargin", entireFile ? POSITIVE_INFINITY : 10);
    }
  }

  void resizeCodeMirror() {
    int height = header.getOffsetHeight() + getDiffTable().getHeaderHeight();
    for (CodeMirror cm : getCms()) {
      cm.adjustHeight(height);
    }
  }

  abstract ChunkManager getChunkManager();

  abstract CommentManager getCommentManager();

  Change.Status getChangeStatus() {
    return changeStatus;
  }

  int getStartLine() {
    return startLine;
  }

  void setStartLine(int startLine) {
    this.startLine = startLine;
  }

  DisplaySide getStartSide() {
    return startSide;
  }

  void setStartSide(DisplaySide startSide) {
    this.startSide = startSide;
  }

  DiffInfo getDiff() {
    return diff;
  }

  FileSize getFileSize() {
    return fileSize;
  }

  PreferencesAction getPrefsAction() {
    return prefsAction;
  }

  void setPrefsAction(PreferencesAction prefsAction) {
    this.prefsAction = prefsAction;
  }

  abstract void operation(Runnable apply);

  private Runnable upToChange(boolean openReplyBox) {
    return () -> {
      CallbackGroup group = new CallbackGroup();
      getCommentManager().saveAllDrafts(group);
      group.done();
      group.addListener(
          new GerritCallback<Void>() {
            @Override
            public void onSuccess(Void result) {
              String rev = String.valueOf(revision.get());
              Gerrit.display(
                  PageLinks.toChange(changeId, base.asString(), rev),
                  new ChangeScreen(changeId, base, rev, openReplyBox, FileTable.Mode.REVIEW));
            }
          });
    };
  }

  private Runnable maybePrevVimSearch(CodeMirror cm) {
    return () -> {
      if (cm.vim().hasSearchHighlight()) {
        cm.vim().handleKey("N");
      } else {
        getCommentManager().commentNav(cm, Direction.NEXT).run();
      }
    };
  }

  private Runnable maybeNextVimSearch(CodeMirror cm) {
    return () -> {
      if (cm.vim().hasSearchHighlight()) {
        cm.vim().handleKey("n");
      } else {
        getChunkManager().diffChunkNav(cm, Direction.NEXT).run();
      }
    };
  }

  Runnable maybeNextCmSearch(CodeMirror cm) {
    return () -> {
      if (cm.hasSearchHighlight()) {
        cm.execCommand("findNext");
      } else {
        cm.execCommand("clearSearch");
        getCommentManager().toggleOpenBox(cm).run();
      }
    };
  }

  boolean renderEntireFile() {
    return prefs.renderEntireFile() && canRenderEntireFile(prefs);
  }

  boolean canRenderEntireFile(DiffPreferences prefs) {
    // CodeMirror is too slow to layout an entire huge file.
    return fileSize.compareTo(FileSize.HUGE) < 0
        || (prefs.context() != WHOLE_FILE_CONTEXT && prefs.context() < 100);
  }

  DiffInfo.IntraLineStatus getIntraLineStatus() {
    return diff.intralineStatus();
  }

  void setThemeStyles(boolean d) {
    if (d) {
      getDiffTable().addStyleName(Resources.I.diffTableStyle().dark());
    } else {
      getDiffTable().removeStyleName(Resources.I.diffTableStyle().dark());
    }
  }

  void setShowTabs(boolean show) {
    for (CodeMirror cm : getCms()) {
      cm.extras().showTabs(show);
    }
  }

  void setLineLength(int columns) {
    for (CodeMirror cm : getCms()) {
      cm.extras().lineLength(columns);
    }
  }

  String getContentType(DiffInfo.FileMeta meta) {
    if (prefs.syntaxHighlighting() && meta != null && meta.contentType() != null) {
      ModeInfo m = ModeInfo.findMode(meta.contentType(), path);
      return m != null ? m.mime() : null;
    }
    return null;
  }

  String getContentType() {
    return getContentType(diff.metaB());
  }

  void injectMode(DiffInfo diffInfo, AsyncCallback<Void> cb) {
    new ModeInjector()
        .add(getContentType(diffInfo.metaA()))
        .add(getContentType(diffInfo.metaB()))
        .inject(cb);
  }

  abstract void setAutoHideDiffHeader(boolean hide);

  void prefetchNextFile() {
    String nextPath = header.getNextPath();
    if (nextPath != null) {
      DiffApi.diff(revision, nextPath)
          .base(base.asPatchSetId())
          .wholeFile()
          .intraline(prefs.intralineDifference())
          .ignoreWhitespace(prefs.ignoreWhitespace())
          .get(
              new AsyncCallback<DiffInfo>() {
                @Override
                public void onSuccess(DiffInfo info) {
                  new ModeInjector()
                      .add(getContentType(info.metaA()))
                      .add(getContentType(info.metaB()))
                      .inject(CallbackGroup.<Void>emptyCallback());
                }

                @Override
                public void onFailure(Throwable caught) {}
              });
    }
  }

  void reloadDiffInfo() {
    int id = ++reloadVersionId;
    DiffApi.diff(revision, path)
        .base(base.asPatchSetId())
        .wholeFile()
        .intraline(prefs.intralineDifference())
        .ignoreWhitespace(prefs.ignoreWhitespace())
        .get(
            new GerritCallback<DiffInfo>() {
              @Override
              public void onSuccess(DiffInfo diffInfo) {
                if (id == reloadVersionId && isAttached()) {
                  diff = diffInfo;
                  operation(
                      () -> {
                        skipManager.removeAll();
                        getChunkManager().reset();
                        getDiffTable().scrollbar.removeDiffAnnotations();
                        setShowIntraline(prefs.intralineDifference());
                        render(diff);
                        skipManager.render(prefs.context(), diff);
                      });
                }
              }
            });
  }

  private static FileSize bucketFileSize(DiffInfo diff) {
    FileMeta a = diff.metaA();
    FileMeta b = diff.metaB();
    FileSize[] sizes = FileSize.values();
    for (int i = sizes.length - 1; 0 <= i; i--) {
      FileSize s = sizes[i];
      if ((a != null && s.lines <= a.lines()) || (b != null && s.lines <= b.lines())) {
        return s;
      }
    }
    return FileSize.SMALL;
  }

  abstract Runnable updateActiveLine(CodeMirror cm);

  private GutterClickHandler onGutterClick(final CodeMirror cm) {
    return new GutterClickHandler() {
      @Override
      public void handle(
          CodeMirror instance, final int line, final String gutterClass, NativeEvent clickEvent) {
        if (Element.as(clickEvent.getEventTarget()).hasClassName(getLineNumberClassName())
            && clickEvent.getButton() == NativeEvent.BUTTON_LEFT
            && !clickEvent.getMetaKey()
            && !clickEvent.getAltKey()
            && !clickEvent.getCtrlKey()
            && !clickEvent.getShiftKey()) {
          cm.setCursor(Pos.create(line));
          Scheduler.get()
              .scheduleDeferred(
                  new ScheduledCommand() {
                    @Override
                    public void execute() {
                      getCommentManager().newDraftOnGutterClick(cm, gutterClass, line + 1);
                    }
                  });
        }
      }
    };
  }

  abstract FocusHandler getFocusHandler();

  abstract CodeMirror[] getCms();

  abstract CodeMirror getCmFromSide(DisplaySide side);

  abstract DiffTable getDiffTable();

  abstract int getCmLine(int line, DisplaySide side);

  abstract String getLineNumberClassName();

  LineOnOtherInfo lineOnOther(DisplaySide side, int line) {
    return getChunkManager().lineMapper.lineOnOther(side, line);
  }

  abstract ScreenLoadCallback<ConfigInfoCache.Entry> getScreenLoadCallback(
      CommentsCollections comments);

  abstract boolean isSideBySide();
}
