/**
 * AjaxHandler.class.js file
 *
 * @author Aaron <aaron@doc-net.com>
 * @copyright Doctor Net Ltd &copy; 2008
 * @package SprintToolv3.default
 */
/**
 * AjaxHandler class
 *
 * Processes AJAX requests using jQuery
 *
 * @static
 */
function AjaxHandler() {}
AjaxHandler.str_url = '';
AjaxHandler.arr_data = new Array();
AjaxHandler.str_custom_xml = false;
AjaxHandler.bol_busy = false;
AjaxHandler.bol_async = false;

/**
 * Reset
 */
AjaxHandler.reset = function(str_url) {
   AjaxHandler.str_url = '';
   if(str_url) {
      AjaxHandler.str_url = str_url;
   }
   AjaxHandler.arr_data = new Array();
   AjaxHandler.str_custom_xml = false;
   AjaxHandler.bol_async = false;
};
/**
 * Set the URL
 *
 * @param String str_url
 */
AjaxHandler.set_url = function(str_url) {
   AjaxHandler.str_url = str_url;
};

/**
 * Add some data
 *
 * @param String str_field Field name
 * @param Mix mix_val Field value
 */
AjaxHandler.add_data = function(str_field, mix_val) {
   AjaxHandler.arr_data[str_field] = mix_val;
};

/**
 * Set the custom XML
 *
 * To be used instead of add_data to specify
 * bespoke XML
 */
AjaxHandler.set_custom_xml = function(str_xml) {
   AjaxHandler.str_custom_xml = str_xml;
};

/**
 * Build up the XML document to send over AJAX
 *
 * @return String
 */
AjaxHandler.build_xml = function() {
   // Allow use of custom XML if set
   if (AjaxHandler.str_custom_xml) {
      return AjaxHandler.str_custom_xml;
   }
   var str_xml = '<'+'?xml version="1.0"?><root><fields>';
   for (str_field in AjaxHandler.arr_data) {
      // This will try to include the functions attached to AjaxHandler.arr_data
      if ((typeof AjaxHandler.arr_data[str_field]) != 'function') {
         str_xml += '<'+str_field+'><![CDATA['+AjaxHandler.arr_data[str_field]+']]></'+str_field+'>';
      }
   }
   str_xml += '</fields></root>';
   return str_xml;
}

/**
 * Set up a "busy" icon before dispatching the AjaxRequest
 *
 * Refer to do_dispatch() for parameters
 */
AjaxHandler.dispatch = function(fnc_success, fnc_failure) {
   $('#busy-wait-icon').show();
   if (AjaxHandler.bol_busy) {
      var int_timeout = 1000;
   } else {
      var int_timeout = 1;
   }
   setTimeout(function() {AjaxHandler.do_dispatch(fnc_success, fnc_failure)}, int_timeout);
}

/**
 * Perform the AJAX request
 *
 * Pass in the response object from the ajax call as a parameter to the callback(s).
 *
 * @param Function fnc_success (Optional) Function to be called on success
 * @param Function fnc_failure (Optional) Function to be called on failure
 */
AjaxHandler.do_dispatch = function(fnc_success, fnc_failure) {
   AjaxHandler.bol_busy = true;
   $.ajax({
      async: AjaxHandler.bol_async,
      type: "POST",
      url: AjaxHandler.str_url,
      data: 'str_xml='+escape(AjaxHandler.build_xml()),
      // If the AJAX call completed successfully
      success: function(obj_response) {
         AjaxHandler.bol_busy = false;
         // if the server-side script returned success
         if($('response', obj_response).attr('success') == 'true') {
             // If we've passed in an anonymous function into do_dispatch(), call it,
             // passing in the response object as a parameter.
            if (fnc_success) {
               fnc_success(obj_response);
            }
         } else if($('response', obj_response).attr('success') == 'logged_out') {
            // user has been logged out, so tell them this is the case, wait for them to hit OK and then forward to the login screen
            AjaxHandler.ajax_failure('You have been logged out, possibly due to a period of inactivity.  Please click OK to be forwarded to the login screen.');
            window.location = '/auth/login';
         // server-side didn't return success
         } else {
            // If we've passed in an anonymous function into do_dispatch(), call it,
            // passing in the response object as a parameter.
            if (fnc_failure) {
               fnc_failure(obj_response);
            } else {
               AjaxHandler.ajax_failure($('message', obj_response).text());
            }
         }
         $('#busy-wait-icon').hide();
      },
      // AJAX call didn't complete successfully
      error: function(obj_xmlhttp, str_error) {
         AjaxHandler.bol_busy = false;
         $('#busy-wait-icon').hide();
         // If the request was interrupted by page navigation there will be no response
         if (obj_xmlhttp.responseText) {
            AjaxHandler.ajax_failure('Sorry, there was a problem\n\n(Error code: AJAX-002)');
         }
      }
   });


};

