(function(context,$) {

    "use strict";

    context.JK = context.JK || {};
    context.JK.InviteMusiciansUtil = function(app) {
        var logger = context.JK.logger;
        var userNames = [];
        var userIds = [];
        var userPhotoUrls = [];
        var friendSelectorDialog = null;
        var invitedFriends = [];
        var invitedFriendNames = [];
        var existingInvites = [];
        var autoComplete = null;
        var rest = context.JK.Rest();
        var inviteAction = 'create';  // create/update
        var friendInput = null;
        var updateSessionID = null;
        var addInstructions = '';

        function _initInvite(elemSelector, iAction, instructions) {
            addInstructions = instructions;
            inviteAction = iAction;
            friendInput = '#friend-input-'+inviteAction;
            _appendFriendSelector($(elemSelector));
            return friendInput;
        }

        this.inviteSessionCreate = function(elemSelector, instructions) {
            return _initInvite(elemSelector, 'create', instructions)
        };

        this.inviteBandCreate = function(elemSelector, instructions) {
            return _initInvite(elemSelector, 'band', instructions)
        };

        this.inviteSessionUpdate = function(elemSelector, sessionId) {
            this.clearSelections();
            updateSessionID = sessionId;
            friendSelectorDialog.setCallback(friendSelectorCallback);

            inviteAction = 'update';
            friendInput = '#friend-input-' + inviteAction;

            if (0 == $(elemSelector + ' .friendbox').length) {
                _appendFriendSelector($(elemSelector));
            }

            $('#btn-save-invites').unbind('click');

            $('#btn-save-invites').click(function() {
              createInvitations(updateSessionID);
              app.layout.closeDialog('select-invites');
            });

            $.ajax({
                url: "/api/invitations",
                data: { session_id:  sessionId, sender: context.JK.currentUserId }
            }).done(function(response) {
                response.map(function(item) {
                    var dd = item['receiver'];
                    existingInvites.push(dd.id);
                    addInvitation(dd.name, dd.id);
                });
            }).fail(app.ajaxError);

            return friendInput;
        }

        this.clearSelections = function() {
            userNames = [];
            userIds = [];
            userPhotoUrls = [];
            invitedFriends = [];
            invitedFriendNames = [];
            existingInvites = [];
            updateSessionID = null;
            $('.selected-friends').empty();
            $(friendInput).val('');
        };

        this.loadFriends = function() {
            friendSelectorDialog.setCallback(friendSelectorCallback);

            var friends = rest.getFriends({ id: context.JK.currentUserId })
                .done(function(friends) {
                    $.each(friends, function() {
                        userNames.push(this.name);
                        userIds.push(this.id);
                        userPhotoUrls.push(this.photo_url);
                    });
                    if (friendInput) {
                        var autoCompleteOptions = {
                            lookup: { suggestions: userNames, data: userIds },
                            onSelect: addInvitation,
                            serviceUrl: '/api/search.json?srch_sessinv=1',
                            minChars: 3,
                            autoSelectFirst: true
                        };
                        $(friendInput).attr("placeholder", "Type a friend\'s name").prop('disabled', false)
                        autoComplete = $(friendInput).autocomplete(autoCompleteOptions);
                        $(".autocomplete").width("150px");
                    }
                })
                .fail(function() {
                    $(friendInput).attr("placeholder", "Unable to lookup friends");
                    app.ajaxError(arguments);
                });
        }

        function friendSelectorCallback(newSelections) {
            var keys = Object.keys(newSelections);
            for (var i=0; i < keys.length; i++) {
                var dd = newSelections[keys[i]];
                addInvitation(dd.userName, dd.userId);
            }
        }

        function addInvitation(value, data) {
            if (undefined === data) {
                data = value.data;
                value = value.value;
            }
            if (0 > invitedFriends.indexOf(data)) {
                var template = $('#template-added-invitation').html();
                var invitationHtml = context.JK.fillTemplate(template, 
                                                             {userId: data, 
                                                              userName: value});
                $('.selected-friends').append(invitationHtml);
                $(friendInput).select();
                invitedFriends.push(data);
                invitedFriendNames.push(value);

            } else {
                $(friendInput).select();
                // context.alert('Invitation already exists for this musician.');
            }
            $(friendInput).val('');
        }

        this.addInvitationIfAbsent = addInvitation;

        function getInvitedFriends() {
          return invitedFriends;
        }

        this.getInvitedFriends = getInvitedFriends;

        function getInvitedFriendNames() {
          return invitedFriendNames;
        }

        this.getInvitedFriendNames = getInvitedFriendNames;

        function removeInvitation(evt) {
            var idx = invitedFriends.indexOf($(evt.currentTarget).parent().attr('user-id'));
            if (0 <= idx) {
              invitedFriends.splice(idx, 1);
              invitedFriendNames.splice(idx, 1);
            }
            $(evt.currentTarget).closest('.invitation').remove();
        }

        function createInvitations(sessionId, onComplete) {
            var callCount = 0;
            var totalInvitations = invitedFriends.length;
            invitedFriends.map(function(invite_id) {
              callCount++;
              var invite = {
                  music_session: sessionId,
                  receiver: invite_id
              };
              $.ajax({
                  type: "POST",
                  url: "/api/invitations",
                  data: invite
              }).done(function(response) {
                  callCount--;
              }).fail(app.ajaxError);
            });
            // TODO - this is the second time I've used this pattern.
            // refactor to make a common utility for this.
            function checker() {
                callCount === 0 ? onComplete() : context.setTimeout(checker, 10);
            }
            if (onComplete) checker();
            return totalInvitations;
        }
        this.createInvitations = createInvitations;

        function searchFriends(query) {
            if (query.length < 2) {
                $('#friend-search-results').empty();
                return;
            }
            var url = "/api/search?query=" + query + "&userId=" + context.JK.currentUserId;
            $.ajax({
                type: "GET",
                url: url,
                success: friendSearchComplete
            });
        }

        function friendSearchComplete(response) {
            // reset search results each time
            $('#friend-search-results').empty();

            // loop through each
            $.each(response.friends, function() {
                // only show friends who are musicians
                if (this.musician === true) {
                    var template = $('#template-friend-search-results').html();
                    var searchResultHtml = context.JK.fillTemplate(template, {userId: this.id, name: this.first_name + ' ' + this.last_name});
                    $('#friend-search-results').append(searchResultHtml);
                    $('#friend-search-results').attr('style', 'display:block');
                }
            });
        }

        function _friendSelectorHTML() {
            var fInput = friendInput ? friendInput.substring(1,friendInput.length) : '';
            return context.JK.fillTemplate($('#template-session-invite-musicians').html(),
                                           {choose_friends_id: 'btn-choose-friends-' + inviteAction,
                                            selected_friends_id: 'selected-friends-' + inviteAction,
                                            friend_input: fInput,
                                            instructions: addInstructions}); 
        }

        function _appendFriendSelector(elemSelector) {
            elemSelector.append(_friendSelectorHTML());
            $('#selected-friends-' + inviteAction).on("click", ".invitation a", removeInvitation);
            $('#btn-choose-friends-' + inviteAction).click(function(){
                var obj = {};
                invitedFriends.map(function(uid) { obj[uid] = true; });
                friendSelectorDialog.showDialog(obj);
            });
            if ('update' == inviteAction) {
                $(friendInput).hide();
            }
        };

        this.initialize = function(friendSelectorDialogInstance) {
            friendSelectorDialog = friendSelectorDialogInstance;
            return this;
        };

        return this;
    };

})(window,jQuery);