jest.dontMock('../glop.js');

describe('glop', function () {
	var glop;

	beforeEach(function () {
		glop = require('../glop.js');
	});

	it('should register and call an event handler', function () {
		glop.setup(['TEST_EVENT']);

		var spy = jest.genMockFn();
		glop.on('TEST_EVENT', spy);

		glop.emit('TEST_EVENT');
		expect(spy).toBeCalled();
	});

	it('should pass arguments to an event handler', function () {
		glop.setup(['TEST_EVENT']);

		var spy = jest.genMockFn();
		glop.on('TEST_EVENT', spy);

		glop.emit('TEST_EVENT', 'value1', 'value2', { value: 3 }, 4);
		expect(spy).toBeCalledWith('value1', 'value2', { value: 3 }, 4);
	});

	it('should register and call multi-bound event handlers', function () {
		glop.setup(['TEST_EVENT1', 'TEST_EVENT2', 'TEST_EVENT3']);
		var spy = jest.genMockFn();

		glop.on(['TEST_EVENT1','TEST_EVENT2','TEST_EVENT3'], spy);

		glop.emit('TEST_EVENT1');
		glop.emit('TEST_EVENT2');
		glop.emit('TEST_EVENT3');

		expect(spy.mock.calls.length).toEqual(3);
	});

	it('should only call the right event handler', function () {
		glop.setup(['TEST_EVENT1', 'TEST_EVENT2']);

		var spy1 = jest.genMockFn();
		var spy2 = jest.genMockFn();

		glop.on('TEST_EVENT1', spy1);
		glop.on('TEST_EVENT2', spy2);

		glop.emit('TEST_EVENT1');

		expect(spy1).toBeCalled();
		expect(spy2).not.toBeCalled();
	});

	it('should return bound emitter function', function () {
		glop.setup(['TEST_EVENT']);

		var spy = jest.genMockFn();
		glop.on('TEST_EVENT', spy);

		var emitter = glop.emitter('TEST_EVENT');
		emitter('value');

		expect(spy).toBeCalledWith('value');
	});

	it('should invoke handler repeatedly', function () {
		glop.setup(['TEST_EVENT']);
		var spy = jest.genMockFn();

		glop.on('TEST_EVENT', spy);
		for (var i = 0; i < 10; i++) { glop.emit('TEST_EVENT'); }

		expect(spy.mock.calls.length).toEqual(10);
	});

	it('should invoke handler only once when registered as "one"', function () {
		glop.setup(['TEST_EVENT']);
		var spy = jest.genMockFn();

		glop.one('TEST_EVENT', spy);
		for (var i = 0; i < 10; i++) { glop.emit('TEST_EVENT'); }

		expect(spy.mock.calls.length).toEqual(1);
	});

	it('should replace existing handlers on "only"', function () {
		glop.setup(['TEST_EVENT']);

		var spy1 = jest.genMockFn();
		var spy2 = jest.genMockFn();
		var spy3 = jest.genMockFn();

		glop.on('TEST_EVENT', spy1);
		glop.on('TEST_EVENT', spy2);
		glop.only('TEST_EVENT', spy3);

		glop.emit('TEST_EVENT');

		expect(spy1).not.toBeCalled();
		expect(spy2).not.toBeCalled();
		expect(spy3).toBeCalled();
	});

	it('should replace existing handlers and only call once on "onely"', function () {
		glop.setup(['TEST_EVENT']);

		var spy1 = jest.genMockFn();
		var spy2 = jest.genMockFn();
		var spy3 = jest.genMockFn();

		glop.on('TEST_EVENT', spy1);
		glop.on('TEST_EVENT', spy2);
		glop.onely('TEST_EVENT', spy3);

		for (var i = 0; i < 10; i++) { glop.emit('TEST_EVENT'); }

		expect(spy1).not.toBeCalled();
		expect(spy2).not.toBeCalled();

		expect(spy3.mock.calls.length).toEqual(1);
	});

	it('should invoke handler registered as "one" and regular twice at first emit only', function () {
		glop.setup(['TEST_EVENT']);

		var spy = jest.genMockFn();
		glop.one('TEST_EVENT', spy);
		glop.on('TEST_EVENT', spy);

		glop.emit('TEST_EVENT');
		expect(spy.mock.calls.length).toEqual(2);

		glop.emit('TEST_EVENT');
		expect(spy.mock.calls.length).toEqual(3);
	});

	it('should deregister event handlers for specific event if no handler is defined', function () {
		glop.setup(['TEST_EVENT']);

		var spy1 = jest.genMockFn();
		var spy2 = jest.genMockFn();

		glop.one('TEST_EVENT', spy1);
		glop.on('TEST_EVENT', spy2);

		glop.off('TEST_EVENT');

		glop.emit('TEST_EVENT');

		expect(spy1).not.toBeCalled();
		expect(spy2).not.toBeCalled();
	});

	it('should only deregister specific event handler if provided', function () {
		glop.setup(['TEST_EVENT']);

		var spy1 = jest.genMockFn();
		var spy2 = jest.genMockFn();

		glop.on('TEST_EVENT', spy1);
		glop.on('TEST_EVENT', spy2);

		glop.off('TEST_EVENT', spy2);

		glop.emit('TEST_EVENT');

		expect(spy1).toBeCalled();
		expect(spy2).not.toBeCalled();
	});

	it('should not allow handling of unregistered event name', function () {
		glop.setup(['TEST_EVENT']);

		var spy = jest.genMockFn();

		glop.on('not-registered-name', spy);
		glop.emit('not-registered-name');

		expect(spy).not.toBeCalled();
	});

	it('should treat instances separately', function () {
		var instance1 = glop().setup(['TEST_EVENT']);
		var instance2 = glop().setup(['TEST_EVENT']);

		var spy1 = jest.genMockFn();
		var spy2 = jest.genMockFn();

		instance1.on('TEST_EVENT', spy1);
		instance2.on('TEST_EVENT', spy2);

		instance1.emit('TEST_EVENT', 'value');

		expect(spy1).toBeCalled();
		expect(spy2).not.toBeCalled();
	});

	it('should clear handlers on clear', function () {
		var instance = glop().setup(['TEST_EVENT1', 'TEST_EVENT2']);

		var spy1 = jest.genMockFn();
		var spy2 = jest.genMockFn();

		instance.on('TEST_EVENT1', spy1);
		instance.on('TEST_EVENT2', spy2);

		instance.emit('TEST_EVENT1', 'valid emit 1');
		instance.emit('TEST_EVENT2', 'valid emit 2');

		expect(spy1).toBeCalledWith('valid emit 1');
		expect(spy2).toBeCalledWith('valid emit 2');

		instance.clear();

		instance.emit('TEST_EVENT1', 'invalid emit 1');
		instance.emit('TEST_EVENT2', 'invalid emit 2');

		expect(spy1).not.toBeCalledWith('invalid emit 1');
		expect(spy2).not.toBeCalledWith('invalid emit 2');
	});

	it('should not remove event name setup on clear', function () {
		var instance = glop().setup(['TEST_EVENT']);

		instance.clear();

		var spy = jest.genMockFn();
		instance.on('TEST_EVENT', spy);

		instance.emit('TEST_EVENT');

		expect(spy).toBeCalled();
	});

	it('should set log function', function () {
		var instance = glop().setup(['TEST_EVENT']);
		var logger = jest.genMockFn();

		instance.setLogger(logger);
		instance.on('TEST_EVENT', function () {});
		expect(logger).toBeCalled();
	});
});