// 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 net.codemirror.lib;

import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.diff.DisplaySide;
import com.google.gerrit.client.rpc.CallbackGroup;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;

import net.codemirror.lib.TextMarker.FromTo;

/**
 * Glue to connect CodeMirror to be callable from GWT.
 *
 * @see <a href="http://codemirror.net/doc/manual.html#api">CodeMirror API</a>
 */
public class CodeMirror extends JavaScriptObject {
  public static void preload() {
    initLibrary(CallbackGroup.<Void> emptyCallback());
  }

  public static void initLibrary(AsyncCallback<Void> cb) {
    Loader.initLibrary(cb);
  }

  interface Style extends CssResource {
    String activeLine();
    String showTabs();
    String margin();
  }

  static Style style() {
    return Lib.I.style();
  }

  public static CodeMirror create(Element p, Configuration cfg) {
    CodeMirror cm = newCM(p, cfg);
    Extras.attach(cm);
    return cm;
  }

  private static native CodeMirror newCM(Element p, Configuration cfg) /*-{
    return $wnd.CodeMirror(p, cfg);
  }-*/;

  public final native void setOption(String option, boolean value) /*-{
    this.setOption(option, value)
  }-*/;

  public final native void setOption(String option, double value) /*-{
    this.setOption(option, value)
  }-*/;

  public final native void setOption(String option, String value) /*-{
    this.setOption(option, value)
  }-*/;

  public final native void setOption(String option, JavaScriptObject val) /*-{
    this.setOption(option, val)
  }-*/;

  public final native String getStringOption(String o) /*-{ return this.getOption(o) }-*/;

  public final native String getValue() /*-{ return this.getValue() }-*/;
  public final native void setValue(String v) /*-{ this.setValue(v) }-*/;

  public final native int changeGeneration(boolean closeEvent)
  /*-{ return this.changeGeneration(closeEvent) }-*/;
  public final native boolean isClean(int generation)
  /*-{ return this.isClean(generation) }-*/;

  public final native void setWidth(double w) /*-{ this.setSize(w, null) }-*/;
  public final native void setHeight(double h) /*-{ this.setSize(null, h) }-*/;

  public final int getHeight() {
    return getWrapperElement().getClientHeight();
  }

  public final void adjustHeight(int localHeader) {
    int rest = Gerrit.getHeaderFooterHeight()
        + localHeader
        + 5; // Estimate
    setHeight(Window.getClientHeight() - rest);
  }

  public final native String getLine(int n) /*-{ return this.getLine(n) }-*/;
  public final native double barHeight() /*-{ return this.display.barHeight }-*/;
  public final native double barWidth() /*-{ return this.display.barWidth }-*/;
  public final native int lastLine() /*-{ return this.lastLine() }-*/;
  public final native void refresh() /*-{ this.refresh() }-*/;

  public final native TextMarker markText(Pos from, Pos to,
      Configuration options) /*-{
    return this.markText(from, to, options)
  }-*/;

  public enum LineClassWhere {
    TEXT { @Override String value() { return "text"; } },
    BACKGROUND { @Override String value() { return "background"; } },
    WRAP { @Override String value() { return "wrap"; } };
    abstract String value();
  }

  public final void addLineClass(int line, LineClassWhere where,
      String className) {
    addLineClassNative(line, where.value(), className);
  }

  private final native void addLineClassNative(int line, String where,
      String lineClass) /*-{
    this.addLineClass(line, where, lineClass)
  }-*/;

  public final void addLineClass(LineHandle line, LineClassWhere where,
      String className) {
    addLineClassNative(line, where.value(), className);
  }

  private final native void addLineClassNative(LineHandle line, String where,
      String lineClass) /*-{
    this.addLineClass(line, where, lineClass)
  }-*/;

  public final void removeLineClass(int line, LineClassWhere where,
      String className) {
    removeLineClassNative(line, where.value(), className);
  }

  private final native void removeLineClassNative(int line, String where,
      String lineClass) /*-{
    this.removeLineClass(line, where, lineClass)
  }-*/;

