/**
 * This is testing my response objects
 */
remoteActionHandler = {
        
/******************************************************************************
 * XHR Communication Handlers
 *****************************************************************************/

    /**
     * POST data to our actions and hand and DMRActions to our DMRAction method
     * Show error box if there were any problems
     * 
     * @param    string    URL to our action
     * @param    object    Hash of all Key/Value pairs to be sent to action
     */
    submitData: function (url,params,form) {
        var self=this;
        $.ajax({
            type: "POST",
            url: url,
            data: params,
            dataType: 'json',
            success: function(json, textStatus){
            
                /**
                 * TODO Add error checking to make sure we got a valid JSON OBJECT
                 *      type response.  If we don't get one put up the error 
                 *      box.  Also check for an error object and if it has a 
                 *      flag to show error message in error box then post it 
                 *      in there and show it.
                 */
                
                // Check for redline_error
                if (json.redline_error instanceof Object) {
                    self.redlineErrorHandler(json.redline_error);
                } else {
                
                    // Validate that a result object was returned
                    if (!json.result instanceof Object) {
                        console.error('INVALID JSON RESPONSE', json);
                    } else {
                        
                        if (json.result.DMRActions instanceof Object) { 
                            // Run DMRActions if they are present                
                            self.runDMRA(self,json.result.DMRActions);                    
                        }
                        if (json.result.message instanceof Object) { 
                            // Display Message                
                            self.messageBox(json.result.message);                    
                        }
                        
                    }
                    
                    // Unlock element from sending data if 'unlockElement' set to true
                    if (json.result.unlockElement == true) {
                        self.unlockElement(form);    
                    }
                    
                    // Bind All Forms (including new ones that might have been added to the page)
                    self.bindForms();
                }

            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                console.error('WE NEED TO REPLACE THIS WITH PROPPER ERROR HANDLING', XMLHttpRequest, textStatus, errorThrown);
                
                // Unlock form from sending data
                // self.unlockElement(form);
                // NOTE: Keep It Locked
            }
        });
    },
    /**
     * Serialize a form into params and then forward to submitData.  Returns 
     * false to stop refular form submission from going through.
     * 
     * Note: We stop forms from submitting until a response is returned.
     * 
     * @param   string  
     * @return  bool    false
     */
    submitForm: function (form) {
        var self = this;
        // Only process form if it is not locked.
        if (!self.isElementLocked(form)) {
            // Lock form from sending data
            self.lockElement(form);
            // Post Form Data
            var params = form.serialize();
            var url = form.attr('action');
            if (this.notEmpty(url,params)) {
                this.submitData(url,params,form);
            } else {
                this.errorBox('','We are sorry there has been an error.  Please try again later.');
            }
        }
        return false;
    },
    /**
     * Post a hash of params to an action
     * 
     * Note: We stop forms from submitting until a response is returned.
     * 
     * @param   string  
     * @param   Object
     * @param   string  Id of element sending values.  This is used for
     *                  locking the posting element.
     * @return  bool    false
     */
    submitParams: function (url,params,element) {
        var self = this;
        var element = $(element);
        // Only process if element it is not locked.
        if (!self.isElementLocked(element)) {
            // Lock form from sending data
            self.lockElement(element);
            // Post Form Data
            if (this.notEmpty(url,params)) {
                this.submitData(url,params,element);
            } else {
                this.errorBox('','We are sorry there has been an error.  Please try again later.');
            }
        }
        return false;
    },
    /**
     * Bind all forms with a method of "ajax" to the submitForm function 
     * 
     * @return  void
     */
    bindForms: function () {
        var self = this;
        $.each($('form.ajax-form'), function(i, form) {
            $(form).bind("submit", function(e){
                return self.submitForm($(form));
            });
        });        
    },
    /**
     * Lock an element from submitting
     * 
     * @param   jQuery object
     */
    lockElement: function (form) {
        form.attr('locked','true');
        form.addClass('locked');
    },
    /**
     * Unlock an element from submitting
     * 
     * @param   jQuery object
     */
    unlockElement: function (form) {
        form.attr('locked','false');
        form.removeClass('locked');
    },
    /**
     * Check if an element is locked from from submitting
     * 
     * @param   jQuery object
     */
    isElementLocked: function (form) {
        return (form.attr('locked') == 'true');
    },




/******************************************************************************
 * DOM Manipulation Actions
 *****************************************************************************/
    
    /**
     * Iterate through each DMRAction
     * 
     * @param    array    An array of all DRM Actions to be performed    
     */
    runDMRA: function(self,actions)
    {
        $.each(actions, function(i, action) {
            self[action.action](action.selectors,action.params);
        });
    },
    /**
     * Show elements using jQuery's .show() Effect
     * 
     * @param    string    jQuery CSS selector
     * @param    string    Any of the jQuery's .show() effect speeds
     */
    show: function(selectors,params)
    {
        $(selectors).show(params);
    },
    /**
     * Hide elements using jQuery's .hide() Effect
     * 
     * @param    string        jQuery CSS selector
     * @param    string        Any of the jQuery's .hide() effect speeds 
     */
    hide: function(selectors,params)
    {
        $(selectors).hide(params);
    },
    /**
     * Show elements using jQuery's .fadeIn() Effect
     * 
     * @param    string    jQuery CSS selector
     * @param    string    Any of the jQuery's .show() effect speeds
     */
    fadeIn: function(selectors,params)
    {
        $(selectors).fadeIn(params);
    },
    /**
     * Hide elements using jQuery's .fadeOut() Effect
     * 
     * @param    string        jQuery CSS selector
     * @param    string        Any of the jQuery's .hide() effect speeds 
     */
    fadeOut: function(selectors,params)
    {
        $(selectors).fadeOut(params);
    },
    /**
     * Show elements using jQuery's .fadeOut() Effect wait specified amnount of 
     * time and fade out.
     * 
     * @param    string        jQuery CSS selector
     * @param    string        Any of the jQuery's .hide() effect speeds
     * @param    number        Number in seconds to delay until the fade out 
     */
    fadeInDelayOut: function(selectors,params)
    {
        $(selectors).fadeIn(params.fadeInParams)
            .animate({opacity: 1.0}, (params.stayDelay*1000))
            .fadeOut(params.fadeOutParams);
    },
    /**
     * Show elements using jQuery's .fadeOut() Effect wait specified amnount of 
     * time, fade out and then remove from DOM
     * 
     * @param    string        jQuery CSS selector
     * @param    string        Any of the jQuery's .hide() effect speeds
     * @param    number        Number in seconds to delay until the fade out 
     */
    fadeInDelayOutRemove: function(selectors,params)
    {
        var elements = $(selectors);
        elements.fadeIn(params.fadeInParams)
            .animate({opacity: 1.0}, (params.stayDelay*1000), function() {
                elements.fadeOut(params.fadeOutParams, function() {
                    elements.remove();
                });
            });
    },
    /**
     * Removes all matched elements from the DOM.
     * 
     * @param    string        jQuery CSS selector
     */
    remove: function(selectors)
    {
        $(selectors).remove();
    },
    /**
     * Insert content before each of the matched elements.
     * 
     * @param    string        jQuery CSS selector
     * @param    string        html to insert
     */
    before: function(selectors,params)
    {
        $(selectors).before(params);
    },
    /**
     * Insert content after each of the matched elements.
     * 
     * @param    string        jQuery CSS selector
     * @param    string        html to insert
     */
    after: function(selectors,params)
    {
        $(selectors).after(params);
    },
    /**
     * Insert content after each of the matched elements.
     * 
     * @param    string        jQuery CSS selector
     * @param    string        html to insert
     */
    text: function(selectors,params)
    {
        $(selectors).text(params);
    },
    /**
     * Insert content after each of the matched elements.
     * 
     * @param    string        jQuery CSS selector
     * @param    string        html to insert
     */
    html: function(selectors,params)
    {
        $(selectors).html(params);
    },
    
    /**
     * Adds the specified class(es) to each of the set of matched elements.
     * 
     * @param    string     jQuery CSS selector
     * @param    string     One or more classes to add to the elements, these 
     *                      are separated by spaces. 
     */
    addClass: function(selectors,params)
    {
        $(selectors).addClass(params);
    },
    /**
     * Removes all or the specified class(es) from the set of matched elements.
     * 
     * @param    string     jQuery CSS selector
     * @param    string     One or more classes to add to the elements, these 
     *                      are separated by spaces. 
     */
    removeClass: function(selectors,params)
    {
        $(selectors).removeClass(params);
    },
    /**
     * Set the value attribute of every matched element.
     * 
     * @param    string         jQuery CSS selector
     * @param    string/array   Set the value attribute of every matched 
     *                          element.
     *                          Checks, or selects, all the radio buttons, 
     *                          checkboxes, and select options that match 
     *                          the set of values.  User an array for multiple
     *                          selects. 
     *                          
     */
    val: function(selectors,params)
    {
        $(selectors).val(params);
    },
    
    /**
     * Set the attribute of every matched element.
     * 
     * @param    string         jQuery CSS selector
     * @param    string/array   Set the value attribute of every matched 
     *                          element.
     *                          Checks, or selects, all the radio buttons, 
     *                          checkboxes, and select options that match 
     *                          the set of values.  User an array for multiple
     *                          selects. 
     *                          
     */
    attr: function(selectors,params)
    {
        $(selectors).attr(params.name,params.value);
    },
    /**
     * @param    string         URL
     */
    redirect: function(selectors,url)
    {
    	window.location = url;
    },    
    /**
     * Close The Login Modal
     */
    closeLoginModal: function()
    {
        $('#login-modal').dialog('close');
    },

/******************************************************************************
 * Success/Error/Message Reporting
 *****************************************************************************/

    /**
     * We need to populate and show some message modal that comes up and closes 
     * for all pages.  For now we will just pop an alert.
     * 
     * @param   string  The title of the message box
     * @param   string  Message
     */
    messageBox: function(msgObj)
    {
        alert(msgObj.message);
    },
    /**
     * We need to populate and show some error modal that comes up and closes 
     * for all pages.  For now we will just pop an alert.
     * 
     * @param   string  The title of the error box
     * @param   string  Error message
     */
    errorBox: function(title,errorMsg)
    {
        alert(errorMsg);
    },    
    /**
     * Handle a redline_error JSON object
     * 
     * 
     */
    redlineErrorHandler: function(rlError)
    {
        /**
         * TODO     Decide if we want any type of information from the error 
         *          dispalyed.  We dont :D 
         */
        this.errorBox('Error','There has been an error and we are looking into it.  Please try again later.');
    },




/******************************************************************************
 * Utility Functions
 *****************************************************************************/

    /**
     * Checks all supplied arguments to be non empty.
     * 0, '', null and undefined are all False
     * 
     * @param    string(s)
     */
    notEmpty: function(str)
    {
        var a=arguments; var l=a.length; var i=0;
        
        if (l==0) { 
            throw new Error('Empty isset'); 
        }
        
        while (i!=l) {
            if (a[i]) { 
                i++;                
            } else { 
                return false;
            }
        }
        return true;
    }

};

/**
 * Setup once document is ready
 */
$(document).ready(function(){
    // Bind all forms with the method 'ajax' when Document is ready
    remoteActionHandler.bindForms();
});


/**
 * Unlock all forms on the page
 */
function unlock()
{
    $('form').attr('locked',false);
}