/*
 ajaxUtil.js
 contains AJAX logic implementation
 */

var isResponseValid = true;

function setResponseValid(valid) {
    isResponseValid = valid;
}

function getAJAXHttpRequest() {

    try { // Handle possible errors

        if (window.XMLHttpRequest) {
            // If browser supports Netscape interfaces and native objects, create an instance of
            // native XMLHttpReqest object.
            return new XMLHttpRequest();

        } else if (window.ActiveXObject) {
            // If browser supports Microsoft ActiveX objects. Create an instance of ActiveX XML
            // HTTP request.
            try { // Trying to create ver 2 of ActiveX XML HTTP
                return new ActiveXObject("Msxml2.XMLHTTP");
            } catch(e) { // Failed to create newer version of ActiveX XML HTTP. Try to create
                // odler instance of ActiveX XML HTTP.
                return new ActiveXObject("Microsoft.XMLHTTP");
            }
        }
    } catch(e) {
        alert("Could not instantiate XML HTTP connection.", e);
    }

    return null;
}
;

/**
 * Returns form parameters serialized to query string.
 */
function serializeForm(form) {
    // If nothing to serialize return empty result.
    if (form == null) {
        return "";
    }

    var queryString = "";
    try { // Handle possible errors

        // Reserve empty string for empty result.

        // Serialize form.
        for (var i = 0; i < form.elements.length; i++) { // Iterate through form elements.
            // Form element instance.
            var el = form.elements[i];

            if (el.name != null && el.name != "") {
                // Element tag name.
                var elTagName = el.tagName.toLowerCase();

                if (elTagName == "select") { // Serialize select element.
                    // The select tag is assumed to have extended submit info. Field send is assumed to
                    // indicate whether to send all select items to server, to send none of them or to
                    // work in standard mode. The send parameter in this case should be "all", "none"
                    // and ahy other value respectively.

                    var send = el.getAttribute("send");
                    if (send) {
                        send = send.toLowerCase();
                    }
                    ;

                    if (send != "none") { // Check
                        var all = ( send == "all" );
                        for (var j = 0; j < el.options.length; j++) { // Iterate through select options.
                            var op = el.options[j];
                            if (op.selected || all || el.selectedIndex == j) { // Send if selected or is sending all.
                                queryString += "&" + encodeURIComponent(el.name) + "=" + encodeURIComponent(op.value);
                            }
                        }
                    }

                } else if (elTagName == "textarea") { // Serialize textarea element.
                    queryString += "&" + encodeURIComponent(el.name) + "=" + encodeURIComponent(el.value);


                } else if (elTagName == "input") {  // Serialize input element.
                    // Input element includes various controls. Check control type.
                    var elType = el.type.toLowerCase();

                    if (elType == "checkbox" || elType == "radio") { // Elements that are sent only if selected.
                        if (el.checked) {
                            queryString += "&" + encodeURIComponent(el.name) + "=" + encodeURIComponent(el.value);
                        }

                    } else if (elType != "submit" && elType != "button"/* && elType != "file" */) { // Do not send buttons
                        // and files
                        queryString += "&" + encodeURIComponent(el.name) + "=" + encodeURIComponent(el.value);
                    }
                }
            }
        }
    } catch(e) {
        var message = "Possibly provided DOM element is not a form.\n" +
                      "Tag name of DOM element: " + form.tagName;
        alert(message, e);
    }
    return queryString;
}
;


/**
 * Determines submit URL. If user do not override standard submit location
 * extracts URL from form being submited.
 *
 * @param urlString         user url override
 * @param form              form object being submited
 */
function prepareUrlBase(urlString, form) {

    if (urlString && urlString != "" && urlString != null) {
        return urlString;
    } else if (form && form.action) {
        return form.action;
    } else {
        return null;
    }
}
;


/**
 * Concatenates user provided parameters and form elements into single
 * parameter string.
 *
 * @param params            user defined parameters
 * @param form              form object being submited
 */
function prepareParams(method, params, form) {

    var formElements = serializeForm(form);
    var pars = "method=" + method;
    if (params != null) {
        if (formElements != null) {
            return pars + "&" + params + formElements;
        } else {
            return pars + params;
        }
    } else {
        return pars + formElements;
    }
}
;

/**
 * Forms a single request address from the url string and additional
 * parameters.
 *
 * @param url               url string (may contain parameters)
 * @param params            parameters to be added
 */
function prepareUrl(url, params) {

    if (url.indexOf("?") == -1) {
        return url + "?" + params;
    } else {
        return url + "&" + params;
    }
}
;


/**
 * Send formed request to the server.
 *
 * @param url               url string
 * @param parameters        request params to pass
 * @param target            the element response will be loaded into
 * @param func              javascript code that will be executed after response processing
 */
function sendRequest(url, parameters, target, func) {
    if (url == null) {
        alert("The request could not be completed due to null URL");
        return false;
    }
    // Create local references for connection attributes (needed for reflection emulation).
    var connection = getAJAXHttpRequest();

    // Set method to default if none provided.
    try { // Hande send errors
        document.body.style.cursor = 'wait';
        connection.onreadystatechange = function() {
            proccessResponse(connection, target, func);
        };

        // Open connection.
        connection.open("POST", url, true);
        // Set connection headers.
        connection.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

        // Launch request.
        connection.send(parameters);

    } catch(e) {
        //!!! alert("Error sending the asynchronised request.", e);
        return false;
    }
    return true;
}

/**
 * Proccesses server response and refreshes the needed content.
 *
 * @param req               http request
 * @param reloadZone        the element response will be loaded into
 * @param req               javascript code that will be executed after response processing
 * @return                  nothing
 */
function proccessResponse(req, reloadZone, func)
{
    if (req.readyState == 4 || req.readyState == "complete"){
        if (req.status == 200){
	    window.scrollTo(0,0);

            var respText = req.responseText;
            var target;
            if (reloadZone != null) {
                target = $el(reloadZone);

                if (target!=null){
                    target.innerHTML=respText;
                }else{
                    alert("Can't find target element with id: "+reloadZone+"!");
                }
            }
            /*else{
                target=document.getElementsByTagName("body")[0];
                target.innerHTML=respText;
            }*/

            // running response scripts
            if (target) {
                var scripts = target.getElementsByTagName("script");
                if (scripts != null)
                {
                    var scriptLoader = new getAJAXHttpRequest();
                    for (var i = 0; i < scripts.length; i++)
                    {
                        if (scripts[i].src != null && scripts[i].src != "")
                        {
                            scriptLoader.load(scripts[i].src);
                        }
                        try {
                            eval(scripts[i].innerHTML);
                        }
                        catch(e)
                        {
                            alert("Loaded script evaluation resulted in error for script.\n" + scripts[i].innerHTML, e);
                        }
                    }
                }
            }

            try {
                eval(func);
            }
            catch(e)
            {
                alert("Script evaluation resulted in error for script.\n" + func, e);
            }

        }
        else
        {
            //!!!alert('There was a problem with the request: \n' + req.responseText);
        }
        //Canceling loading notifocations.
        document.body.style.cursor = 'default';
    }
}


/**
 * Sends the data to the server and returnes a XML response.
 *
 * @param url               request URL
 * @param params            submit parameters
 * @param form              submited form
 * @param target            id of html element the response is to be loaded into
 * @param func              js function to be called after response is got
 * @return                  response XML
 */
function doSend(url, method, params, form, target, func) {

    url = prepareUrlBase(url, form);
    params = prepareParams(method, params, form);

    if (!sendRequest(url, params, target, func))
    {
        //!!!alert("request proccessing error occured:\n");
    }

}