// 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.api;

import com.google.gerrit.client.actions.ActionButton;
import com.google.gerrit.client.info.ActionInfo;
import com.google.gerrit.client.info.ChangeInfo;
import com.google.gerrit.client.info.ChangeInfo.EditInfo;
import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
import com.google.gerrit.client.projects.BranchInfo;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.rpc.NativeString;
import com.google.gerrit.client.rpc.RestApi;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gwt.core.client.JavaScriptObject;

public class ActionContext extends JavaScriptObject {
  static final native void init() /*-{
    var Gerrit = $wnd.Gerrit;
    var doc = $wnd.document;
    var stopPropagation = function (e) {
      if (e && e.stopPropagation) e.stopPropagation();
      else $wnd.event.cancelBubble = true;
    };

    Gerrit.ActionContext = function(u){this._u=u};
    Gerrit.ActionContext.prototype = {
      go: Gerrit.go,
      refresh: Gerrit.refresh,
      refreshMenuBar: Gerrit.refreshMenuBar,
      isSignedIn: Gerrit.isSignedIn,
      showError: Gerrit.showError,

      br: function(){return doc.createElement('br')},
      hr: function(){return doc.createElement('hr')},
      button: function(label, o) {
        var e = doc.createElement('button');
        e.appendChild(this.div(doc.createTextNode(label)));
        if (o && o.onclick) e.onclick = o.onclick;
        return e;
      },
      checkbox: function() {
        var e = doc.createElement('input');
        e.type = 'checkbox';
        return e;
      },
      div: function() {
        var e = doc.createElement('div');
        for (var i = 0; i < arguments.length; i++)
          e.appendChild(arguments[i]);
        return e;
      },
      label: function(c,label) {
        var e = doc.createElement('label');
        e.appendChild(c);
        e.appendChild(doc.createTextNode(label));
        return e;
      },
      prependLabel: function(label,c) {
        var e = doc.createElement('label');
        e.appendChild(doc.createTextNode(label));
        e.appendChild(c);
        return e;
      },
      span: function() {
        var e = doc.createElement('span');
        for (var i = 0; i < arguments.length; i++)
          e.appendChild(arguments[i]);
        return e;
      },
      msg: function(label) {
        var e = doc.createElement('span');
        e.appendChild(doc.createTextNode(label));
        return e;
      },
      textarea: function(o) {
        var e = doc.createElement('textarea');
        e.onkeypress = stopPropagation;
        if (o && o.rows) e.rows = o.rows;
        if (o && o.cols) e.cols = o.cols;
        return e;
      },
      textfield: function() {
        var e = doc.createElement('input');
        e.type = 'text';
        e.onkeypress = stopPropagation;
        return e;
      },
      select: function(a,s) {
        var e = doc.createElement('select');
        for (var i = 0; i < a.length; i++) {
          var o = doc.createElement('option');
          if (i==s) {
            o.setAttributeNode(doc.createAttribute("selected"));
          }
          o.appendChild(doc.createTextNode(a[i]));
          e.appendChild(o);
        }
        return e;
      },
      selected: function(e) {
        return e.options[e.selectedIndex].text;
      },

      popup: function(e){
        this._p=@com.google.gerrit.client.api.PopupHelper::popup(
          Lcom/google/gerrit/client/api/ActionContext;Lcom/google/gwt/dom/client/Element;)(this,e)},
      hide: function() {
        this._p.@com.google.gerrit.client.api.PopupHelper::hide()();
        delete this['_p'];
      },

      call: function(i,b) {
        var m = this.action.method.toLowerCase();
        if (m == 'get' || m == 'delete' || i==null) this[m](b);
        else this[m](i,b);
      },
      get: function(b){@com.google.gerrit.client.api.ActionContext::get(
        Lcom/google/gerrit/client/rpc/RestApi;Lcom/google/gwt/core/client/JavaScriptObject;)(this._u,b)},
      post: function(i,b){@com.google.gerrit.client.api.ActionContext::post(
        Lcom/google/gerrit/client/rpc/RestApi;Lcom/google/gwt/core/client/JavaScriptObject;Lcom/google/gwt/core/client/JavaScriptObject;)(
        this._u,i,b)},
      put: function(i,b){@com.google.gerrit.client.api.ActionContext::put(
        Lcom/google/gerrit/client/rpc/RestApi;Lcom/google/gwt/core/client/JavaScriptObject;Lcom/google/gwt/core/client/JavaScriptObject;)(
        this._u,i,b)},
      'delete': function(b){@com.google.gerrit.client.api.ActionContext::delete(
        Lcom/google/gerrit/client/rpc/RestApi;Lcom/google/gwt/core/client/JavaScriptObject;)(this._u,b)},
      del: function(b){@com.google.gerrit.client.api.ActionContext::delete(
        Lcom/google/gerrit/client/rpc/RestApi;Lcom/google/gwt/core/client/JavaScriptObject;)(this._u,b)},
    };
  }-*/;

