/**
 * @author Raphaël Benitte
 * @since  2012-01-27
 */
(function ($) {

    'use strict';

    var _namespace = 'mr.invite',
        _env;

    var _methods = {

        /**----------------- DATA PROCESSING ---------------------------------*/
        /**
         * @param data json containing an ajax response
         */
        _sanitizeData: function (data) {
            if (data.hasOwnProperty('status') && data.status === 'fail') {
                jQuery.notice.display(data.error, 'error');
                return false;
            }

            if (data.hasOwnProperty('contacts')) {
                return data.contacts;
            }

            _env.errors.push(__('message_error_format', null, _env.settings.catalogue));
            _methods._flushErrors();

            return false;
        },

        /**
         * @param inputEmails
         */
        _sanitizeEmails: function(inputEmails) {

            var valid   = [],
                invalid = [],
                nbEmail = inputEmails.length,
                regex   = /^([A-Za-z0-9_\-\.])+@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/,
                email;

            for (var i = 0; i < nbEmail; i++) {
                email = inputEmails[i];
                if (!regex.test(email)) {
                    invalid.push(email);
                } else {
                    valid.push(email);
                }
            }

            return {
                valid:   valid,
                invalid: invalid
            };
        },

        /**
         * Returns a list of valid and invalid emails from a comma separated list
         *
         * @param string
         */
        _emailsFromString: function(string) {

            var emails = string.replace(/\s/g, '').split(',');

            return _methods._sanitizeEmails(emails);
        },


        /**----------------- RENDERING ---------------------------------------*/
        /**
         * @param contact
         * @param source should be buddies, web, csv, plain-text
         */
        _appendSelectedItem: function(contact, source) {

            _methods._log('_appendSelectedItem from "' + source + '" source');

            var contactItem = _methods._renderSelectedContactItem(contact, source);
            _env.$listToSend.append(contactItem);
            _env.$listToSend.find('.remove_invite').click(_methods._onRemoveButtonClick);
        },

        /**
         * @param contact
         * @param source
         */
        _renderSelectedContactItem: function(contact, source) {

            _methods._log('_renderSelectedContactItem from "' + source + '" source', contact);

            var cssClass = '';
            if (contact.isMember === true) {
                cssClass = ' class="member"';
            }

            return '<li' + cssClass + '>\n\
                <label><span class="name">' + contact.name + '</span></label>\n\
                <a href="#" class="remove_invite ' + source + '">' + __('link_remove_invite', null, _env.settings.catalogue) + '</a>\n\
                <input type="hidden" name="contacts[to][]" value="' + contact.email + '" />\n\
            </li>';
        },

        /**
         * @param contact
         * @param source  should be buddies, web, csv, plain-text
         */
        _appendContactItem: function(contact, source) {

            _methods._log('_appendContactItem from "' + source + '" source', contact);

            var contactItem = _methods._renderContactItem(contact, source),
                $list;

            if (source === 'buddies') {
                $list = _env.$buddyList;
            } else if (source === 'csv') {
                $list = _env.$csvList;
            } else if (source === 'web') {
                $list = _env.$socialList;
            }

            if ($list) {
                $list.append(contactItem).find('input:checkbox').click(_methods._onAddItemClick);
            }
        },

        /**
         * @param contact
         * @param source
         */
        _renderContactItem: function(contact, source) {

            var inputClass = contact.isMember ? 'registered member' : 'unregistered',
                id         = 'add_contact_' + contact.email.replace('@', '_'),
                name       = contact.hasOwnProperty('name') ? contact.name : contact.email;

            var buddyItem = '<li class="' + source + '">';
            buddyItem += '<p class="add_invite">';
            buddyItem += '<input type="checkbox" id="' + id + '" value="' + contact.email + '" class="' + inputClass + '" />&nbsp;';
            buddyItem += '<label for="' + id + '">' + name + '</label>';
            if (contact.isMember) {
                buddyItem += '&nbsp;&nbsp;<img src="/images/common/ever-register.gif" />';
            }
            buddyItem += '</p>';
            buddyItem += '</li>';

            return buddyItem;
        },

        _displayImportedEmails: function(contacts, $container, source) {

            var items = '',
                nbContact = contacts.length,
                contact,
                email;

            for (var index = 0; index < nbContact; index++) {
                contact = contacts[index];
                email   = contact.email;
                contact.isMember = false;
                if (contact.hasOwnProperty('is_member')) {
                    contact.isMember = contact.is_member;
                }

                items += _methods._renderContactItem(contact, source);
            }

            if (items.length > 0) {
                $container.append(items);
                $container.find(':checkbox').bind('click', _methods._onAddItemClick);
            }
        },

        /**----------------- HANDLERS ----------------------------------------*/
        /**
         * Invoked when user clicks the add button.
         * Adds a contact to the selected list.
         *
         * @param event a jQuery click event
         *
         * @return bool
         */
        _onAddItemClick: function(event) {

            var $this  = $(this),
                email  = $this.val(),
                source = 'buddies',
                $li    = $(this).closest('li');

            if ($li.hasClass('csv')) {
                source = 'csv';
            } else if ($li.hasClass('web')) {
                source = 'web';
            }

            _methods._log('Item clicked for addition from "' + source + '" source', $li);

            _methods._appendSelectedItem({
              email:    email,
              name:     $li.find('label').text(),
              isMember: $this.hasClass('member')
            }, source);

            $li.remove();

            return false; // Prevents event concurrency
        },

        /**
         * Invoked when user clicks the remove button.
         * Removes a contact from the selected list.
         *
         * @param event a jQuery click event
         *
         * @return bool
         */
        _onRemoveButtonClick: function (event) {
            event.preventDefault();

            var $button     = $(this),
                $li         = $button.closest('li'),
                email       = $li.find('input').val(),
                source      = 'undefined',
                contactData = {
                    email:    email,
                    name:     $li.find('label').text(),
                    isMember: $li.hasClass('member')
                };

            if ($button.hasClass('buddies')) {
                contactData.name = $li.find('.name').text();
                source = 'buddies';
            } else if ($button.hasClass('web')) {
                source = 'web';
            } else if ($button.hasClass('csv')) {
                source = 'csv';
            } else if ($button.hasClass('plain-text')) {
                source = 'plain-text';
            }

            _methods._log('Item clicked for removal from "' + source + '" source', $li);

            // don't restore for plain text generated items
            if (!$button.hasClass('plain-text')) {
                _methods._appendContactItem(contactData, source);
            }

            $li.remove();

            return false; // Prevents event concurrency
        },

        /**----------------- ERRORS ------------------------------------------*/
        /**
         * Display and empty current errors.
         */
        _flushErrors: function() {

            if (_env.errors.length > 0) {
                $.notice.display(_env.errors.join(' '), 'error');

                _env.errors = [];
            }
        },

        /**----------------- LOGGING/DEBUG -----------------------------------*/
        /**
         * @param logMessage
         */
        _log: function(logMessage, logData) {

            _env.logs.push({
                message: logMessage,
                data:    logData
            });

            if (_env.settings.debug === true) {
                console.info(logMessage);
                if (logData) {
                    console.log(logData);
                }
            }
        }
    };

    var methods = {

        /**
         * Initialization.
         *
         * @param options
         */
        init: function(options) {
            return this.each(function () {
                var $this    = $(this),
                    settings = $.extend({
                        inviteFormSelector:    '#send_invitations_form',
                        socialListSelector:    '#adress_import .contact_list',
                        socialButtonSelector:  '#neighbour_webmail_validation_button',
                        csvFormSelector:       '#ajax_invite_csv',
                        plainTextFormSelector: '#manual_form',
                        listToSendSelector:    '#send_email_to_list',
                        buddyListSelector:     '#contact_mr_list .list',
                        buddySelectSelector:   '#select_group',
                        csvListSelector:       '#add_file .contact_list',
                        catalogue:             'contact',
                        debug:                 true
                    }, options);

                if (!$this.data(_namespace)) {
                    $this.data(_namespace, {
                        $inviteForm:     $(settings.inviteFormSelector),
                        $socialList:     $(settings.socialListSelector),
                        $socialButton:   $(settings.socialButtonSelector),
                        $plainTextForm:  $(settings.plainTextFormSelector),
                        $csvForm:        $(settings.csvFormSelector),
                        $listToSend:     $(settings.listToSendSelector),
                        $buddyList:      $(settings.buddyListSelector),
                        $buddySelect:    $(settings.buddySelectSelector),
                        $csvList:        $(settings.csvListSelector),
                        settings:        settings,
                        errors:          [],
                        logs:            [],
                        contacts:        {}
                    });
                }
            });
        },

        /**
         * @param contacts an array of contacts
         * @param source   should be buddies, web, csv, plain-text
         */
        addItems: function (contacts, source) {

            var nbContacts = contacts.length,
                html       = '',
                contact,
                contactData;

            for (var i = 0; i < nbContacts; i++) {

                contact = contacts[i];
                contactData = {
                    email:    contact,
                    name:     contact,
                    isMember: false
                };

                if (contact.hasOwnProperty('email')) {
                    contactData.email = contact.email;
                } else if (contact.hasOwnProperty('contact')) {
                    contactData.email = contact.contact;
                }

                if (contact.hasOwnProperty('name')) {
                    contactData.name = contact.name;
                } else {
                    contactData.name = contactData.email;
                }

                if (contact.hasOwnProperty('is_member')) {
                    contactData.isMember = contact.is_member;
                } else if (contact.hasOwnProperty('isMember')) {
                    contactData.isMember = contact.isMember;
                }

                html += _methods._renderSelectedContactItem(contactData, source);
            }

            if (html.length > 0) {
                _env.$listToSend.append(html);
                _env.$listToSend.find('.remove_invite').bind('click', _methods._onRemoveButtonClick);
            }
        },

        /**
         * Initialization of buddies invite.
         */
        initBuddies: function() {

            _methods._log('initBuddies()');

            _env.$buddyList.find('input:checkbox').bind('click', _methods._onAddItemClick);

            _env.$buddyList.find('.add_invite_all').click(function(event){
                event.preventDefault();

                var $buddies = _env.$buddyList.find('input:checkbox');
                _methods._log('Adding all buddies', $buddies);
                $buddies.trigger('click');
            });

            _env.$buddySelect.change(function() {

                var $select      = _env.$buddySelect,
                    elementActif = $select.val(),
                    options      = $select.children(),
                    index,
                    selector;

                if (elementActif != 'all') {
                    for (index = 0; index < options.length; index++ ) {
                        selector = '.' + options[index].value + '.here';
                        $(selector + ' > p ').removeClass('add_invite');
                        $(selector).hide();
                    }

                    selector = '.' + elementActif + '.here';
                    $(selector + ' > p ').addClass('add_invite');
                    $(selector).show();
                } else {
                    for (index = 0; index < options.length; index++ ) {
                        selector = '.' + options[index].value + '.here';
                        $(selector + ' > p ').addClass('add_invite');
                        $(selector).show();
                    }
                }
            });

            return this;
        },

        /**
         * Initialization of social invite (janrain used on january 2012).
         */
        initSocialImport: function() {

            _methods._log('initSocialImport()');

            _env.$socialList.hide();

            var $container = _env.$socialButton.closest('div'),
                $loader    = $container.find('.loader');

            _env.$socialList.find('.other_provider').click(function(event) {
                event.preventDefault();

                _methods._log('Trying to change social contact provider');

                $container.show();
                _env.$socialList.hide().find('li:gt(1)').remove();
            });

            _env.$socialButton.bind('click', function(event){
                event.preventDefault();

                var $wrapper = _env.$socialButton.parent(),
                    url      = _env.$socialButton.closest('a').attr('href');

                $wrapper.css('opacity', 0.3);
                $loader.show();

                $.post(
                    url,
                    null,
                    function (data) {

                        _methods._log('Social import data received', data);

                        $loader.hide();
                        $container.hide();
                        $wrapper.css('opacity', 1);

                        _methods._displayImportedEmails(_methods._sanitizeData(data), _env.$socialList, 'web');

                        _env.$socialList.find('.add_invite_all').click(function(event){
                            event.preventDefault();

                            var $socialContacts = _env.$socialList.find('input:checkbox');
                            _methods._log('Adding all social contacts', $socialContacts);
                            $socialContacts.trigger('click');
                        });

                        _env.$socialList.show();
                    },
                    'json'
                );
            });

            return this;
        },

        /**
         * Plain text import (via textarea) initialization.
         */
        initPlainTextInvite: function() {

            _methods._log('initPlainTextInvite()');

            var $textarea = _env.$plainTextForm.find('textarea');

            _env.$plainTextForm.bind('submit', function(event){
                event.preventDefault();

                var emailResult = _methods._emailsFromString($textarea.val());

                if (emailResult.valid.length > 0) {
                    methods.addItems(emailResult.valid, 'textarea');
                }
                if (emailResult.invalid.length > 0) {
                    _env.errors.push( __('message_error_format',  null, 'contact') + ' : ' + emailResult.invalid.join(', '));
                    _methods._flushErrors();
                }

                $textarea.val('');
            });

            return this;
        },

        /**
         * Initialization of CSV contacts import/invite.
         */
        initCsvInvite: function() {

            _methods._log('initCsvInvite()');

            _env.$csvList.hide();

            _env.$csvForm.ajaxForm({
                cache:    false,
                dataType: 'json',
                success:  function (data) {

                    _methods._log('CSV data received', data);

                    _env.$csvForm.hide().deactivateValidationProtection();
                    _methods._displayImportedEmails(_methods._sanitizeData(data), _env.$csvList, 'csv');
                    _env.$csvList.show();
                }
            });

            _env.$csvList.find('.add_invite_all').click(function (event) {
                event.preventDefault();

                var $csvContacts = _env.$csvList.find('input:checkbox');

                _methods._log('Adding all CSV contacts', $csvContacts);

                $csvContacts.trigger('click');
            });

            _env.$csvList.find('.other_file').click(function(event) {
                event.preventDefault();

                _methods._log('Trying to load an other CSV file');

                _env.$csvForm.show();
                _env.$csvList.hide().find('li:gt(1)').remove();
            });

            return this;
        },

        initRemovalCommand: function() {

            _methods._log('initRemovalCommand()');

            _env.$inviteForm.find('.remove_user').click(function (event) {
                event.preventDefault();
                _env.$listToSend.find('.remove_invite').trigger('click');
            });

            return this;
        },

        /**
         * All in one initialization.
         */
        initAll: function() {

            _methods._log('initAll()');

            methods.initSocialImport();
            methods.initBuddies();
            methods.initPlainTextInvite();
            methods.initCsvInvite();
            methods.initRemovalCommand();

            return this;
        }
    };

    $.fn.mrInvite = function(method) {
        if (!$(this).data(_namespace)) {
            methods.init.apply(this, arguments);
        }

        _env = $(this).data(_namespace);

        return methods;
    };

})(jQuery);


/**
 * Used for invitation module
 */
jQuery(document).bind('cbox_complete', function () {

    var $invitePopup = jQuery('#popup.invite');

    // If the popup opened is not invitation popup
    if ($invitePopup.length === 0) {
        return true;
    }

    $invitePopup.mrInvite().initAll();

    jQuery('#send_invitations_form').bind('submit', function (e) {
        var inviter = jQuery.mrInviteContacts();
        inviter.invite(e, this, true);
    });

    return false;
});
