/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
*/

describe("channel", function () {
    var channel = require('cordova/channel'),
        multiChannel,
        stickyChannel;

    function callCount(spy) {
        return spy.argsForCall.length;
    }
    function expectCallCount(spy, count) {
        expect(callCount(spy)).toEqual(count);
    }
    beforeEach(function() {
        multiChannel = channel.create('multiChannel');
        stickyChannel = channel.createSticky('stickyChannel');
    });

    describe("subscribe method", function() {
        it("should throw an exception if no arguments are provided", function() {
            expect(function() {
                multiChannel.subscribe();
            }).toThrow();

            expect(function() {
                multiChannel.subscribe(null);
            }).toThrow();

            expect(function() {
                multiChannel.subscribe(undefined);
            }).toThrow();
        });
        it("should accept a function or an EventListener object implementing the handleEvent interface", function() {
            expect(function() {
                multiChannel.subscribe(function () {});
            }).not.toThrow();

            expect(function() {
                multiChannel.subscribe({handleEvent: function () {}});
            }).not.toThrow();

            expect(function() {
                multiChannel.subscribe({apply:function(){},call:function(){}});
            }).toThrow();
        });
        it("should not change number of handlers if no function is provided", function() {
            var initialLength = multiChannel.numHandlers;

            try {
                multiChannel.subscribe();
            } catch(e) {}

            expect(multiChannel.numHandlers).toEqual(initialLength);

            try {
                multiChannel.subscribe(null);
            } catch(e) {}

            expect(multiChannel.numHandlers).toEqual(initialLength);
        });
        it("should not change number of handlers when subscribing same function multiple times", function() {
            var handler = function(){};

            multiChannel.subscribe(handler);
            multiChannel.subscribe(handler);
            stickyChannel.subscribe(handler);
            stickyChannel.subscribe(handler);

            expect(multiChannel.numHandlers).toEqual(1);
            expect(stickyChannel.numHandlers).toEqual(1);
        });
    });

    describe("unsubscribe method", function() {
        it("should throw an exception if no arguments are provided", function() {
            expect(function() {
                multiChannel.unsubscribe();
            }).toThrow();

            expect(function() {
                multiChannel.unsubscribe(null);
            }).toThrow();
        });
        it("should accept a function or an EventListener object implementing the handleEvent interface", function() {
            expect(function() {
                multiChannel.unsubscribe(function () {});
            }).not.toThrow();

            expect(function() {
                multiChannel.unsubscribe({handleEvent: function () {}});
            }).not.toThrow();

            expect(function() {
                multiChannel.unsubscribe({apply:function(){},call:function(){}});
            }).toThrow();
        });
        it("should not decrement numHandlers if unsubscribing something that does not exist", function() {
            multiChannel.subscribe(function() {});
            multiChannel.unsubscribe(function() {});
            expect(multiChannel.numHandlers).toEqual(1);
        });
        it("should change the handlers length appropriately", function() {
            var firstHandler = function() {};
            var secondHandler = function() {};
            var thirdHandler = function() {};

            multiChannel.subscribe(firstHandler);
            multiChannel.subscribe(secondHandler);
            multiChannel.subscribe(thirdHandler);
            expect(multiChannel.numHandlers).toEqual(3);

            multiChannel.unsubscribe(thirdHandler);
            expect(multiChannel.numHandlers).toEqual(2);

            multiChannel.unsubscribe(firstHandler);
            multiChannel.unsubscribe(secondHandler);

            expect(multiChannel.numHandlers).toEqual(0);
        });
        it("should not decrement handlers length more than once if unsubscribing a single handler", function() {
            var firstHandler = function(){};
            multiChannel.subscribe(firstHandler);

            expect(multiChannel.numHandlers).toEqual(1);

            multiChannel.unsubscribe(firstHandler);
            multiChannel.unsubscribe(firstHandler);
            multiChannel.unsubscribe(firstHandler);
            multiChannel.unsubscribe(firstHandler);

            expect(multiChannel.numHandlers).toEqual(0);
        });
        it("should not unregister a function registered with a different handler", function() {
            var cHandler = function(){};
            var c2Handler = function(){};
            var c2 = channel.create('jables');
            multiChannel.subscribe(cHandler);
            c2.subscribe(c2Handler);

            expect(multiChannel.numHandlers).toEqual(1);
            expect(c2.numHandlers).toEqual(1);

            multiChannel.unsubscribe(c2Handler);
            c2.unsubscribe(cHandler);

            expect(multiChannel.numHandlers).toEqual(1);
            expect(c2.numHandlers).toEqual(1);
        });
    });

    function commonFireTests(multi) {
        it("should fire all subscribed handlers", function() {
            var testChannel = multi ? multiChannel : stickyChannel;
            var handler = jasmine.createSpy();
            var anotherOne = jasmine.createSpy();

            testChannel.subscribe(handler);
            testChannel.subscribe(anotherOne);

            testChannel.fire();

            expectCallCount(handler, 1);
            expectCallCount(anotherOne, 1);
        });
        it("should pass params to handlers", function() {
            var testChannel = multi ? multiChannel : stickyChannel;
            var handler = jasmine.createSpy();

            testChannel.subscribe(handler);

            testChannel.fire(1, 2, 3);
            expect(handler.argsForCall[0]).toEqual({0:1, 1:2, 2:3});
        });
        it("should not fire a handler that was unsubscribed", function() {
            var testChannel = multi ? multiChannel : stickyChannel;
            var handler = jasmine.createSpy();
            var anotherOne = jasmine.createSpy();

            testChannel.subscribe(handler);
            testChannel.subscribe(anotherOne);
            testChannel.unsubscribe(handler);

            testChannel.fire();

            expectCallCount(handler, 0);
            expectCallCount(anotherOne, 1);
        });
        it("should not fire a handler more than once if it was subscribed more than once", function() {
            var testChannel = multi ? multiChannel : stickyChannel;
            var handler = jasmine.createSpy();

            testChannel.subscribe(handler);
            testChannel.subscribe(handler);
            testChannel.subscribe(handler);

            testChannel.fire();

            expectCallCount(handler, 1);
        });
        it("handler should be called when subscribed, removed, and subscribed again", function() {
            var testChannel = multi ? multiChannel : stickyChannel;
            var handler = jasmine.createSpy();

            testChannel.subscribe(handler);
            testChannel.unsubscribe(handler);
            testChannel.subscribe(handler);

            testChannel.fire();

            expectCallCount(handler, 1);
        });
        it("should not prevent a callback from firing when it is removed during firing.", function() {
            var testChannel = multi ? multiChannel : stickyChannel;
            var handler = jasmine.createSpy().andCallFake(function() { testChannel.unsubscribe(handler2); });
            var handler2 = jasmine.createSpy();
            testChannel.subscribe(handler);
            testChannel.subscribe(handler2);
            testChannel.fire();
            expectCallCount(handler, 1);
            expectCallCount(handler2, 1);
        });
    }
    describe("fire method for sticky channels", function() {
        commonFireTests(false);
        it("should instantly trigger the callback if the event has already been fired", function () {
            var before = jasmine.createSpy('before'),
                after = jasmine.createSpy('after');

            stickyChannel.subscribe(before);
            stickyChannel.fire(1, 2, 3);
            stickyChannel.subscribe(after);

            expectCallCount(before, 1);
            expectCallCount(after, 1);
            expect(after.argsForCall[0]).toEqual({0:1, 1:2, 2:3});
        });
        it("should instantly trigger the callback if the event is currently being fired.", function () {
            var handler1 = jasmine.createSpy().andCallFake(function() { stickyChannel.subscribe(handler2); }),
                handler2 = jasmine.createSpy().andCallFake(function(arg1) { expect(arg1).toEqual('foo');});

            stickyChannel.subscribe(handler1);
            stickyChannel.fire('foo');

            expectCallCount(handler2, 1);
        });
        it("should unregister all handlers after being fired.", function() {
            var handler = jasmine.createSpy();
            stickyChannel.subscribe(handler);
            stickyChannel.fire();
            stickyChannel.fire();
            expectCallCount(handler, 1);
        });
    });
    describe("fire method for multi channels", function() {
        commonFireTests(true);
        it("should not trigger the callback if the event has already been fired", function () {
            var before = jasmine.createSpy('before'),
                after = jasmine.createSpy('after');

            multiChannel.subscribe(before);
            multiChannel.fire();
            multiChannel.subscribe(after);

            expectCallCount(before, 1);
            expectCallCount(after, 0);
        });
        it("should not trigger the callback if the event is currently being fired.", function () {
            var handler1 = jasmine.createSpy().andCallFake(function() { multiChannel.subscribe(handler2); }),
                handler2 = jasmine.createSpy();

            multiChannel.subscribe(handler1);
            multiChannel.fire();
            multiChannel.fire();

            expectCallCount(handler1, 2);
            expectCallCount(handler2, 1);
        });
        it("should not unregister handlers after being fired.", function() {
            var handler = jasmine.createSpy();
            multiChannel.subscribe(handler);
            multiChannel.fire();
            multiChannel.fire();
            expectCallCount(handler, 2);
        });
    });
    describe("channel.join()", function() {
        it("should be called when all functions start unfired", function() {
            var handler = jasmine.createSpy(),
                stickyChannel2 = channel.createSticky('stickyChannel');
            channel.join(handler, [stickyChannel, stickyChannel2]);
            expectCallCount(handler, 0);
            stickyChannel.fire();
            expectCallCount(handler, 0);
            stickyChannel2.fire();
            expectCallCount(handler, 1);
        });
        it("should be called when one functions start fired", function() {
            var handler = jasmine.createSpy(),
                stickyChannel2 = channel.createSticky('stickyChannel');
            stickyChannel.fire();
            channel.join(handler, [stickyChannel, stickyChannel2]);
            expectCallCount(handler, 0);
            stickyChannel2.fire();
            expectCallCount(handler, 1);
        });
        it("should be called when all functions start fired", function() {
            var handler = jasmine.createSpy(),
                stickyChannel2 = channel.createSticky('stickyChannel');
            stickyChannel.fire();
            stickyChannel2.fire();
            channel.join(handler, [stickyChannel, stickyChannel2]);
            expectCallCount(handler, 1);
        });
        it("should throw if a channel is not sticky", function() {
            expect(function() {
                channel.join(function(){}, [stickyChannel, multiChannel]);
            }).toThrow();
        });
    });
    describe("onHasSubscribersChange", function() {
        it("should be called only when the first subscriber is added and last subscriber is removed.", function() {
            var handler = jasmine.createSpy().andCallFake(function() {
                if (callCount(handler) == 1) {
                    expect(this.numHandlers).toEqual(1);
                } else {
                    expect(this.numHandlers).toEqual(0);
                }
            });
            multiChannel.onHasSubscribersChange = handler;
            function foo1() {}
            function foo2() {}
            multiChannel.subscribe(foo1);
            multiChannel.subscribe(foo2);
            multiChannel.unsubscribe(foo1);
            multiChannel.unsubscribe(foo2);
            expectCallCount(handler, 2);
        });
    });
});
