(function (window, $) {
    'use strict';

    function ContactsController(user) {
        this._user = user;
        this._contactsService = user.getContacts();
        this._contactDetails = new window.ContactController(this._contactsService);
        this._searchRequest = undefined;
        this._searchRetrieval = undefined;
        this._searchDataSet = undefined;

        this._contactsView = new window.ContactsView({
            handleStartSearch: function (searchString) {
                this.startSearch(searchString);
            }.bind(this),
            handleShowDetails: function (contactId) {
                this.openContactDetails(contactId);
            }.bind(this)
        });

        this._contacts = [];
        this._searchContacts = [];
    }


    ContactsController.prototype = {
        /**
         * Starts searching contacts.
         *
         * @param {String} searchString
         */
        startSearch: function (searchString) {
            if (this._searchRequest) {
                this._contactsService.changeSearchContactsRequest(this._searchRetrieval, searchString);
                this._contactsView.setSearchTitle(searchString);
                console.log('Search criteria were updated.');
            } else {
                this._searchRequest = new AvayaClientServices.Services.Contacts.ContactSearchRequest(searchString, "ALL", "ALL", 0, 0);
                this._contactsView.setSearchTitle(searchString);

                this._searchRetrieval = this._contactsService.searchContacts(this._searchRequest);
                this._searchDataSet = this._searchRetrieval.getDataSet();

                this._searchRetrieval.addOnDataRetrievalProgressCallback(function () {
                    console.log('Received search results');
                });

                this._searchRetrieval.addOnDataRetrievalDoneCallback(function () {
                    console.log('Search completed');
                }.bind(this));

                this._searchDataSet.addOnDataSetChangedCallback(function (contacts, type) {
                    if (type === AvayaClientServices.Base.DataSetChangeTypes.ADDED) {
                        console.log('Received ' + contacts.length + ' search results');
                        this._addContacts(contacts, this._searchContacts, 'searchContacts');
                    } else if (type === AvayaClientServices.Base.DataSetChangeTypes.REMOVED) {
                        console.log(contacts.length + ' search results were invalidated');
                        this._removeContacts(contacts, this._searchContacts);
                    }
                }.bind(this));
            }
        },
        /**
         * Function open modal with contact details.
         *
         * @param {String} [contactId]
         */
        openContactDetails: function(contactId) {
            if (contactId) {
                if (this._contacts[contactId]) {
                    this._contactDetails.init(this._contacts[contactId]);
                } else if (this._searchContacts[contactId]) {
                    this._contactDetails.init(this._searchContacts[contactId]);
                } else {
                    console.log('Contact not found');
                }
            } else {
                this._contactDetails.init();
            }
        },

        /**
         * Function add contact and presence state to local/search contacts list.
         *
         * @param {Array} contacts
         * @param {Array} contactsArray
         * @private
         */
        _addContacts: function (contacts, contactsArray) {
            contacts.forEach(function (contact) {
                var fname, lname;
                var contactId = this._getContactId(contact);
                if (contact.getFirstName().getValue()) {
                    fname = contact.getFirstName().getValue();
                } else if (contact.getASCIIFirstName().getValue()) {
                    fname = contact.getASCIIFirstName().getValue();
                }

                if (contact.getLastName().getValue()) {
                    lname = contact.getLastName().getValue();
                } else if (contact.getASCIILastName().getValue()) {
                    lname = contact.getASCIILastName().getValue();
                }
                this._contactsView.addContact(contactId, fname, lname);
                contactsArray[contactId] = contact;
            }.bind(this));
        },

        /**
         * Function remove contact from local/search contacts list.
         *
         * @param {Array} contacts
         * @param {Array} contactsArray
         * @param {String} contactsType
         * @private
         */
        _removeContacts: function (contacts, contactsArray, contactsType) {
            contacts.forEach(function (contact) {
                var contactId = this._getContactId(contact);
                contactsArray[contactId].stopPresence();
                this._contactsView.removeContact(contactId, contactsType);
                delete contactsArray[contactId];
            }.bind(this));
        },

        /**
         * Function generate contact id.
         *
         * @param {Object} contact
         * @returns {string}
         * @private
         */
        _getContactId: function (contact) {
            return "contact_" + contact.getUniqueAddressForMatching().replace(/[^a-zA-Z0-9]/g, '');
        }
    };

    window.ContactsController = ContactsController;

})(window, jQuery);
