/**
 * Plugin de prise en charge des différents formulaires pour s'appuyer sur le framework Idvive
 * @author Yannick (yannickdalbin at gmail.com) 2011-10-12
 *          @corpyright 2011
 *
 * Prend en charge le submit. Simplement appliquer le plugin idform() sur un objet jQuery de type form.
 * Les messages sont contenus dans un div avec comme attribus la classe .errors.
 * Chaque erreur d'un champs particulier est contenu dans un li
 *
 * Les events :
 *  Chaque form aura différents events :
 *      idform_[idFormulaire]_submitted : event sur l'envoi du formulaire par l'utilisateur
 *      idform_[idFormulaire]_actionBeforeSend : event juste avant la requête ajax
 *      idform_[idFormulaire]_savedSuccess : event lorsque tout s'est bien passé
 *      idform_[idFormulaire]_validationError : event lorsque le formulaire est en erreur
 *      idform_[idFormulaire]_savedFailed : event lorsque le traitement du formulaire est en echec
 *
 */
(function ($) {

    var methods = {
        init : function () {
            return this.each(function () {

                //Détection de l'envoi du form
                $(this).submit(function (e) {
                    e.preventDefault();
                    $(this).trigger('idform_' + $(this).attr('id') + '_submitted');
                    //On lance le traitement
                    $(this).idform('action');
                })

            });
        },
        action : function () {
            return this.each(function () {

                var $this = $(this);

                //La requête ajax va être lancée....
                $(this).trigger('idform_' + $(this).attr('id') + '_actionBeforeSend');

                $(this).ajaxSubmit({
                    dataType        : 'json',
                    success         : function (response) {
                        //On cache les éventuels messages d'erreur encore présent avant toute choses
                        $('.errors, .error').each(function () {
                            $(this).remove();
                        });

                        //Si tout est ok on prévient !
                        if (response.success === true) {
                            $this.trigger('idform_' + $this.attr('id') + '_savedSuccess', [response]);
                        }
                        else {
                            //Si erreur dans le formulaire, on affiche les messages d'erreurs
                            if (response.errorType === 'validation') {

                                //On va traiter tous les messages un par un
                                var messages = $.parseJSON(response.messages);
                                $.each(messages, function (field, errors) {
                                    //Chaque champs peut contenir plusieurs erreurs.. on met tout dans un ul
                                    var message_errors = $('<ul></ul>');
                                    $.each(errors, function (typeError, message) {
                                        message_errors.append($('<li></li>').append(message))
                                    });

                                    //Petit tweaks lorsque le champs est de type password et est donc dédoublé
                                    var el = $('#' + field);

                                    if (el.length === 0) {
                                        el = $('input[name="' + field + '"]');

                                        if (el.length > 0) {
                                            if (el.attr('type') == 'checkbox' || el.attr('type') == 'radio') {
                                                el = el.eq(-1);
                                                el = el.parent();
                                            }
                                        }
                                    }

                                    if (el.next().attr('class') !== undefined && el.next().attr('class') == el.attr('id')) {
                                        el = el.next();
                                    }

                                    if (el.next().is('label') && el.next().attr('for') !== undefined && el.next().attr('for') == el.attr('id')) {
                                        el = el.next();
                                    }

                                    //On se prépare pour afficher les erreurs des différents champs
                                    var cont = $('<div></div>').attr('class', 'errors');
                                    cont.append(message_errors);
                                    el.after(cont.hide());
                                    if (cont.css('position') == 'absolute') {
                                        cont.css({
                                            left:   el.offset().left,
                                            top:    el.offset().top+3
                                        });
                                        cont.width(el.outerWidth());
                                    }

                                    //Un petit effet d'affichage'
                                    cont.slideDown();
                                    //On détect le focus sur l'élément pour cacher le message d'erreur en cas de focus
                                    var binded_el = null;
                                    if (el.attr('class') !== undefined && el.attr('class') == el.prev().attr('id')) {
                                        binded_el = el.prev();
                                    }
                                    else {
                                        binded_el = el;
                                    }
                                    binded_el.bind('change keypress', function () {
                                        if ($(this).next().attr('class') === 'errors') {
                                            $(this).next().slideUp('normal', function () {
                                                $(this).remove();
                                            });
                                        }
                                        else if ($(this).next().attr('class') === $(this).attr('id') && $(this).next().next().attr('class') === 'errors') {
                                            $(this).next().next().slideUp('normal', function () {
                                                $(this).remove();
                                            });
                                        }
                                    });
                                });

                                $('.errors:first').prev().focus();

                                //On prévient que rien ne vas !
                                $this.trigger('idform_' + $this.attr('id') + '_validationError');

                            }
                            else {
                                //Sinon erreur du formulaire
                                $this.trigger('idform_' + $this.attr('id') + '_savedFailed', [response]);
                            }
                        }
                    }
                });

            });
        }
    };

    $.fn.idform = function (method) {

        //Si le paramètre correspond à une fonction de l'objet méthode.. On lance
        if (methods[method]) {
            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
        }
        //Sinon si le param est un objet de parametre ou aucun param, on lance le constructeur
        else if (typeof method === 'object' || !method) {
            return methods.init.apply(this, arguments);
        }
        //Sinon on sait pas !
        else {
            $.error('Method ' +  method + ' does not exist on jQuery.idform');
            return false;
        }

    }

})(jQuery);
