var RPCRequest = Class.create();

// content:save, page:id, version:id, content:id, value, name, description, styleid, typeid
Object.extend(RPCRequest.prototype, {
    timer: null,
    request: null,
    otherOptions: null,
    initialize: function (options, otherOptions) {
        var parAr = [];
        var parameters;
        
        // Compile options into a url encoded string
        if (options.parameters instanceof Object)
        {
            for (var item in options.parameters) {
                if (options.parameters[item] && options.parameters[item].indexOf && options.parameters[item].indexOf('[]') >= 0)
                    parAr.push(options.parameters[item])
                else        
                    parAr.push(item + '=' + encodeURIComponent(options.parameters[item]));
            }; 
            parameters = parAr.join('&');
        }
        else
        {
            parameters = options.parameters;
        }
        
        this.options = {
            method: 'post',
            postBody: parameters,
            onSuccess: function (a, b) { 
                // Stop the timeout timer
                if (this.timer)
                    clearTimeout(this.timer);
                options.onSuccess(a, b);
            }.bind(this),
            onFailure: function (a, b) { 
                // Stop the timeout timer
                if (this.timer)
                    clearTimeout(this.timer);

                if (options.onFailure)
                    options.onFailure(a, b);
            }.bind(this)
        };

        this.otherOptions = otherOptions;
        
        // Set up timeout timer
        // this.timer = setTimeout(this.timeout.bind(this), 5000);
        var href = document.location.href;
        if (otherOptions && otherOptions.href)
            href = otherOptions.href;

        // debug: display the content of the RPC call      
        debug('RPC: ' + href + ', Post Body :\n' + this.options.postBody);

        this.request = new Ajax.Request(href, this.options);
    },
    timeout: function () {
        if (this.otherOptions && 
            this.otherOptions.original &&
            this.otherOptions.original.addError)
                this.otherOptions.original.addError('Save Failed. Timeout.');

        //this.request.abort();
        this.request = null;
        this.options.onFailure();
    }
});

/* -----------------------  RPC  ------------------------- */

