// 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 implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.client.diff;

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.diff.LineMapper.LineOnOtherInfo;
import com.google.gerrit.client.patches.PatchUtil;
import com.google.gerrit.client.projects.ConfigInfoCache;
import com.google.gerrit.client.rpc.ScreenLoadCallback;
import com.google.gerrit.client.ui.InlineHyperlink;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DiffView;
import com.google.gerrit.reviewdb.client.Patch;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Element;
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.uibinder.client.UiBinder;
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.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.ImageResourceRenderer;
import com.google.gwtexpui.globalkey.client.GlobalKey;
import com.google.gwtexpui.globalkey.client.KeyCommand;
import java.util.Collections;
import java.util.List;
import net.codemirror.lib.CodeMirror;
import net.codemirror.lib.CodeMirror.LineHandle;
import net.codemirror.lib.Configuration;
import net.codemirror.lib.KeyMap;
import net.codemirror.lib.Pos;

public class SideBySide extends DiffScreen {
  interface Binder extends UiBinder<FlowPanel, SideBySide> {}

  private static final Binder uiBinder = GWT.create(Binder.class);
  private static final String LINE_NUMBER_CLASSNAME = "CodeMirror-linenumber";

  @UiField(provided = true)
  SideBySideTable diffTable;

  private CodeMirror cmA;
  private CodeMirror cmB;

  private ScrollSynchronizer scrollSynchronizer;

  private SideBySideChunkManager chunkManager;
  private SideBySideCommentManager commentManager;

  public SideBySide(
      DiffObject base, DiffObject revision, String path, DisplaySide startSide, int startLine) {
    super(base, revision, path, startSide, startLine, DiffView.SIDE_BY_SIDE);

    diffTable = new SideBySideTable(this, base, revision, path);
    add(uiBinder.createAndBindUi(this));
    addDomHandler(GlobalKey.STOP_PROPAGATION, KeyPressEvent.getType());
  }

  @Override
  ScreenLoadCallback<ConfigInfoCache.Entry> getScreenLoadCallback(
      final CommentsCollections comments) {
    return new ScreenLoadCallback<ConfigInfoCache.Entry>(SideBySide.this) {
      @Override
      protected void preDisplay(ConfigInfoCache.Entry result) {
        commentManager =
            new SideBySideCommentManager(
                SideBySide.this,
                base,
                revision,
                path,
                result.getCommentLinkProcessor(),
                getChangeStatus().isOpen());
        setTheme(result.getTheme());
        display(comments);
        header.setupPrevNextFiles(comments);
      }
    };
  }

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

    operation(
        () -> {
          resizeCodeMirror();
          chunkManager.adjustPadding();
          cmA.refresh();
          cmB.refresh();
        });
    setLineLength(Patch.COMMIT_MSG.equals(path) ? 72 : prefs.lineLength());
    diffTable.refresh();