/**
 * Alert user that the AJAX request failed
 *
 * @param String str_msg (Optional) Error message to display
 */
AjaxHandler.ajax_failure = function(str_msg) {
   if (!str_msg) {
      str_msg = 'Sorry, there was a problem';
   }
   alert(str_msg);
};

/**
 * Process the fields of a form ready for AJAX submission
 *
 * @param DOMElement|jQuery The form to process
 */
AjaxHandler.process_form = function(obj_form) {
   // Determine the parameter type
   if (obj_form instanceof jQuery) {
      obj_form = obj_form.get(0);
   }
   // Set the URL if appropriate
   if ($(obj_form).attr('action') && !AjaxHandler.str_url) {
      AjaxHandler.set_url($(obj_form).attr('action'));
   }
   // Process the form's data
   var arr_data = $(obj_form).formToArray();
   for (int_count in arr_data) {
      if (typeof(arr_data[int_count]) != 'function') {
         AjaxHandler.add_data(arr_data[int_count]['name'], arr_data[int_count]['value']);
      }
   }
};

/**
 * The following code is taken directly from the jQuery form plugin from http://malsup.com/jquery/form/
 */

/**
 * jQuery Form Plugin
 * version: 2.25 (08-APR-2009)
 * @requires jQuery v1.2.2 or later
 *
 * Examples and documentation at: http://malsup.com/jquery/form/
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * formToArray() gathers form element data into an array of objects that can
 * be passed to any of the following ajax functions: $.get, $.post, or load.
 * Each object in the array has both a 'name' and 'value' property.  An example of
 * an array for a simple login form might be:
 *
 * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
 *
 * It is this array that is passed to pre-submit callback functions provided to the
 * ajaxSubmit() and ajaxForm() methods.
 */

$.fn.formToArray = function(semantic) {
    var a = [];
    if (this.length == 0) return a;

    var form = this[0];
    var els = semantic ? form.getElementsByTagName('*') : form.elements;
    if (!els) return a;
    for(var i=0, max=els.length; i < max; i++) {
        var el = els[i];
        var n = el.name;
        if (!n) continue;

        if (semantic && form.clk && el.type == "image") {
            // handle image inputs on the fly when semantic == true
            if(!el.disabled && form.clk == el)
                a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
            continue;
        }

        var v = $.fieldValue(el, true);
        if (v && v.constructor == Array) {
            for(var j=0, jmax=v.length; j < jmax; j++)
                a.push({name: n, value: v[j]});
        }
        else if (v !== null && typeof v != 'undefined')
            a.push({name: n, value: v});
    }

    if (!semantic && form.clk) {
        // input type=='image' are not found in elements array! handle them here
        var inputs = form.getElementsByTagName("input");
        for(var i=0, max=inputs.length; i < max; i++) {
            var input = inputs[i];
            var n = input.name;
            if(n && !input.disabled && input.type == "image" && form.clk == input)
                a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
        }
    }
    return a;
};
/**
 * Returns the value of the field element.
 */
$.fieldValue = function(el, successful) {
    var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
    if (typeof successful == 'undefined') successful = true;

    if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
        (t == 'checkbox' || t == 'radio') && !el.checked ||
        (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
        tag == 'select' && el.selectedIndex == -1))
            return null;

    if (tag == 'select') {
        var index = el.selectedIndex;
        if (index < 0) return null;
        var a = [], ops = el.options;
        var one = (t == 'select-one');
        var max = (one ? index+1 : ops.length);
        for(var i=(one ? index : 0); i < max; i++) {
            var op = ops[i];
            if (op.selected) {
				var v = op.value;
				if (!v) // extra pain for IE...
                	v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
                if (one) return v;
                a.push(v);
            }
        }
        return a;
    }
    return el.value;
};