/**
 * mrInviteContacts plugin
 * @author Marek Kalnik <marekk@theodo.fr>
 * @since  2011-05
 *
 * This plugin manages the basic application flow for inviting contacts:
 * - receive contacts from server (in form of JSON array)
 * - display contacts as a list in attached form element
 * - allow user to transfer contacts to a "selected contacts" form
 * - submit the "selected contacts" form along with a message provided by user
 *
 * This plugin depends on mrNotice plugin for displaying it's errors
 */
(function ($) {
  /**
   * @param  params {Object}  Parameter list
   *   params = {
   *     serverResponse = {
   *       status {String}, // ok | fail, fail
   *       error  {String}, // Provide in case of error
   *       contacts {Object} // The server response object
   *     },
   *     directInput {String} // Direct input to use instead of server response
   *     form {Object} // A form object that contains the data to send
   *                   // For multiple forms make it an object eg. 'registered': form, 'unregisterd':form
   *     postParameters {Object}, // POST parameters to send with targetForm submit
   *     dictionary {String}, // i18n dictionary name
   *     steps {Number} // Number of steps: 1 - display all, 2 - display unregistered/registered;
   *                    // 2 steps require form parameter to be an array
   *   }
   */
    $.mrInviteContacts = function(params) {

        // Options by default
        params = $.extend({
          dictionary: 'contact',
          steps: 1
        }, params);

         var env = {
           errors: [],
           step: null
         };

    var methods =
    {
      /**
       * Verifies server response and initializes forms
       */
      init: function()
      {
        // Verification of server response
        if (params.serverResponse.status === 'fail') {
          env.errors.push(params.serverResponse.error);
        }

        if (typeof params.serverResponse.contacts === 'undefined' || params.serverResponse.contacts.length === 0) {
          env.errors.push(__('message_no_contacts_received', null, params.dictionary));
          return;
        }

        var contacts = params.serverResponse.contacts;

          switch (params.steps) {

            case 1:

              // Case of event invitations
              params.form.init(contacts, this);
              break;
  
            case 2:
              var unregisteredContacts = [],
                  registeredContacts   = [],
                  nb_contacts          = contacts.length;
  
              // Case of contact invitations
              // Filter contacts registered / unregistered
              for (var i = 0; i < nb_contacts; i++) {
                if (contacts[i].is_member) {
                  registeredContacts.push(contacts[i]);
                } else {
                  unregisteredContacts.push(contacts[i]);
                }
              }
  
              // Initializes the form, sets state and preserves data
              if (registeredContacts.length) {
  
                params.form.registered.init(registeredContacts, this, true);
                env.step = 'registered';
                env.cachedData = unregisteredContacts;
  
              } else if (unregisteredContacts.length) {
  
                params.form.unregistered.init(unregisteredContacts, this);
                env.step = 'unregistered';
              }
              break;

          default:
            throw 'Number of steps not defined correctly';
        }

        methods._flushErrors();
      },

      /**
       * AJAX handler for submitting invitation
       * 
       * @param event {Object} An browser submit event
       * @param form  {Object} An form DOM element
       * @param sendOnly {Boolean} Wheter to skip form switching
       */
      invite: function(event, form, sendOnly) {

        event.preventDefault();

        var postParams;

        // Default value = false
        sendOnly = sendOnly || false;

        $form = $(form);

        var formData = $form.serializeArray(),
            url      = $form.attr('action');

        // No user selected
        if (formData.length === 0) {
          env.errors.push(__('message_select_add_before_send_invitation', null, params.dictionary));
          methods._flushErrors();
          jQuery('#ajax_form_registered_contacts').deactivateValidationProtection();

          return false;

        } else {

          if (typeof params.postParameters != 'undefined' && params.postParameters.length != 0) {
              postParams = jQuery.param(params.postParameters) + $form.serialize()
          } else {
              postParams = $form.serialize();
          }
  
          $.post(
            url,
            postParams,
            function (data) {
              try {
                if (data.hasOwnProperty('redirect_to')) {
                  parent.location.replace(data.redirect_to);
                }
                                
                if ((data.hasOwnProperty('error_message') && data.error_message.length > 0)) {
                  $('#ajax_load_multi_tools_right_column').hide();
                  env.errors.push(data.error_message);
                } else {
                  $.notice.display(__('message_invitation_has_been_successfully_sent', null, params.dictionary), 'notice');
                }
                
              } catch (e) {
                env.errors.push(__('message_server_communication_error', null, params.dictionary));
              }
  
              methods._flushErrors();
              $form.deactivateValidationProtection();
            },
            'json'
          );

          $('#ajax_load_multi_tools_right_column').hide();
          $('#ajax_selected_emails_for_send li').remove();
        }

        if (!sendOnly) {
          methods._flushErrors();
          methods._finishCurrentForm();
        }

        return false;
      },

      // Hides the current form and moves to next step if needed
      _finishCurrentForm: function () {
        if (!env.step) {

          params.form.end();
        } else {
          params.form[env.step].end();

          if (env.step == 'registered' // the current step is registered
              && typeof env.cachedData != 'undefined'
              && env.cachedData.length != 0) // and there are saved contacts available
          {
            env.step = 'unregistered';
            params.form.unregistered.init(env.cachedData, this);

            delete env.cachedData;
          }
        }
      },

      // Call it after every event handler
      _flushErrors: function() {

        if (env.errors.length != 0) {

          $.notice.display(env.errors.join(' '), 'error');

          env.errors = [];
        }
      }
    };

    // Returns public methods
    return {
      init: methods.init,
      invite: methods.invite
    };
  }
})(jQuery);
