﻿Jspb = {};

Jspb.invokeNoReturn = function(methodInfo) {
    methodInfo = Jspb.Helper.parseMethodInfo(methodInfo);
    if (!methodInfo) return false;
    Jspb.invoke(methodInfo, null);
    return true;
};
Jspb.invoke = function(methodInfo, callback, args) {
    methodInfo = Jspb.Helper.parseMethodInfo(methodInfo);
    if (!methodInfo) return;
    var invoker = Jspb._createInvoker(callback, args);
    Jspb._invoke(invoker, methodInfo);
    return invoker;
};
Jspb._invoke = function(invoker, methodInfo) { invoker.invoke(methodInfo); };
Jspb._createInvoker = function(callback, sender) { return new Jspb.Invoker(callback, sender); };
Jspb.createHttpObject = function() { var xmlhttp = false; try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (ex1) { try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (ex2) { xmlhttp = false; } } if (!xmlhttp && typeof XMLHttpRequest != 'undefined') xmlhttp = new XMLHttpRequest(); return xmlhttp; };

Jspb.onerror = function(e) {
    alert("Error: " + e);
};

Jspb.Helper = {};

Jspb.Helper.parseBool = function(value) {
    if (value == null) return false;
    return value.toString() == "true";
};

Jspb.Helper.parseMethodInfo = function(mi) {

    if (typeof mi == "string")
        return new Jspb.MethodInfo(mi, null, null);

    if (!mi.methodName) {
        alert("Method info is not valid");
        return null;
    }

    if (!mi.assemblyName) mi.assemblyName = "";
    if (!mi.className) mi.className = "";

    var ret = new Jspb.MethodInfo(mi.methodName, mi.className, mi.assemblyName);

    if (!mi.args)
        return ret;

    if (!mi.args.push || !mi.args.pop) {
        alert("Argument list is invalid");
        return null;
    }

    for (var i = 0; i < mi.args.length; i++) {
        var o = mi.args[i];
        if (typeof o == "object")
            ret.addArgument(o.data, o.type || null, o.assembly || null);
        else
            ret.addArgument(o);
    }

    return ret;
};

Jspb.Invoker = function(callback, sender) {
    this.callback = callback;
    this.xmlhttp = Jspb.createHttpObject();
    this.timer = null;
    this.sender = sender;
    this.cancel = false;
};

Jspb.Invoker.prototype.invoke = function(methodInfo) {
    var Jspb = methodInfo.serialize();
    this.async = true;
    if (this.async) {
        this._invokeAsyncServerMethod(Jspb);
    }
    else {
        this._invokeServerMethod(Jspb);
        this._invokeCallback();
    }
};

Jspb.Invoker.prototype._invokeCallback = function() {
    if (this.cancel) return;
    var ret = this.xmlhttp.responseText;
    var retObject;

    try {
        retObject = eval("(" + ret + ")");
    }
    catch (e) {
        alert(ret);
        return;
    }

    if (retObject.success) {
        if (this.callback)
            this.callback(retObject.response, this.sender);
    }
    else {
        if (Jspb.onerror)
            Jspb.onerror(retObject.response, this.sender);
    }
};

Jspb.Invoker.prototype._invokeServerMethod = function(methodInfoXml) {

    this.xmlhttp.open("POST", Jspb.defaultInvokeUrl, false);
    this.xmlhttp.send(methodInfoXml);
};

Jspb.Invoker.prototype._invokeAsyncServerMethod = function(methodInfoXml) {
    this.xmlhttp.open("POST", Jspb.defaultInvokeUrl, true);
    this.xmlhttp.send(methodInfoXml);
    var realThis = this;
    this.timer = window.setInterval(function() {
        realThis.checkState();
    }, 100);
};

Jspb.Invoker.prototype.checkState = function(index) {
    if (this.xmlhttp.readyState == 4) {
        window.clearInterval(this.timer);
        this._invokeCallback();
    }
};
Jspb.MethodInfo = function(methodName, className, assemblyName) {
    this.methodName = methodName;
    this.assemblyName = assemblyName == null ? "" : assemblyName;
    this.className = className == null ? "" : className;
    this.args = [];
};

Jspb.MethodInfo.prototype.addArgument = function(data, type, assembly) {
    this.args[this.args.length] = new Jspb.MethodArgument(data, type, assembly);
};

Jspb.MethodInfo.prototype.serialize = function() {
    var retXml = "";
    retXml += "<Jspb_invoke>";
    retXml += "<method>" + this.methodName + "</method>";
    retXml += "<class>" + this.className + "</class>";
    retXml += "<assembly>" + this.assemblyName + "</assembly>";
    retXml += "<args>";
    for (var i = 0; i < this.args.length; i++)
        retXml += "<arg type=\"" + this.args[i].type + "\" assembly=\"" + this.args[i].assembly + "\"><![CDATA[" + this.args[i].data + "]]></arg>";
    retXml += "</args>";
    retXml += "</Jspb_invoke>";
    return retXml;
};

Jspb.MethodArgument = function(data, type, assembly) {
    this.data = data;
    if (type == null)
        type = typeof data;
    this.type = type;
    this.assembly = assembly ? assembly : "";
};
