/**
 * Common utility functions.
 */
(function(context,$) {

    "use strict";

    context.JK = context.JK || {};
    var logger = context.JK.logger;

    // types
    var registrationTypes = {
        native : "Native",
        facebook : "Facebook"
    };

    var sessionCreationTypes = {
        create : "Create",
        join : "Join"
    };

    var invitationTypes = {
        email : "Email",
        facebook : "Facebook",
        google : "Google"
    };

    var friendConnectTypes = {
        request : "Request",
        accept : "Accept"
    };

    var categories = {
        register : "Register",
        download : "DownloadClient",
        audioTest : "AudioTest",
        sessionCount : "SessionCount",
        sessionMusicians : "SessionMusicians",
        invite : "Invite",
        findSession : "FindSession",
        friendConnect : "Connect"

    };

    function translatePlatformForGA(platform) {
        assertOneOf(platform, context.JK.OS);

        if(platform == context.JK.OS.WIN32) {
            return "Windows";
        }
        if(platform == context.JK.OS.OSX) {
            return "Mac";
        }
        if(platform == context.JK.OS.UNIX) {
            return "Unix";
        }
    }

    function assertBoolean(value) {
        if(typeof value != 'boolean') {
            throw "value is not a boolean: " + JSON.stringify(value);
        }
    }

    function assertNumber(value) {
        if(typeof value != 'number') {
            throw "value is not a number: " + JSON.stringify(value);
        }
    }

    function assertOneOf(enumValue, enums){
        var found = false;
        for (var key in enums) {
            if (enumValue == enums[key]) {
                found = true;
                break;
            }
        }
        if(!found) {
            throw "unable to find enum: " + enumValue + " in: " + JSON.stringify(enums);
        }
    }

    function trackRegister(asMusician, registrationType) {
        assertBoolean(asMusician);
        assertOneOf(registrationType, registrationTypes);

        var action = asMusician ? "Musician" : "Fan";

        context.ga('send', 'event', categories.register, action, registrationType);
    }

    function trackDownload(platform) {
       var normalizedPlatform = translatePlatformForGA(platform);

       context.ga('send', 'event', categories.download, normalizedPlatform);
    }

    function trackFTUECompletion(state, platform) {
        var normalizedPlatform = translatePlatformForGA(platform);

        context.ga('send', 'event', categories.audioTest, state, normalizedPlatform);
    }

    function trackSessionCount(musicianAccess, fanAccess, invitationCount) {
        assertBoolean(musicianAccess);
        assertBoolean(fanAccess);
        assertNumber(invitationCount);

        var gaMusicianAccess = musicianAccess ? "MusicianPublic" : "MusicianPrivate";
        var gaFanAccess = fanAccess ? "FanPublic" : "FanPrivate";

        context.ga('send', 'event', categories.sessionCount, gaMusicianAccess, gaFanAccess, invitationCount);
    }

    function trackSessionMusicians(joinOrCreate) {
        assertOneOf(joinOrCreate, sessionCreationTypes);

        context.ga('send', 'event', categories.sessionMusicians, joinOrCreate);
    }

    function trackServiceInvitations(invitationType, numInvited) {
        assertOneOf(invitationType, invitationTypes);
        assertNumber(numInvited);

        context.ga('send', 'event', categories.invite, invitationType, numInvited);
    }

    function trackFindSessions(numSessionsFound) {
        assertNumber(numSessionsFound);

        var sessionCountRollup = "n/a";
        if(numSessionsFound === 0) {
            sessionCountRollup = "0";
        }
        else if(numSessionsFound >= 1 && numSessionsFound <= 5) {
            sessionCountRollup = "1-5";
        }
        else if(numSessionsFound >= 6 && numSessionsFound <= 10) {
            sessionCountRollup = "6-10";
        }
        else {
            sessionCountRollup = "10+";
        }

        context.ga('send', 'event', categories.findSession, sessionCountRollup, numSessionsFound);
    }

    // if you want to pass in no title, either omit it from the arg list when u invoke virtualPageView, or pass in undefined, NOT null
    function virtualPageView(page, title) {

        context.ga('send', 'pageview', {
            'page': page,
            'title': title
        });
    }

    function trackFriendConnect(friendConnectType) {
        assertOneOf(friendConnectType, friendConnectTypes);

        context.ga('send', 'event', categories.friendConnect, friendConnectType);
    }

    var GA = {};
    GA.SessionCreationTypes = sessionCreationTypes;
    GA.InvitationTypes = invitationTypes;
    GA.FriendConnectTypes = friendConnectTypes;
    GA.trackRegister = trackRegister;
    GA.trackDownload = trackDownload;
    GA.trackFTUECompletion = trackFTUECompletion;
    GA.trackSessionCount = trackSessionCount;
    GA.trackSessionMusicians = trackSessionMusicians;
    GA.trackServiceInvitations = trackServiceInvitations;
    GA.trackFindSessions = trackFindSessions;
    GA.virtualPageView = virtualPageView;
    GA.trackFriendConnect = trackFriendConnect;

    context.JK.GA = GA;

})(window,jQuery);