(function(context,$) {

    "use strict";

    context.JK = context.JK || {};
    context.JK.FindSessionScreen = function(app) {
        var CATEGORY = {
            INVITATION : {index: 0, id: "table#sessions-invitations"},
            FRIEND : {index: 1, id: "table#sessions-friends"},
            OTHER : {index: 2, id: "table#sessions-other"}
        };

        var logger = context.JK.logger;
        var sessionLatency;
        var sessions = {};
        var invitationSessionGroup = {};
        var friendSessionGroup = {};
        var otherSessionGroup = {};
        var sessionCounts = [0, 0, 0];
        var sessionList;

        // for unit tests
        function getCategoryEnum() {
            return CATEGORY;
        }

        function removeSpinner() {
            $('<div[layout-id=findSession] .content .spinner').remove();// remove any existing spinners

        }

        function addSpinner() {
            removeSpinner();
            $('<div[layout-id=findSession] .content').append('<div class="spinner spinner-large"></div>')

        }

        function loadSessions(queryString) {

            addSpinner();

            // squelch nulls and undefines
            queryString = !!queryString ? queryString : "";

            $.ajax({
                type: "GET",
                url: "/api/sessions?" + queryString,
                async: true,
                success: afterLoadSessions,
                complete: removeSpinner,
                error: app.ajaxError
            });
        }

        function search() {
            logger.debug("Searching for sessions...");
            clearResults();
            var queryString = '';

            // musician filter
            var musicians = getSelectedMusicians();
            if (musicians !== null && musicians.length > 0) {
                queryString += "participants=" + musicians.join(',');
            }

            // genre filter
            var genres = context.JK.GenreSelectorHelper.getSelectedGenres('#find-session-genre');
            if (genres !== null && genres.length > 0) {
                if (queryString.length > 0) {
                    queryString += "&";
                }

                queryString += "genres=" + genres.join(',');
            }

            // keyword filter
            var keyword = $('#session-keyword-srch').val();
            if (keyword !== null && keyword.length > 0 && keyword !== 'Search by Keyword') {
                if (queryString.length > 0) {
                    queryString += "&";
                }

                queryString += "keyword=" + $('#session-keyword-srch').val();
            }

            loadSessions(queryString);
        }

        function refreshDisplay() {
            var priorVisible;

            var INVITATION = 'div#sessions-invitations';
            var FRIEND = 'div#sessions-friends';
            var OTHER = 'div#sessions-other';

            // INVITATION
            logger.debug("sessionCounts[CATEGORY.INVITATION.index]=" + sessionCounts[CATEGORY.INVITATION.index]);
            if (sessionCounts[CATEGORY.INVITATION.index] === 0) {
                priorVisible = false;
                $(INVITATION).hide();
            }
            else {
                priorVisible = true;
                $(INVITATION).show();
            }

            // FRIEND
            if (!priorVisible) {
                $(FRIEND).removeClass('mt35');
            }

            logger.debug("sessionCounts[CATEGORY.FRIEND.index]=" + sessionCounts[CATEGORY.FRIEND.index]);
            if (sessionCounts[CATEGORY.FRIEND.index] === 0) {
                priorVisible = false;
                $(FRIEND).hide();
            }
            else {
                priorVisible = true;
                $(FRIEND).show();
            }

            // OTHER
            if (!priorVisible) {
                $(OTHER).removeClass('mt35');
            }

            logger.debug("sessionCounts[CATEGORY.OTHER.index]=" + sessionCounts[CATEGORY.OTHER.index]);
            if (sessionCounts[CATEGORY.OTHER.index] === 0) {
                $(OTHER).hide();
            }
            else {
                $(OTHER).show();
            }
        }

        function getSelectedMusicians() {
            var selectedMusicians = [];
            // $('#musician-list-items :checked').each(function() {
            //     selectedMusicians.push($(this).val());
            // });

            var selectedVal = $('#musician-list').val();
            if (selectedVal !== '') {
                selectedMusicians.push(selectedVal);
            }

            return selectedMusicians;
        }

        function afterLoadSessions(sessionList) {

            // display the 'no sessions' banner if appropriate
            var $noSessionsFound = $('#sessions-none-found');
            if(sessionList.length == 0) {
                $noSessionsFound.show();
            }
            else {
                $noSessionsFound.hide();
            }

            startSessionLatencyChecks(sessionList);

            context.JK.GA.trackFindSessions(sessionList.length);
        }

        function startSessionLatencyChecks(sessionList) {
            logger.debug("Starting latency checks on " + sessionList.length + " sessions");

            sessionLatency.subscribe(app.clientId, latencyResponse);
            $.each(sessionList, function(index, session) {
                sessions[session.id] = session;
                sessionLatency.sessionPings(session);
            });
        }

        function containsInvitation(session) {
            var i, invitation = null;
            // user has invitations for this session
            for (i=0; i < session.invitations.length; i++) {
                invitation = session.invitations[i];
                // session contains an invitation for this user
                if (invitation.receiver_id == context.JK.currentUserId) {
                    return true;
                }
            }

            return false;
        }

        function containsFriend(session) {
            var i, participant = null;

            for (i=0; i < session.participants.length; i++) {
                participant = session.participants[i];
                // this session participant is a friend
                if (participant !== null && participant !== undefined && participant.user.is_friend) {
                    return true;
                }
            }
            return false;
        }

        function latencyResponse(sessionId) {
            logger.debug("Received latency response for session " + sessionId);
            renderSession(sessionId);
        }

        /**
        * Not used normally. Allows modular unit testing
        * of the renderSession method without having to do
        * as much heavy setup.
        */
        function setSession(session) {
            invitationSessionGroup[session.id] = session;
        }

        /**
        * Render a single session line into the table.
        * It will be inserted at the appropriate place according to the
        * sortScore in sessionLatency.
        */
        function renderSession(sessionId) {
            // store session in the appropriate bucket and increment category counts
            var session = sessions[sessionId];
            if (containsInvitation(session)) {
                invitationSessionGroup[sessionId] = session;
                sessionCounts[CATEGORY.INVITATION.index]++;
            }
            else if (containsFriend(session)) {
                friendSessionGroup[sessionId] = session;
                sessionCounts[CATEGORY.FRIEND.index]++;
            }
            else {
                otherSessionGroup[sessionId] = session;
                sessionCounts[CATEGORY.OTHER.index]++;
            }

            // hack to prevent duplicate rows from being rendered when filtering
            var sessionAlreadyRendered = false;
            var $tbGroup;

            logger.debug('Rendering session ID = ' + sessionId);

            if (invitationSessionGroup[sessionId] != null) {
                $tbGroup = $(CATEGORY.INVITATION.id);

                if ($("table#sessions-invitations tr[id='" + sessionId + "']").length > 0) {
                    sessionAlreadyRendered = true;
                }
            }
            else if (friendSessionGroup[sessionId] != null) {;
                $tbGroup = $(CATEGORY.FRIEND.id);

                if ($("table#sessions-friends tr[id='" + sessionId + "']").length > 0) {
                    sessionAlreadyRendered = true;
                }
            }
            else if (otherSessionGroup[sessionId] != null) {
                $tbGroup = $(CATEGORY.OTHER.id);

                if ($("table#sessions-other tr[id='" + sessionId + "']").length > 0) {
                    sessionAlreadyRendered = true;
                }
            }
            else {
                logger.debug('ERROR: No session with ID = ' + sessionId + ' found.');
                return;
            }

            if (!sessionAlreadyRendered) {
                var row = sessionList.renderSession(session, sessionLatency, $tbGroup, $('#template-session-row').html(), $('#template-musician-info').html(),
                                            // populate the musician filter with musicians that haven't already been added
                                            function(musicianArray) {
                                                var template = $('#template-musician-option').html();
                                                $.each(musicianArray, function(index, val) {
                                                    // check if this musician is already in the filter
                                                    if ( $('#musician-list option[value=' + val.id + ']').length === 0 ) {
                                                        var musicianOptionHtml = context.JK.fillTemplate(template, {value: val.id, label: val.name});
                                                        $('#musician-list').append(musicianOptionHtml);
                                                    }
                                                });
                                            });
            }

            refreshDisplay();
        }

        // TODO: refactor this and GenreSelector into common code
        // function toggleMusicianBox() {
        //     var boxHeight = $('#musician-list').css("height");
        //     // TODO: clean this up (check class name of arrow to determine current state)
        //     if (boxHeight == "20px") {
        //         $('#musician-list').css({height: "auto"});
        //         $('#musician-list-arrow').removeClass("arrow-down").addClass("arrow-up");

        //     }
        //     else {
        //         $('#musician-list').css({height: "20px"});
        //         $('#musician-list-arrow').removeClass("arrow-up").addClass("arrow-down");
        //     }
        // }

        function beforeShow(data) {
            context.JK.GenreSelectorHelper.render('#find-session-genre');
        }

        function afterShow(data) {
            clearResults();
            refreshDisplay();
            loadSessions();
        }

        function clearResults() {
            $('table#sessions-invitations').children(':not(:first-child)').remove();
            $('table#sessions-friends').children(':not(:first-child)').remove();
            $('table#sessions-other').children(':not(:first-child)').remove();

            sessionCounts = [0, 0, 0];

            sessions = {};
            invitationSessionGroup = {};
            friendSessionGroup = {};
            otherSessionGroup = {};
        }

        function deleteSession(evt) {
            var sessionId = $(evt.currentTarget).attr("action-id");
            if (sessionId) {
                $.ajax({
                    type: "DELETE",
                    url: "/api/sessions/" + sessionId,
                    error: app.ajaxError
                }).done(loadSessions);
            }
        }

        function events() {
            //$('#findSession-tableBody').on("click", '[action="delete"]', deleteSession);
            // $('#musician-list-header').on("click", toggleMusicianBox);
            // $('#musician-list-arrow').on("click", toggleMusicianBox);

            $('#session-keyword-srch').focus(function() {
                $(this).val('');
            });

            $('#btn-refresh').on("click", search);
        }

        /**
        * Initialize, providing an instance of the SessionLatency class.
        */
        function initialize(latency) {

            var screenBindings = {
                'beforeShow': beforeShow,
                'afterShow': afterShow
            };
            app.bindScreen('findSession', screenBindings);

            if (latency) {
                sessionLatency = latency;
            }
            else {
                logger.warn("No sessionLatency provided.");
            }

            sessionList = new context.JK.SessionList(app);

            events();
        }

        this.initialize = initialize;
        this.renderSession = renderSession;
        this.afterShow = afterShow;

        // Following exposed for easier testing.
        this.setSession = setSession;
        this.clearResults = clearResults;
        this.getCategoryEnum = getCategoryEnum;

        return this;
    };

 })(window,jQuery);