/**
 * AjaxHelper defines a set of helpers to interact with the view after an
 * AJAX call.
 *
 * A handler should be defined in the particular view:
 *
 * Example:
 *
  function handler(data) {
    // Parse the data string into a JSON object.
    data = JSON.parse(data);

    var logElement = "#log";
    var formElement = ".form";

    AjaxHelper.clearForm(formElement);
    AjaxHelper.clearLog(logElement);

    if (data.method == "successReplace") {
        AjaxHelper.successReplace(data.parameters.header, "#heading",
            data.parameters.message, formElement);
    } else if (data.method == "successHighlight") {
        AjaxHelper.highlight(data.parameters.message, logElement,
            "success");
    } else if (data.method == "errorForm") {
        AjaxHelper.errorForm(data.parameters.list, formElement);
    } else if (data.method == "error") {
        AjaxHelper.highlight(data.parameters.message, logElement,
            "error");
    }
  }
 *
 * @author Dario Javier Cravero <dario@starlight.ie>
 * @version 0.1b
 */

var AjaxHelper = {
    /**
     * Display a message on the desired item applying a fadeOut/fadeIn
     * jQuery effect.
     *
     * @param   header  (string)  The header of the page.
     * @param   headerElement (string)  The selector of the element to update
     * with the header.
     * @param   message (string)  The html message.
     * @param   messageElement (string)  The selector of the element to update
     * with the message.
     */
    successReplace: function(header, headerElement, message, messageElement) {
        $(headerElement).fadeOut().html(header).fadeIn();
        $(messageElement).fadeOut().html(message).fadeIn();
    },

    /**
     * Highlight a message on the desired item applying a fadeOut/fadeIn
     * jQuery effect.
     *
     * @param   message (string)  The html message.
     * @param   messageElement (string)  The selector of the element to update
     * with the message.
     * @param   classes (string)  A list of CSS clasess to apply to the element.
     */
    highlight: function(message, messageElement, classes) {
        $(messageElement).addClass("highlight " + classes).
            html(message).fadeIn(3000).fadeOut(3000);

        // Scroll the document to the element that changed.
        $(document).scrollTop($(messageElement).position().top);
    },

    /**
    * Removes an element from the DOM
    *
    * @param    element (string)    The selector of the element to remove.
    */
    remove: function(element) {
        $(element).fadeOut().remove();
    },

    /**
     * Clears a form of error messages.
     *
     * @param   form    (string)    The selector of the form to clear.
     */
    clearForm: function(form) {
        $(form + " .formError").attr("title", "").
            removeClass("formError fieldError labelError");
    },

    /**
     * Clears the log of messages.
     *
     * @param   log    (string)    The selector of the log to clear.
     */
    clearLog: function(log) {
        $(log).fadeOut().removeClass().html("");
    },

    /**
     * Clears a form of error messages.
     *
     * @param   list    (string)  The list of fields with errors.
     * @param   form    (string)  The selector of the form to clear.
     */
    errorForm: function(list, form) {
        var scroll = $(document).scrollTop();

        // Traverse the array looking for elements to mark as errors.
        for (key in list) {
            // Get the field/s.
            var fields = $(form + " [name*='[" + key + "]']");

            // In controls such as radio buttons we may have more than one
            // field. Therefore, we need to apply the error to all of those.
            fields.each(function (i, field) {
                // Apply the style and set its error message.
                $(field).addClass("formError fieldError").
                    attr("title", list[key]);

                // Get the label. Apply the style and set its error message.

                // Cake's radio button helper outputs its ids in a different
                // way that it does with regular inputs, hence we can't take
                // the id and get the label right away. So we have to get
                // rid of the _ and any attached numbers before using it.

                var id = $(this).attr("id");
                if ($(field).attr("type") == "radio") {
                  id = id.replace(/[0-9|_]/g, "");
                }

                $(form + " label[for='" + id + "']").
                    addClass("formError labelError").
                    attr("title", list[key]);
                
                // If this field is first, then change the scrolling value.
                if ($(field).position().top <= scroll) {
                    scroll = $(field).position().top;
                }
            });
        }

        // If the security image exists, reload it to get a new one.
        var d = new Date();
        var security = $(".security_image");
        if (security.length > 0) {
            var url = security.attr("src");
            var baseUrl = url.substring(0, url.indexOf("/download/security_image/"));
            security.attr("src", baseUrl + "/download/security_image/" +
                d.getTime() + ".jpg");
            // Reset the captcha value
            $("#SecurityCode").val("");
        }

        // Scroll the document to the element that changed which is first.
        $(document).scrollTop(scroll);

        // Focus the first element with errors and select it's values.
        $(form + " .fieldError:first").focus().select();
    }
}