var odoRPC = {
    requests: [],
    sendUserCaps: function () {
		if (getCookie('today') == 'done')
			return;

        var browserCategory =
            (Prototype.Browser.IE ? 'IE' : '')
            + (Prototype.Browser.Opera ? 'Opera' : '')
            + (Prototype.Browser.WebKit ? 'WebKit' : '')
            + (Prototype.Browser.Gecko ? 'Gecko' : '');
        
        var postVars = {
            browser_category: browserCategory,
            screen_width: screen.width,
            screen_height: screen.height,
            browser_width: window.innerWidth || document.body.offsetWidth,
            browser_height: window.innerHeight || document.body.offsetHeight,

            // action
            'ping':'ping'
        };
        
        var options = {
            parameters: postVars
        };
        this.requests.push(new RPCRequest(options, {href: '/backend/ping/'}));
    },
    saveBlock: function (opt) {
        var postVars = {
            content_id: retrieveIdNumber(opt.contentId),
            content_value: opt.value,
            content_alpha: opt.alpha == null ? '' : opt.alpha,
            content_beta: opt.beta == null ? '' : opt.beta,
            content_gamma: opt.gamma == null ? '' : opt.gamma,
//            content_style: opt.style == null ? '' : opt.style,
            page_id: storage.page.pageId,
            page_version_id: storage.page.versionId,
        
            // action
            'content:update':'Save'
        };
        Object.extend(postVars, opt.properties || {});
        
        var options = {
            onSuccess: function (response) {
                this.handleIdChanges(response);
                if (opt.onSuccess)
                    opt.onSuccess(response);
            }.bind(this),
            onFailure: function (a, b) {
                if (opt.onFailure)
                    opt.onFailure(a, b)
            },
            parameters: postVars
        };
        
        this.requests.push(new RPCRequest(options, opt.otherOptions));
    },
    deleteBlock: function (opt) {
        var postVars = {
            content_id: retrieveIdNumber(opt.contentId),
            page_id: storage.page.pageId,
            page_version_id: storage.page.versionId,
            parent_id: retrieveIdNumber(opt.parentId),

            // action
            'content:delete':'content:delete'
        };
        Object.extend(postVars, opt.properties || {});
        
        var options = {
            onSuccess: function (response) {
                this.handleIdChanges(response);
                if (opt.onSuccess)
                    opt.onSuccess(response);
            }.bind(this),
            onFailure: function (a, b) {
                if (opt.onFailure)
                    opt.onFailure(a, b);
            },
            parameters: postVars
        };
        
        this.requests.push(new RPCRequest(options, opt.otherOptions));
    },
    newContent: function (opt) {
        if (!opt.contentId)
        {
            assert('ASSERT FAILED @ odoRPC::newContent: opt.contentId not set (contentlist\'s id)');
            return null;
        }
        
        var postVars = {
            page_id: storage.page.pageId,
            page_version_id: storage.page.versionId,
            content_id: retrieveIdNumber(opt.contentId),
            type_id: opt.type,
            
            // action
            'content:new':'content:new'
        };
        
        if (opt.pendingNode)
            postVars.pending_node = opt.pendingNode;
        
        var options = {
            onSuccess: function (response) {
                this.handleIdChanges(response);
                if (opt.onSuccess)
                    opt.onSuccess(response, true);
            }.bind(this),
            onFailure: function (a, b) {
                if (opt.onFailure)
                    opt.onFailure(a, b);
            },
            parameters: postVars
        };

        this.requests.push(new RPCRequest(options, opt.otherOptions));
    },
    reorderContent: function (opt) {
        if (!opt.contentId)
        {
            assert('ASSERT FAILED @ odoRPC::reorderContent: opt.contentId not set');
            return null;
        }

        var postVars = {
            page_id: storage.page.pageId,
            page_version_id: storage.page.versionId,
            content_id: retrieveIdNumber(opt.contentId),
            child_content_id: retrieveIdNumber(opt.childContentId),
            
            // action
            'content:order':'content:order'
        };

        var parAr = [];
        // We already have a string with the parameters in so we need to build the
        // query string ourselves and pass it as a string rather than an array
        for (var item in postVars) {
            if (postVars[item] && postVars[item].indexOf && postVars[item].indexOf('[]') >= 0)
                parAr.push(postVars[item])
            else        
                parAr.push(item + '=' + postVars[item]);
        };
        parameters = parAr.join('&');

        // Add in the content string from Serialize
        parameters += '&' + opt.serialized;

        var options = {
            onSuccess: function (response) {
                debug(response.responseText);
                this.handleIdChanges(response);
            }.bind(this),
            parameters: parameters
        };
        
        this.requests.push(new RPCRequest(options, opt.otherOptions));
    },
    handleIdChanges: function (responseObj) {
        try {
            debug('odoRPC::handleIdChanges:\n' + responseObj.responseText);

        if (!responseObj.responseXML)
        {
            assert('ASSERT FAILED @ odoRPC::handleIdChanges: Response was not XML.');
            return null;
        }

        var responseXML = responseObj.responseXML;
        // DEBUG: Show full responseText

        var idChanges = responseXML.getElementsByTagName('changeid');
        $A(idChanges).each(function (change) {
            var oldId = change.getAttribute('old');
            var newId = change.getAttribute('new');
            var oldNode = storage.items['content-' + oldId];
            debug(oldId + ' - to - ' + newId);
            
            // It must already be gone or we don't have this node
            if (!oldNode)
                return;

            // Call the object to handle its own change
            // Also bind the method to its owner so that it may use 'this'
            oldNode.obj.changeId.bind(oldNode.obj)(newId);
        });
        } catch (e) {
            debug('ER1: ' + e, 3);
        }
    }
};

/* -------------------------------------------------------- */

