/**
 * Partial update namespace.
 */

function PartialUpdateAjaxManager(doQueue) {
    this.doQueue = doQueue;
    this.queueManager = jQuery.manageAjax !== undefined ?
                            jQuery.manageAjax.create('partialUpdateQueue', {}) : null;
    this.ajaxCall = function(settings) {
        if (doQueue && this.queueManager !== null) {
            //queue requests
            this.queueManager.add(settings);
        } else {
            //no queuing will occur manager not accessible
            jQuery.ajax(settings);
        }
    }
}

jQuery.partialUpdateAjaxManager = new PartialUpdateAjaxManager(true);

jQuery.partialUpdate = {

    /**
     * Returns div that contains HTML code of the partialy replaced HTML content.
     */
    _getPartialUpdateReplacementContainer: function(container) {
        /**
         * This is class constant that is appended to dynamically created divs that are used to replace content
         * of the partial updated widgets.
         */
        var partialUpdateContainerClass = "partialUpdateDynamicContainer";

        if (this.length === 0) {
            jQuery.log("Cannot wrap container into the partial update replacement container - no container selected.");
            return null;
        }
        if (this.length > 1) {
            jQuery.log("Cannot wrap container into the partial update replacement container - multiple containers selected.");
            return null;
        }

        var containerParentNode = container.get(0).parentNode;
        var replacementDivAvailable = containerParentNode.className == partialUpdateContainerClass;        
        var replacementDiv = replacementDivAvailable ? containerParentNode : null;
        if(replacementDiv === null || replacementDiv === undefined) {
            replacementDiv = document.createElement("div");
            replacementDiv.className = partialUpdateContainerClass;
            container.wrap(replacementDiv);
            replacementDiv = container.get(0).parentNode;
        }
        return jQuery(replacementDiv);
    },

    /**
     * This method will call server with specified url.
     * Url will be appended with @widgetId so the server side could know whit widget template it should return.
     * Returned HTML will replace current content of element with containerId.
     *
     * @submitId url that points to any of RamJet rendered pages
     * @callback callback function that ought to be called on successful partial form update
     */
    execute: function(url, containerId, callback) {
            //identify widget
            var container = jQuery("#" + containerId);
            if (container.length === 0) {
                jQuery.log("Cannot perform partial update of the container id " + containerId + " is not present.");
                return false;
            }
            //compose final ulr
            var finalUrl;
            var index = url.indexOf("?");
            if(index > -1) {
                finalUrl = url.substr(0, index) + "@" + containerId + url.substr(index);
            } else {
                finalUrl = url + "@" + containerId;
            }
            //init callback function
            var finalCallback;
            if (callback === undefined) {
                finalCallback = function(container, htmlResult) {
                    container.html(htmlResult);
                };
            } else {
                finalCallback = callback;
            }
            //execute post            
            jQuery.partialUpdateAjaxManager.ajaxCall({
                url: finalUrl,
                type: 'POST',
                dataType: 'html',
                success: function(result) {
                    var replacementDiv = jQuery.partialUpdate._getPartialUpdateReplacementContainer(container);
                    finalCallback(replacementDiv, result);
                }                
            });
            return false;
    },

    /**
     * This method will call server with specified url.
     * Url will be appended with @widgetId so the server side could know what widget template it should return.
     * Returned HTML will replace current content of element with containerId.
     *
     * @submitId id of the submit widget
     * @containerId id of the HTML element, whose content should be replaced with AJAX returned content
     *              also id of the widget, whose content is expected to be rendered back
     */
    executeSubmit: function(submitId, containerId, callback) {
                    var jButton = jQuery("#" + submitId);
                    if (jButton.length === 0) {
                        jQuery.log("Cannot perform partial update - submit with id " + submitId + " is not present.");
                        return false;
                    }

                    var jForm = jButton.parents("form");
                    var form = jForm[0];
                    var url = form.action + "@" + containerId;
                    var data = jForm.serializeArray();
                    data[data.length] = {name: jButton[0].name,  value: ""};
                    var container = jQuery("#" + containerId);
                    if (container.length === 0) {
                        jQuery.log("Cannot perform partial update of the container id " + containerId + " is not present.");
                        return false;
                    }
                    //init callback function
                    var finalCallback;
                    if (callback === undefined) {
                        finalCallback = function(container, htmlResult) {
                            container.html(htmlResult);
                        };
                    } else {
                        finalCallback = callback;
                    }
                    //execute post
                    jQuery.partialUpdateAjaxManager.ajaxCall({
                        url: url,
                        data: data,
                        type: 'POST',
                        dataType: 'html',
                        success: function(result) {
                            var replacementDiv = jQuery.partialUpdate._getPartialUpdateReplacementContainer(container);
                            finalCallback(replacementDiv, result);
                        }
                    });
                    return false;
    },

    /**
     * This method will call server with specified url.
     * Url will be appended with @widgetId so the server side could know what widget template it should return.
     * Returned HTML will replace current content of element with containerId.
     *
     * @params url with parameters or parameters alone that should be combined along with form data
     * @submitId id of the submit widget or form itself
     * @containerId id of the HTML element, whose content should be replaced with AJAX returned content
     *              also id of the widget, whose content is expected to be rendered back
     */
    executeCombi: function(params, submitId, containerId, callback) {
                    var jButton = jQuery("#" + submitId);
                    if (jButton.length === 0) {
                        jQuery.log("Cannot perform partial update - submit with id " + submitId + " is not present.");
                        return false;
                    }
                    var jForm = jButton.tagName == "form" ? jButton : jButton.parents("form");
                    var form = jButton.tagName == "form" ? jButton : jForm[0];

                    //local function for this piece of code
                    var replaceValue = function (a, name, value) {
                        for (var i = 0; i < a.length; i++) {
                            if (a[i].name == name) {
                                a[i].value = value;
                                return true;
                            }
                        }
                        return false;
                    };

                    var url = form.action + "@" + containerId;
                    var data = jForm.serializeArray();

                    var paramsIndex = params.indexOf("?");
                    if (paramsIndex > -1) {
                        params = params.substring(paramsIndex + 1);
                    }
                    var paramItems = params.replace("&amp;", "&").split("&");
                    for (var i = 0; i < paramItems.length; i++) {
                    	var paramItem = paramItems[i];
                        var nameValue = paramItem.split("=");
                        var paramName = nameValue[0];
                            var paramValue = nameValue[1] !== undefined ? nameValue[1] : "";
                        if (replaceValue(data, paramName, paramValue)) {
                            continue;
                        }
                            data[data.length] = {name: paramName,  value: paramValue};
                        }

                    var container = jQuery("#" + containerId);
                    if (container.length === 0) {
                        jQuery.log("Cannot perform partial update of the container id " + containerId + " is not present.");
                        return false;
                    }
                    //init callback function
                    var finalCallback;
                    if (callback === undefined) {
                        finalCallback = function(container, htmlResult) {
                            container.html(htmlResult);
                        };
                    } else {
                        finalCallback = callback;
                    }
                    //execute post
                    jQuery.partialUpdateAjaxManager.ajaxCall({
                        url: url,
                        data: data,
                        type: 'POST',
                        dataType: 'html',
                        success: function(result) {
                            var replacementDiv = jQuery.partialUpdate._getPartialUpdateReplacementContainer(container);
                            finalCallback(replacementDiv, result);
                        }
                    });
    }

};