  static final native ActionContext create(RestApi f) /*-{
    return new $wnd.Gerrit.ActionContext(f);
  }-*/;

  final native void set(ActionInfo a) /*-{ this.action=a; }-*/;

  final native void set(ChangeInfo c) /*-{ this.change=c; }-*/;

  final native void set(EditInfo e) /*-{ this.edit=e; }-*/;

  final native void set(Project.NameKey p) /*-{ this.project=p; }-*/;

  final native void set(BranchInfo b) /*-{ this.branch=b }-*/;

  final native void set(RevisionInfo r) /*-{ this.revision=r; }-*/;

  final native void button(ActionButton b) /*-{ this._b=b; }-*/;

  final native ActionButton button() /*-{ return this._b; }-*/;

  public final native boolean has_popup() /*-{ return this.hasOwnProperty('_p') }-*/;

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

  protected ActionContext() {}

  static final void get(RestApi api, JavaScriptObject cb) {
    api.get(wrap(cb));
  }

  /**
   * The same as {@link #get(RestApi, JavaScriptObject)} but without converting a {@link
   * NativeString} result to String.
   */
  static final void getRaw(RestApi api, final JavaScriptObject cb) {
    api.get(wrapRaw(cb));
  }

  static final void post(RestApi api, JavaScriptObject in, JavaScriptObject cb) {
    if (NativeString.is(in)) {
      post(api, ((NativeString) in).asString(), cb);
    } else {
      api.post(in, wrap(cb));
    }
  }

  /**
   * The same as {@link #post(RestApi, JavaScriptObject, JavaScriptObject)} but without converting a
   * {@link NativeString} result to String.
   */
  static final void postRaw(RestApi api, JavaScriptObject in, JavaScriptObject cb) {
    if (NativeString.is(in)) {
      postRaw(api, ((NativeString) in).asString(), cb);
    } else {
      api.post(in, wrapRaw(cb));
    }
  }

  static final void post(RestApi api, String in, JavaScriptObject cb) {
    api.post(in, wrap(cb));
  }

  /**
   * The same as {@link #post(RestApi, String, JavaScriptObject)} but without converting a {@link
   * NativeString} result to String.
   */
  static final void postRaw(RestApi api, String in, JavaScriptObject cb) {
    api.post(in, wrapRaw(cb));
  }

  static final void put(RestApi api, JavaScriptObject cb) {
    api.put(wrap(cb));
  }

  /**
   * The same as {@link #put(RestApi, JavaScriptObject)} but without converting a {@link
   * NativeString} result to String.
   */
  static final void putRaw(RestApi api, JavaScriptObject cb) {
    api.put(wrapRaw(cb));
  }

  static final void put(RestApi api, JavaScriptObject in, JavaScriptObject cb) {
    if (NativeString.is(in)) {
      put(api, ((NativeString) in).asString(), cb);
    } else {
      api.put(in, wrap(cb));
    }
  }

  /**
   * The same as {@link #put(RestApi, JavaScriptObject, JavaScriptObject)} but without converting a
   * {@link NativeString} result to String.
   */
  static final void putRaw(RestApi api, JavaScriptObject in, JavaScriptObject cb) {
    if (NativeString.is(in)) {
      putRaw(api, ((NativeString) in).asString(), cb);
    } else {
      api.put(in, wrapRaw(cb));
    }
  }

  static final void put(RestApi api, String in, JavaScriptObject cb) {
    api.put(in, wrap(cb));
  }

  /**
   * The same as {@link #put(RestApi, String, JavaScriptObject)} but without converting a {@link
   * NativeString} result to String.
   */
  static final void putRaw(RestApi api, String in, JavaScriptObject cb) {
    api.put(in, wrapRaw(cb));
  }

  static final void delete(RestApi api, JavaScriptObject cb) {
    api.delete(wrap(cb));
  }

  /**
   * The same as {@link #delete(RestApi, JavaScriptObject)} but without converting a {@link
   * NativeString} result to String.
   */
  static final void deleteRaw(RestApi api, JavaScriptObject cb) {
    api.delete(wrapRaw(cb));
  }

  private static GerritCallback<JavaScriptObject> wrap(final JavaScriptObject cb) {
    return new GerritCallback<JavaScriptObject>() {
      @Override
      public void onSuccess(JavaScriptObject result) {
        if (NativeString.is(result)) {
          NativeString s = result.cast();
          ApiGlue.invoke(cb, s.asString());
        } else {
          ApiGlue.invoke(cb, result);
        }
      }
    };
  }

  private static GerritCallback<JavaScriptObject> wrapRaw(final JavaScriptObject cb) {
    return new GerritCallback<JavaScriptObject>() {
      @Override
      public void onSuccess(JavaScriptObject result) {
        ApiGlue.invoke(cb, result);
      }
    };
  }
}