    if (getStartLine() == 0) {
      DiffChunkInfo d = chunkManager.getFirst();
      if (d != null) {
        if (d.isEdit() && d.getSide() == DisplaySide.A) {
          setStartSide(DisplaySide.B);
          setStartLine(lineOnOther(d.getSide(), d.getStart()).getLine() + 1);
        } else {
          setStartSide(d.getSide());
          setStartLine(d.getStart() + 1);
        }
      }
    }
    if (getStartSide() != null && getStartLine() > 0) {
      CodeMirror cm = getCmFromSide(getStartSide());
      cm.scrollToLine(getStartLine() - 1);
      cm.focus();
    } else {
      cmA.setCursor(Pos.create(0));
      cmA.focus();
    }
    if (Gerrit.isSignedIn() && prefs.autoReview()) {
      header.autoReview();
    }
    prefetchNextFile();
  }

  @Override
  void registerCmEvents(final CodeMirror cm) {
    super.registerCmEvents(cm);

    KeyMap keyMap =
        KeyMap.create()
            .on("Shift-A", diffTable.toggleA())
            .on("Shift-Left", moveCursorToSide(cm, DisplaySide.A))
            .on("Shift-Right", moveCursorToSide(cm, DisplaySide.B));
    cm.addKeyMap(keyMap);
    maybeRegisterRenderEntireFileKeyMap(cm);
  }

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

    getKeysNavigation()
        .add(
            new NoOpKeyCommand(KeyCommand.M_SHIFT, KeyCodes.KEY_LEFT, PatchUtil.C.focusSideA()),
            new NoOpKeyCommand(KeyCommand.M_SHIFT, KeyCodes.KEY_RIGHT, PatchUtil.C.focusSideB()));
    getKeysAction()
        .add(
            new KeyCommand(KeyCommand.M_SHIFT, 'a', PatchUtil.C.toggleSideA()) {
              @Override
              public void onKeyPress(KeyPressEvent event) {
                diffTable.toggleA().run();
              }
            });

    registerHandlers();
  }

  @Override
  FocusHandler getFocusHandler() {
    return new FocusHandler() {
      @Override
      public void onFocus(FocusEvent event) {
        cmB.focus();
      }
    };
  }

  private void display(final CommentsCollections comments) {
    final DiffInfo diff = getDiff();
    setThemeStyles(prefs.theme().isDark());
    setShowIntraline(prefs.intralineDifference());
    if (prefs.showLineNumbers()) {
      diffTable.addStyleName(Resources.I.diffTableStyle().showLineNumbers());
    }

    cmA = newCm(diff.metaA(), diff.textA(), diffTable.cmA);
    cmB = newCm(diff.metaB(), diff.textB(), diffTable.cmB);

    getDiffTable()
        .setUpBlameIconA(
            cmA,
            base.isBaseOrAutoMerge(),
            base.isBaseOrAutoMerge() ? revision : base.asPatchSetId(),
            path);
    getDiffTable().setUpBlameIconB(cmB, revision, path);

    cmA.extras().side(DisplaySide.A);
    cmB.extras().side(DisplaySide.B);
    setShowTabs(prefs.showTabs());

    chunkManager = new SideBySideChunkManager(this, cmA, cmB, diffTable.scrollbar);

    operation(
        () -> {
          // Estimate initial CodeMirror height, fixed up in onShowView.
          int height = Window.getClientHeight() - (Gerrit.getHeaderFooterHeight() + 18);
          cmA.setHeight(height);
          cmB.setHeight(height);

          render(diff);
          commentManager.render(comments, prefs.expandAllComments());
          skipManager.render(prefs.context(), diff);
        });

    registerCmEvents(cmA);
    registerCmEvents(cmB);
    scrollSynchronizer = new ScrollSynchronizer(diffTable, cmA, cmB, chunkManager.lineMapper);

    setPrefsAction(new PreferencesAction(this, prefs));
    header.init(getPrefsAction(), getUnifiedDiffLink(), diff.sideBySideWebLinks());
    scrollSynchronizer.setAutoHideDiffTableHeader(prefs.autoHideDiffTableHeader());

    setupSyntaxHighlighting();
  }

  private List<InlineHyperlink> getUnifiedDiffLink() {
    InlineHyperlink toUnifiedDiffLink = new InlineHyperlink();
    toUnifiedDiffLink.setHTML(new ImageResourceRenderer().render(Gerrit.RESOURCES.unifiedDiff()));
    toUnifiedDiffLink.setTargetHistoryToken(Dispatcher.toUnified(base, revision, path));
    toUnifiedDiffLink.setTitle(PatchUtil.C.unifiedDiff());
    return Collections.singletonList(toUnifiedDiffLink);
  }

  @Override
  CodeMirror newCm(DiffInfo.FileMeta meta, String contents, Element parent) {
    return CodeMirror.create(
        parent,
        Configuration.create()
            .set("cursorBlinkRate", prefs.cursorBlinkRate())
            .set("cursorHeight", 0.85)
            .set("inputStyle", "textarea")
            .set("keyMap", "vim_ro")
            .set("lineNumbers", prefs.showLineNumbers())
            .set("matchBrackets", prefs.matchBrackets())
            .set("lineWrapping", prefs.lineWrapping())
            .set("mode", getFileSize() == FileSize.SMALL ? getContentType(meta) : null)
            .set("readOnly", true)
            .set("scrollbarStyle", "overlay")
            .set("showTrailingSpace", prefs.showWhitespaceErrors())
            .set("styleSelectedText", true)
            .set("tabSize", prefs.tabSize())
            .set("theme", prefs.theme().name().toLowerCase())
            .set("value", meta != null ? contents : "")
            .set("viewportMargin", renderEntireFile() ? POSITIVE_INFINITY : 10));
  }

  @Override
  void setShowLineNumbers(boolean b) {
    super.setShowLineNumbers(b);

    cmA.setOption("lineNumbers", b);
    cmB.setOption("lineNumbers", b);
  }

  @Override
  void setSyntaxHighlighting(boolean b) {
    final DiffInfo diff = getDiff();
    if (b) {
      injectMode(
          diff,
          new AsyncCallback<Void>() {
            @Override
            public void onSuccess(Void result) {
              if (prefs.syntaxHighlighting()) {
                cmA.setOption("mode", getContentType(diff.metaA()));
                cmB.setOption("mode", getContentType(diff.metaB()));
              }
            }

            @Override
            public void onFailure(Throwable caught) {
              prefs.syntaxHighlighting(false);
            }
          });
    } else {
      cmA.setOption("mode", (String) null);
      cmB.setOption("mode", (String) null);
    }
  }

  @Override
  void setAutoHideDiffHeader(boolean hide) {
    scrollSynchronizer.setAutoHideDiffTableHeader(hide);
  }

  CodeMirror otherCm(CodeMirror me) {
    return me == cmA ? cmB : cmA;
  }

  @Override
  CodeMirror getCmFromSide(DisplaySide side) {
    return side == DisplaySide.A ? cmA : cmB;
  }

  @Override
  int getCmLine(int line, DisplaySide side) {
    return line;
  }

  @Override
  Runnable updateActiveLine(final CodeMirror cm) {
    final CodeMirror other = otherCm(cm);
    return () -> {
      // The rendering of active lines has to be deferred. Reflow
      // caused by adding and removing styles chokes Firefox when arrow
      // key (or j/k) is held down. Performance on Chrome is fine
      // without the deferral.
      //
      Scheduler.get()
          .scheduleDeferred(
              new ScheduledCommand() {
                @Override
                public void execute() {
                  operation(
                      () -> {
                        LineHandle handle = cm.getLineHandleVisualStart(cm.getCursor("end").line());
                        if (!cm.extras().activeLine(handle)) {
                          return;
                        }

                        LineOnOtherInfo info = lineOnOther(cm.side(), cm.getLineNumber(handle));
                        if (info.isAligned()) {
                          other.extras().activeLine(other.getLineHandle(info.getLine()));
                        } else {
                          other.extras().clearActiveLine();
                        }
                      });
                }
              });
    };
  }

  private Runnable moveCursorToSide(final CodeMirror cmSrc, DisplaySide sideDst) {
    final CodeMirror cmDst = getCmFromSide(sideDst);
    if (cmDst == cmSrc) {
      return () -> {};
    }

    final DisplaySide sideSrc = cmSrc.side();
    return () -> {
      if (cmSrc.extras().hasActiveLine()) {
        cmDst.setCursor(
            Pos.create(
                lineOnOther(sideSrc, cmSrc.getLineNumber(cmSrc.extras().activeLine())).getLine()));
      }
      cmDst.focus();
    };
  }

  void syncScroll(DisplaySide masterSide) {
    if (scrollSynchronizer != null) {
      scrollSynchronizer.syncScroll(masterSide);
    }
  }

  @Override
  void operation(Runnable apply) {
    cmA.operation(
        () -> {
          cmB.operation(apply::run);
        });
  }

  @Override
  CodeMirror[] getCms() {
    return new CodeMirror[] {cmA, cmB};
  }

  @Override
  SideBySideTable getDiffTable() {
    return diffTable;
  }

  @Override
  SideBySideChunkManager getChunkManager() {
    return chunkManager;
  }

  @Override
  SideBySideCommentManager getCommentManager() {
    return commentManager;
  }

  @Override
  boolean isSideBySide() {
    return true;
  }

  @Override
  String getLineNumberClassName() {
    return LINE_NUMBER_CLASSNAME;
  }
}