  public final void removeLineClass(LineHandle line, LineClassWhere where,
      String className) {
    removeLineClassNative(line, where.value(), className);
  }

  private final native void removeLineClassNative(LineHandle line, String where,
      String lineClass) /*-{
    this.removeLineClass(line, where, lineClass)
  }-*/;

  public final native void addWidget(Pos pos, Element node) /*-{
    this.addWidget(pos, node, false)
  }-*/;

  public final native LineWidget addLineWidget(int line, Element node,
      Configuration options) /*-{
    return this.addLineWidget(line, node, options)
  }-*/;

  public final native int lineAtHeight(double height) /*-{
    return this.lineAtHeight(height)
  }-*/;

  public final native int lineAtHeight(double height, String mode) /*-{
    return this.lineAtHeight(height, mode)
  }-*/;

  public final native double heightAtLine(int line) /*-{
    return this.heightAtLine(line)
  }-*/;

  public final native double heightAtLine(int line, String mode) /*-{
    return this.heightAtLine(line, mode)
  }-*/;

  public final native Rect charCoords(Pos pos, String mode) /*-{
    return this.charCoords(pos, mode)
  }-*/;

  public final native CodeMirrorDoc getDoc() /*-{
    return this.getDoc()
  }-*/;

  public final native void scrollTo(double x, double y) /*-{
    this.scrollTo(x, y)
  }-*/;

  public final native void scrollToY(double y) /*-{
    this.scrollTo(null, y)
  }-*/;

  public final void scrollToLine(int line) {
    int height = getHeight();
    if (lineAtHeight(height - 20) < line) {
      scrollToY(heightAtLine(line, "local") - 0.5 * height);
    }
    setCursor(Pos.create(line, 0));
  }

  public final native ScrollInfo getScrollInfo() /*-{
    return this.getScrollInfo()
  }-*/;

  public final native Viewport getViewport() /*-{
    return this.getViewport()
  }-*/;

  public final native void operation(Runnable thunk) /*-{
    this.operation(function() {
      thunk.@java.lang.Runnable::run()();
    })
  }-*/;

  public final native void off(String event, RegisteredHandler h) /*-{
    this.off(event, h)
  }-*/;

  public final native RegisteredHandler on(String event, Runnable thunk) /*-{
    var h = $entry(function() { thunk.@java.lang.Runnable::run()() });
    this.on(event, h);
    return h;
  }-*/;

  public final native void on(String event, EventHandler handler) /*-{
    this.on(event, $entry(function(cm, e) {
      handler.@net.codemirror.lib.CodeMirror.EventHandler::handle(
        Lnet/codemirror/lib/CodeMirror;
        Lcom/google/gwt/dom/client/NativeEvent;)(cm, e);
    }))
  }-*/;

  public final native void on(String event, RenderLineHandler handler) /*-{
    this.on(event, $entry(function(cm, h, e) {
      handler.@net.codemirror.lib.CodeMirror.RenderLineHandler::handle(
        Lnet/codemirror/lib/CodeMirror;
        Lnet/codemirror/lib/CodeMirror$LineHandle;
        Lcom/google/gwt/dom/client/Element;)(cm, h, e);
    }))
  }-*/;

  public final native void on(String event, GutterClickHandler handler) /*-{
    this.on(event, $entry(function(cm, l, g, e) {
      handler.@net.codemirror.lib.CodeMirror.GutterClickHandler::handle(
        Lnet/codemirror/lib/CodeMirror;
        I
        Ljava/lang/String;
        Lcom/google/gwt/dom/client/NativeEvent;)(cm, l, g, e);
    }))
  }-*/;

  public final native void on(String event, BeforeSelectionChangeHandler handler) /*-{
    this.on(event, $entry(function(cm, o) {
      var e = o.ranges[o.ranges.length-1];
      handler.@net.codemirror.lib.CodeMirror.BeforeSelectionChangeHandler::handle(
        Lnet/codemirror/lib/CodeMirror;
        Lnet/codemirror/lib/Pos;
        Lnet/codemirror/lib/Pos;)(cm, e.anchor, e.head);
    }))
  }-*/;

