/* ************************************************************************
   Copyright: 2009 OETIKER+PARTNER AG
   License:   GPLv3 or later
   Authors:   Tobi Oetiker <tobi@oetiker.ch>
   Utf8Check: äöü

************************************************************************ */

/**
 * initialize us an Rpc object with some extra thrills.
 */
qx.Class.define("callbackery.data.Server", {
    extend: qx.io.remote.Rpc,
    type: "singleton",

    construct: function () {
        this.base( arguments );
        this.set( {
            timeout: 180000,
            url: 'QX-JSON-RPC/',
            serviceName: 'default',
            protocol: 'qx1'
        });
    },

    properties: {
        sessionCookie: {
            init: null,
            nullable: true
        }
    },
    members: {
        /**
         * A asyncCall handler which tries to
         * login in the case of a permission exception.
         *
         * @param handler {Function} the callback function.
         * @param methodName {String} the name of the method to call.
         * @return {var} the method call reference.
         */
        callAsync: function(handler, methodName) {
            if (methodName == 'login'){
                // arguments.callee.base.apply(this, arguments);
                arguments.callee.base.apply(this, arguments);
                return;
            }
            var origArguments = arguments;
            var origThis = this;
            var localeMgr = qx.locale.Manager.getInstance();
            var newArgs = Array.prototype.slice.call(arguments);
            newArgs[0] = function(ret, exc, id) {
                if (exc) {
                    switch (exc.code) {
                        case 6:
                            let login = callbackery.ui.Login.getInstance();
                            login.addListenerOnce('login', (e) => {
                                let ret = e.getData();
                                origThis.setSessionCookie(ret.sessionCookie);
                                origArguments.callee.base.apply(origThis, origArguments);
                            });
                            login.open();
                            return;
                        case 7:
                            if (window.console){
                                window.console.log("Session Expired. Reloading page");
                            }
                            callbackery.ui.Busy.getInstance().vanish();
                            let mb = callbackery.ui.MsgBox.getInstance()
                            mb.addListenerOnce('choice',(e) => {
                                if (e.getData() == 'ok'){
                                     window.location.reload(true);
                                }
                            });
                            mb.info(
                                mb.tr('Session Expired'),
                                mb.xtr(exc.message)
                            );
                            return;
                    }
                }
                try {
                  handler(ret, exc, id);
                }
                catch(e) {
                    if (window.console){
                        window.console.error("Error while running CallAsync Handler","ret:",ret,"exc",exc,"id",id,"e",e);
                    }
                }
            };
            newArgs.push({
                qxLocale: localeMgr.getLocale()
            });
            arguments.callee.base.apply(this, newArgs);
        },
        /**
         * A variant of the asyncCall method which pops up error messages
         * generated by the server automatically.
         *
         * Note that the handler method only gets a return value never an exception
         * It just does not get called when there is an exception.
         *
         * @param handler {Function} the callback function.
         * @param methodName {String} the name of the method to call.
         * @return {var} the method call reference.
         */
        callAsyncSmart: function(handler, methodName) {
            var origHandler = handler;

            var superHandler = function(ret, exc, id) {
                if (exc) {
                    callbackery.ui.MsgBox.getInstance().exc(exc);
                } else {
                    origHandler(ret);
                }
            };
            var newArgs = Array.prototype.slice.call(arguments);
            newArgs[0] = superHandler;
            this.callAsync.apply(this, newArgs);
        },
        callAsyncSmartBusy: function(handler, methodName) {
            var origHandler = handler;
            var busy = callbackery.ui.Busy.getInstance();
            var superHandler = function(ret, exc, id) {
                busy.vanish();
                if (exc) {
                    callbackery.ui.MsgBox.getInstance().exc(exc);
                } else {
                    origHandler(ret);
                }
            };
            var newArgs = Array.prototype.slice.call(arguments);
            newArgs[0] = superHandler;
            busy.manifest('Running ' + methodName);
            this.callAsync.apply(this, newArgs);
        },
        /**
         * override the request creation, to add our 'cookie' header
         */
        createRequest: function() {
            var req = this.base(arguments);
            var cookie = this.getSessionCookie();
            if (cookie) {
                req.setRequestHeader('X-Session-Cookie', this.getSessionCookie());
            }
            return req;
        }
    }
});
