(function(requirejs, require, define, undefined) {
    require(
['video/00_resizer.js'],
function(Resizer) {
    describe('Resizer', function() {
        var html = [
                '<div ' +
                    'class="rszr-wrapper" ' +
                    'style="width:200px; height: 200px;"' +
                '>',
                '<div ' +
                        'class="rszr-el" ' +
                        'style="width:100px; height: 150px;"' +
                    '>',
                'Content',
                '</div>',
                '</div>'
            ].join(''),
            config, $container, $element;

        beforeEach(function() {
            setFixtures(html);

            $container = $('.rszr-wrapper');
            $element = $('.rszr-el');
            config = {
                container: $container,
                element: $element
            };

            spyOn(console, 'log');
        });

        it('When Initialize without required parameters, log message is shown',
            function() {
                new Resizer({ });
                expect(console.log).toHaveBeenCalled();
            }
        );

        it('`alignByWidthOnly` works correctly', function() {
            var resizer = new Resizer(config).alignByWidthOnly(),
                expectedWidth = $container.width(),
                realWidth = $element.width();

            expect(realWidth).toBe(expectedWidth);
        });

        it('`alignByHeightOnly` works correctly', function() {
            var resizer = new Resizer(config).alignByHeightOnly(),
                expectedHeight = $container.height(),
                realHeight = $element.height();

            expect(realHeight).toBe(expectedHeight);
        });

        it('`align` works correctly', function() {
            var resizer = new Resizer(config).align(),
                expectedHeight = $container.height(),
                realHeight = $element.height(),
                expectedWidth = 50;

            // containerRatio >= elementRatio
            expect(realHeight).toBe(expectedHeight);

            // containerRatio < elementRatio
            $container.width(expectedWidth);
            resizer.align();
            realWidth = $element.width();

            expect(realWidth).toBe(expectedWidth);
        });

        it('`setMode` works correctly', function() {
            var resizer = new Resizer(config).setMode('height'),
                expectedHeight = $container.height(),
                realHeight = $element.height(),
                expectedWidth = 50;

            // containerRatio >= elementRatio
            expect(realHeight).toBe(expectedHeight);

            // containerRatio < elementRatio
            $container.width(expectedWidth);
            resizer.setMode('width');
            realWidth = $element.width();

            expect(realWidth).toBe(expectedWidth);
        });

        it('`setElement` works correctly', function() {
            $container.append('<div ' +
                'id="Another-el" ' +
                'style="width:100px; height: 150px;"' +
            '>');

            var $newElement = $('#Another-el'),
                expectedHeight = $container.height();

            new Resizer(config).setElement($newElement).alignByHeightOnly();
            expect($element.height()).not.toBe(expectedHeight);
            expect($newElement.height()).toBe(expectedHeight);
        });

        describe('Callbacks', function() {
            var resizer,
                spiesList = [];

            beforeEach(function() {
                var spiesCount = _.range(3);

                spiesList = $.map(spiesCount, function() {
                    return jasmine.createSpy();
                });

                resizer = new Resizer(config);
            });


            it('callbacks are called', function() {
                $.each(spiesList, function(index, spy) {
                    resizer.callbacks.add(spy);
                });

                resizer.align();

                $.each(spiesList, function(index, spy) {
                    expect(spy).toHaveBeenCalled();
                });
            });

            it('callback called just once', function() {
                resizer.callbacks.once(spiesList[0]);

                resizer
                    .align()
                    .alignByHeightOnly();

                expect(spiesList[0].calls.count()).toEqual(1);
            });

            it('all callbacks are removed', function() {
                $.each(spiesList, function(index, spy) {
                    resizer.callbacks.add(spy);
                });

                resizer.callbacks.removeAll();
                resizer.align();

                $.each(spiesList, function(index, spy) {
                    expect(spy).not.toHaveBeenCalled();
                });
            });

            it('specific callback is removed', function() {
                $.each(spiesList, function(index, spy) {
                    resizer.callbacks.add(spy);
                });

                resizer.callbacks.remove(spiesList[1]);
                resizer.align();

                expect(spiesList[1]).not.toHaveBeenCalled();
            });

            it(
                'Error message is shown when wrong argument type is passed',
                function() {
                    var methods = ['add', 'once'],
                        errorMessage = '[Video info]: TypeError: Argument is not a function.',
                        arg = {};

                    spyOn(console, 'error');

                    $.each(methods, function(index, methodName) {
                        resizer.callbacks[methodName](arg);
                        expect(console.error).toHaveBeenCalledWith(errorMessage);
                     // reset spy
                        console.log.calls.reset();
                    });
                });
        });

        describe('Delta', function() {
            var resizer;

            beforeEach(function() {
                resizer = new Resizer(config);
            });

            it('adding delta align correctly by height', function() {
                var delta = 100,
                    expectedHeight = $container.height() + delta,
                    realHeight;

                resizer
                    .delta.add(delta, 'height')
                    .setMode('height');

                realHeight = $element.height();

                expect(realHeight).toBe(expectedHeight);
            });

            it('adding delta align correctly by width', function() {
                var delta = 100,
                    expectedWidth = $container.width() + delta,
                    realWidth;

                resizer
                    .delta.add(delta, 'width')
                    .setMode('width');

                realWidth = $element.width();

                expect(realWidth).toBe(expectedWidth);
            });

            it('substract delta align correctly by height', function() {
                var delta = 100,
                    expectedHeight = $container.height() - delta,
                    realHeight;

                resizer
                    .delta.substract(delta, 'height')
                    .setMode('height');

                realHeight = $element.height();

                expect(realHeight).toBe(expectedHeight);
            });

            it('substract delta align correctly by width', function() {
                var delta = 100,
                    expectedWidth = $container.width() - delta,
                    realWidth;

                resizer
                    .delta.substract(delta, 'width')
                    .setMode('width');

                realWidth = $element.width();

                expect(realWidth).toBe(expectedWidth);
            });

            it('reset delta', function() {
                var delta = 100,
                    expectedWidth = $container.width(),
                    realWidth;

                resizer
                    .delta.substract(delta, 'width')
                    .delta.reset()
                    .setMode('width');

                realWidth = $element.width();

                expect(realWidth).toBe(expectedWidth);
            });
        });
    });
});
}(RequireJS.requirejs, RequireJS.require, RequireJS.define));
