if (typeof $Client == "undefined") var $Client = {
    chains : new Object(), // contains chains of requests

    serviceURL: function(service) {
        return $G.API_BASE + "server/api/s.php?service=" + service;
    },

    joinURL: function() {
        return $G.API_BASE + "server/api/join.php";
    },

    upgradeURL: function() {
        return $G.API_BASE + "server/api/upgrade.php";
    },

    updateCreditCardURL: function() {
        return $G.API_BASE + "server/api/update_billing.php";
    },

    loginURL: function() {
        return $G.API_BASE + "server/api/login.php";
    },

    postData: function(method, params) {
        if (params == "") {
            var params = {
                skey: $Auth.getSessionKey()
            }
        } else {
            params.skey = $Auth.getSessionKey();
        }

        adata = {jsonrpc: "2.0", method: method, params: params, id: Math.floor(Math.random() * 100)};
        jdata = $.toJSON(adata);

        return jdata;
    },

    addChainReq: function(service, method, params, callback, chain_name) {
        if (chain_name == null) {
            chain_name = 'default';
        }

        if ($Client.chains[chain_name] == null) {
            $Client.chains[chain_name] = new Object();
        }

        var req = {
            service: service,
            method: method,
            params: params,
            callback: callback,
            id: Math.floor(Math.random() * 100)
        };
        $Client.chains[chain_name][req.id] = req;
    },

    executeChainReq: function(hidden, chain_name) {
        if ($Client.chains[chain_name] != null) {
            if (!hidden) {
                $Loading.addRequest();
            }

            var reqs = $Client.chains[chain_name];
            
            if ($G.AJAX_CHAIN) {
                var d = {
                    skey: $Auth.getSessionKey(),
                    jsonrpc: '2.0',
                    reqs: new Object(),
                    id: Math.floor(Math.random() * 100)
                }

                for(x in reqs) {
                    d.reqs[x] = new Object();
                    d.reqs[x].service = reqs[x].service,
                    d.reqs[x].method = reqs[x].method,
                    d.reqs[x].params = reqs[x].params,
                    d.reqs[x].id = reqs[x].id
                }
                d.reqs = $.toJSON(d.reqs);

                $.ajax({
                    url: $G.API_BASE + "server/api/chain.php",
                    type: "POST",
                    data: d,
                    success: function(data) {
                        if (!hidden) {
                            $Loading.removeRequest();
                        }

                        data = $Client.decode(data);

                        for(y in data) {
                            if ($Client.chkError(data[y])) {
                                $Client.chains[chain_name][data[y].id].callback(data[y].result);
                            } else {
                                break;
                            }
                        }

                        // reset chain
                        $Client.chains[chain_name] = null;
                    },
                    error: function(data) {
                        $Client.chains[chain_name] = null;

                        if (!hidden) {
                            $Loading.removeRequest();
                        }
                    }
                });
            } else {
                // AJAX_CHAIN disabled: use separate calls
                for(x in reqs) {
                    if (hidden) {
                        $Client.hiddenReq(reqs[x].service, reqs[x].method, reqs[x].params, reqs[x].callback);
                    } else {
                        $Client.req(reqs[x].service, reqs[x].method, reqs[x].params, reqs[x].callback);
                    }
                }
            }
        } else {
            $U.errMsg($Lang.tr("A system exception was thrown."), 'The chain ' + chain_name + ' is undefined.');
        }
    },

    req: function(service, method, params, callback, base_url) {
        /*
		 * always append the sKey to the params object
		 */

        $Loading.addRequest();

        jdata = $Client.postData(method, params);
        service = $Client.serviceURL(service);
        $.ajax({
            url: service,
            type: "POST",
            contentType: "application/json-rpc",
            data: jdata,
            processData: false,
            success: function(data) {
                $Loading.removeRequest();
                if ($Client.chkPost(data)) {
                    data = $Client.decode(data);
                    callback(data.result);
                }
            },
            error: function(data) {
                $Loading.removeRequest();
            }
        });
    },

    /*
 *  Same as req but not showing the Loading Dialog
 */
    hiddenReq: function(service, method, params, callback) {

        jdata = $Client.postData(method, params);
        service = $Client.serviceURL(service);
        $.ajax({
            url: service,
            type: "POST",
            contentType: "application/json-rpc",
            data: jdata,
            processData: false,
            success: function(data) {
                if ($Client.chkPost(data)) {
                    data = $Client.decode(data);
                    callback(data.result);
                }
            },
            error: function(data) { }
        });
    },

    chkPost: function(data) {
        data = $Client.decode(data);

        return $Client.chkError(data);
    },
    chkError: function(data) {
        if (data.error) {
            if (data.error.message=='Unauthorized user' && ($G.FRONTDOOR_UNAUTH_REDIRECT)){
                $U.eraseCookie('sKey');
                if ($U.readCookie('auto_logout') != 1) { 
                    $U.createCookie('auto_logout', 1)
                };
                open($G.FRONTDOOR_UNAUTH_REDIRECT,'_self');
                return false;
            }
            else{
                $U.errMsg($Lang.tr("A system exception was thrown."), data.error.message);
                return false;
            }
        }
        return true;
    },
    decode: function(jdata) {
        jdata = jdata.replace('Array{', '{'); // what's this problem about?
        data = $.evalJSON(jdata);
        return data;
    },
    httpsGo: function(w, force_private, force_public) {
        if (force_private) {
            goto_location = 'https://' + window.location.host + '/page/private#' + w + '?secure';
        } else if (force_public) {
            goto_location = 'https://' + window.location.host + '/page/' + w;
        } else {
            goto_location = 'https://' + window.location.host + window.location.pathname + '#' + w + '?secure';
        }
        window.location = goto_location;
    },
    upload: function(bt, method, data, ftype, callback) {
        if (data) {
            data.method = method;
        } else {
            data = {method: method};
        }
        data.skey = $Auth.getSessionKey();
        
        return new AjaxUpload(bt, {
            // Location of the server-side upload script
            action: "server/api/s.php?service=Uploader",
            // File upload name
            name: 'userfile',
            // Additional data to send
            data: data,
            // Submit file after selection
            autoSubmit: true,
            // The type of data that you're expecting back from the server.
            // HTML (text) and XML are detected automatically.
            // Useful when you are using JSON data as a response, set to "json" in that case.
            // Also set server response type to text/html, otherwise it will not work in IE6
            responseType: false,
            // Fired after the file is selected
            // Useful when autoSubmit is disabled
            // You can return false to cancel upload
            // @param file basename of uploaded file
            // @param extension of that file
            onChange: function(file, ext) {
            },
            // Fired before the file is uploaded
            // You can return false to cancel upload
            // @param file basename of uploaded file
            // @param extension of that file
            onSubmit: function(file, ext) {
                var cancel_upload = false;
                if (ftype == 'image') {
                    if (!(ext && /^(jpg|png|jpeg|gif)$/.test(ext))) {
                        cancel_upload = true;
                    }
                }
                if (ftype == 'video') {
                    //if (!(ext && /^(3gp|avi|wmv|mpg|mpeg|mov|rm|flv|mpe)$/.test(ext))) {
                    if (!(ext && /^flv$/.test(ext))) {
                        cancel_upload = true;
                    }
                }
                if (cancel_upload) {
                    $U.errMsg($Lang.tr("Error: invalid file extension."));
                    return false;
                } else {
                    $U.okMsg($Lang.tr("Uploading ..."));
                }
            },
            // Fired when file upload is completed
            // WARNING! DO NOT USE "FALSE" STRING AS A RESPONSE!
            // @param file basename of uploaded file
            // @param response server response
            onComplete: function(file, response) {
                var r = $Client.decode(response);
                if (r.status) {
                    callback(r.data);
                } else {
                    $U.errMsg($Lang.tr("An error occured"), r.message);
                }
            }
        });
    }
}