  public final native void on(ChangesHandler handler) /*-{
    this.on('changes', $entry(function(cm, o) {
      handler.@net.codemirror.lib.CodeMirror.ChangesHandler::handle(
        Lnet/codemirror/lib/CodeMirror;)(cm);
    }))
  }-*/;

  public final native void setCursor(Pos p) /*-{ this.setCursor(p) }-*/;
  public final native Pos getCursor() /*-{ return this.getCursor() }-*/;
  public final native Pos getCursor(String start) /*-{
    return this.getCursor(start)
  }-*/;

  public final FromTo getSelectedRange() {
    return FromTo.create(getCursor("start"), getCursor("end"));
  }

  public final native void setSelection(Pos p) /*-{ this.setSelection(p) }-*/;
  public final native void setSelection(Pos anchor, Pos head) /*-{
    this.setSelection(anchor, head)
  }-*/;

  public final native boolean somethingSelected() /*-{
    return this.somethingSelected()
  }-*/;

  public final native void addKeyMap(KeyMap map) /*-{ this.addKeyMap(map) }-*/;
  public final native void removeKeyMap(KeyMap map) /*-{ this.removeKeyMap(map) }-*/;

  public final native LineHandle getLineHandle(int line) /*-{
    return this.getLineHandle(line)
  }-*/;

  public final native LineHandle getLineHandleVisualStart(int line) /*-{
    return this.getLineHandleVisualStart(line)
  }-*/;

  public final native int getLineNumber(LineHandle handle) /*-{
    return this.getLineNumber(handle)
  }-*/;

  public final native void focus() /*-{
    this.focus()
  }-*/;

  public final native Element getWrapperElement() /*-{
    return this.getWrapperElement()
  }-*/;

  public final native Element getGutterElement() /*-{
    return this.getGutterElement()
  }-*/;

  public final native Element sizer() /*-{
    return this.display.sizer
  }-*/;

  public final native Element mover() /*-{
    return this.display.mover
  }-*/;

  public final native Element measure() /*-{
    return this.display.measure
  }-*/;

  public final native Element scrollbarV() /*-{
    return this.display.scrollbars.vert.node;
  }-*/;

  public final native void execCommand(String cmd) /*-{
    this.execCommand(cmd)
  }-*/;

  public static final native KeyMap getKeyMap(String name) /*-{
    return $wnd.CodeMirror.keyMap[name];
  }-*/;

  public static final native void addKeyMap(String name, KeyMap km) /*-{
    $wnd.CodeMirror.keyMap[name] = km
  }-*/;

  public final native Vim vim() /*-{
    return this;
  }-*/;

  public final DisplaySide side() {
    return extras().side();
  }

  public final Extras extras() {
    return Extras.get(this);
  }

  protected CodeMirror() {
  }

  public static class Viewport extends JavaScriptObject {
    public final native int from() /*-{ return this.from }-*/;
    public final native int to() /*-{ return this.to }-*/;
    public final boolean contains(int line) {
      return from() <= line && line < to();
    }

    protected Viewport() {
    }
  }

  public static class LineHandle extends JavaScriptObject {
    protected LineHandle(){
    }
  }

  public static class RegisteredHandler extends JavaScriptObject {
    protected RegisteredHandler() {
    }
  }

  public interface EventHandler {
    public void handle(CodeMirror instance, NativeEvent event);
  }

  public interface RenderLineHandler {
    public void handle(CodeMirror instance, LineHandle handle, Element element);
  }

  public interface GutterClickHandler {
    public void handle(CodeMirror instance, int line, String gutter,
        NativeEvent clickEvent);
  }

  public interface BeforeSelectionChangeHandler {
    public void handle(CodeMirror instance, Pos anchor, Pos head);
  }

  public interface ChangesHandler {
    public void handle(CodeMirror instance);
  }
}
