(function(context, $) {

    describe("SessionLatency", function() {

        var sessionLatency; // Instance of SessionLatency class for test

        fakeJamClient = {
            TestLatency: function() {}     // Will be overridden by test cases
        };

        var sessions = [
            {id: "1", participants: [ { client_id: "1", ip_address: "1.1.1.1" } ] },
            {id: "2", participants: [ { client_id: "2", ip_address: "1.1.1.2" } ] },
            {id: "3", participants: [ { client_id: "3", ip_address: "1.1.1.3", user: {is_friend:true} } ] },
            {id: "4", participants: [ { client_id: "4", ip_address: "1.1.1.4" } ], invitations: [{id:'1', sender_id:'1'}] },
            {id: "5", participants: [
                        { client_id: "5", ip_address: "1.1.1.5" },
                        { client_id: "6", ip_address: "1.1.1.6" },
                        { client_id: "7", ip_address: "1.1.1.7" }
                    ]}
        ];
        var callCount = 0;
        var testLatencyResponses = {
            "1": {clientID: "1", latency: 35},
            "2": {clientID: "2", latency: 50},
            "3": {clientID: "3", latency: 150},
            "4": {clientID: "4", latency: 200},
            "5": {clientID: "5", latency: 100},
            "6": {clientID: "6", latency: 10},
            "7": {clientID: "7", latency: 10}
        };

        beforeEach(function() {
            callCount = 0;
            sessionLatency = new context.JK.SessionLatency(fakeJamClient);
            spyOn(fakeJamClient, "TestLatency").andCallFake(function(clientID, callbackName) {

                var js = callbackName + '(' + JSON.stringify(testLatencyResponses[clientID]) + ');';
                eval(js);
                //callback(testLatencyResponses[client.id]);
                callCount++;
            });
        });

        describe("SessionPings", function() {
            it("should call jamClient.TestLatency and compute new average", function() {
                sessionLatency.sessionPings(sessions[0]);
                expect(fakeJamClient.TestLatency).toHaveBeenCalled();
                var info = sessionLatency.sessionInfo(sessions[0].id);
                expect(info.averageLatency).toEqual(35);
            });

            it("should average multiple client pings", function() {
                sessionLatency.sessionPings(sessions[4]);
                var info = sessionLatency.sessionInfo(sessions[4].id);
                expect(info.averageLatency).toEqual(40);
            });

        });

        describe("SessionSorting", function() {
            beforeEach(function() {
                $.each(sessions, function(index, session) {
                    sessionLatency.sessionPings(session);
                });
            });

            it("should return >= 2 for invited sessions", function() {
                var score = sessionLatency.getSortScore('4');
                expect(score >= 2).toBeTruthy();
            });

            it("should return < 2, >= 1 for friend sessions", function() {
                var score = sessionLatency.getSortScore('3');
                expect(score < 2).toBeTruthy();
                expect(score >= 1).toBeTruthy();
            });
            it("should return < 1 for unknown sessions", function() {
                var score = sessionLatency.getSortScore('2');
                expect(score < 1).toBeTruthy();
            });
            it("should return 1/AvgLatency for unknown pingable sessions", function() {
                var score = sessionLatency.getSortScore('2');
                expect(score).toEqual(0.02);
            });
            it("should return higher sort value for lower latency", function() {
                var score1 = sessionLatency.getSortScore('1');
                var score2 = sessionLatency.getSortScore('2');
                expect(score1).toBeGreaterThan(score2);
            });
        });

        describe("Register for Events", function() {
            it("should register successfully", function() {
                var cb = jasmine.createSpy();
                sessionLatency.subscribe('test', cb);
            });
            it("should invoke callback on latency result", function() {
                var cb = jasmine.createSpy("Latency Subscription Callback");
                sessionLatency.subscribe('test', cb);
                $.each(sessions, function(index, session) {
                    sessionLatency.sessionPings(session);
                });
                expect(cb).toHaveBeenCalled();
            });
            it("should not add same listener twice", function() {
                var cb = jasmine.createSpy();
                sessionLatency.subscribe('test', cb);
                sessionLatency.subscribe('test', cb);
                sessionLatency.subscribe('test', cb);
                $.each(sessions, function(index, session) {
                    sessionLatency.sessionPings(session);
                });
                expect(cb.callCount).toEqual(7); // 7 clients to ping, once.
            });
        });

    });


 })(window, jQuery);