// 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.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.gerrit.reviewdb.client.PatchSet;
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 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;

import java.util.Collections;
import java.util.List;

public class SideBySide extends DiffScreen {
  interface Binder extends UiBinder<FlowPanel, SideBySide> {}
  private static final Binder uiBinder = GWT.create(Binder.class);

  @UiField(provided = true)
  SideBySideTable diffTable;

  private CodeMirror cmA;
  private CodeMirror cmB;

  private ScrollSynchronizer scrollSynchronizer;

  private SideBySideChunkManager chunkManager;
  private SideBySideCommentManager commentManager;
  private SideBySideSkipManager skipManager;

  public SideBySide(
      PatchSet.Id base,
      PatchSet.Id 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);
      }
    };
  }

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

    operation(new Runnable() {
      @Override
      public void run() {
        resizeCodeMirror();
        chunkManager.adjustPadding();
        cmA.refresh();
        cmB.refresh();
      }
    });
    setLineLength(Patch.COMMIT_MSG.equals(prefs) ? 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(SideBySideTable.style.showLineNumbers());
    }

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

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

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

    operation(new Runnable() {
      @Override
      public void run() {
        // Estimate initial CM3 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.getLineMapper());

    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("lineWrapping", false)
      .set("matchBrackets", prefs.matchBrackets())
      .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) {
    cmA.setOption("lineNumbers", b);
    cmB.setOption("lineNumbers", b);
    if (b) {
      diffTable.addStyleName(SideBySideTable.style.showLineNumbers());
    } else {
      diffTable.removeStyleName(SideBySideTable.style.showLineNumbers());
    }
  }

  @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
  Runnable updateActiveLine(final CodeMirror cm) {
    final CodeMirror other = otherCm(cm);
    return new Runnable() {
      @Override
      public void run() {
        // 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(new Runnable() {
              @Override
              public void run() {
                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 new Runnable() {
        @Override
        public void run() {
        }
      };
    }

    final DisplaySide sideSrc = cmSrc.side();
    return new Runnable() {
      @Override
      public void run() {
        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(final Runnable apply) {
    cmA.operation(new Runnable() {
      @Override
      public void run() {
        cmB.operation(new Runnable() {
          @Override
          public void run() {
            apply.run();
          }
        });
      }
    });
  }

  @Override
  int getCodeMirrorHeight() {
    return header.getOffsetHeight() + diffTable.getHeaderHeight();
  }

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

  @Override
  SideBySideTable getDiffTable() {
    return diffTable;
  }

  @Override
  SideBySideChunkManager getChunkManager() {
    return chunkManager;
  }

  @Override
  SideBySideCommentManager getCommentManager() {
    return commentManager;
  }

  @Override
  SideBySideSkipManager getSkipManager() {
    return skipManager;
  }
}
