import './index';
import crudModel from 'core/mocks/crud-model';

describe('component vnZoneCalendar', () => {
    let $scope;
    let controller;

    beforeEach(ngModule('zone'));

    beforeEach(inject(($componentController, $rootScope) => {
        $scope = $rootScope.$new();
        const $element = angular.element(`<vn-zone-calendar></vn-zone-calendar>`);
        controller = $componentController('vnZoneCalendar', {$element, $scope});
        controller.$.model = crudModel;
        controller.zone = {id: 1};
        controller.days = [];
        controller.exclusions = [];
        controller.geoExclusions = [];
    }));

    describe('date() setter', () => {
        it('should set the month property and then call the refreshEvents() method', () => {
            jest.spyOn(controller, 'refreshEvents').mockReturnThis();

            controller.date = Date.vnNew();

            expect(controller.refreshEvents).toHaveBeenCalledWith();
            expect(controller.months.length).toEqual(4);
        });
    });

    describe('step()', () => {
        it('should set the date month to 4 months backwards', () => {
            const now = Date.vnNew();
            now.setDate(15);
            now.setMonth(now.getMonth() - 4);

            controller.step(-1);

            const expectedMonth = now.getMonth();
            const currentMonth = controller.date.getMonth();

            expect(currentMonth).toEqual(expectedMonth);
        });

        it('should set the date month to 4 months forwards', () => {
            const now = Date.vnNew();
            now.setDate(15);
            now.setMonth(now.getMonth() + 4);

            controller.step(1);

            const expectedMonth = now.getMonth();
            const currentMonth = controller.date.getMonth();

            expect(currentMonth).toEqual(expectedMonth);
        });
    });

    describe('data() setter', () => {
        it('should set the events, exclusions and geoExclusions and then call the refreshEvents() method', () => {
            jest.spyOn(controller, 'refreshEvents').mockReturnThis();

            controller.data = {
                exclusions: [{
                    dated: Date.vnNew()
                }],
                events: [{
                    dated: Date.vnNew()
                }],
                geoExclusions: [{
                    dated: Date.vnNew()
                }],
            };

            expect(controller.refreshEvents).toHaveBeenCalledWith();
            expect(controller.events).toBeDefined();
            expect(controller.events.length).toEqual(1);
            expect(controller.exclusions).toBeDefined();
            expect(controller.geoExclusions).toBeDefined();
            expect(Object.keys(controller.exclusions).length).toEqual(1);
        });
    });

    describe('refreshEvents()', () => {
        it('should fill the days property with the events.', () => {
            controller.data = [];
            controller.firstDay = Date.vnNew();

            const lastDay = Date.vnNew();
            lastDay.setDate(lastDay.getDate() + 10);
            controller.lastDay = lastDay;

            const firstEventStamp = controller.firstDay.getTime();
            const lastEventStamp = controller.lastDay.getTime();
            controller.events = [{
                type: 'day',
                dated: firstEventStamp
            },
            {
                type: 'day',
                dated: lastEventStamp
            }];

            controller.refreshEvents();
            const expectedDays = Object.keys(controller.days);

            expect(expectedDays.length).toEqual(2);
        });
    });

    describe('onSelection()', () => {
        it('should call the emit() method', () => {
            jest.spyOn(controller, 'emit');

            const $event = {};
            const $days = [Date.vnNew()];
            const $type = 'day';
            const $weekday = 1;

            controller.onSelection($event, $days, $type, $weekday);

            expect(controller.emit).toHaveBeenCalledWith('selection',
                {
                    $days: $days,
                    $event: {},
                    $events: [],
                    $exclusions: [],
                    $type: 'day',
                    $weekday: 1,
                    $geoExclusions: [],
                }
            );
        });
    });

    describe('hasEvents()', () => {
        it('should return true for an existing event on a date', () => {
            const dated = Date.vnNew();

            controller.days[dated.getTime()] = true;

            const result = controller.hasEvents(dated);

            expect(result).toBeTruthy();
        });
    });

    describe('getClass()', () => {
        it('should return the className "excluded" for an excluded date', () => {
            const dated = Date.vnNew();

            controller.exclusions = [];
            controller.exclusions[dated.getTime()] = true;

            const result = controller.getClass(dated);

            expect(result).toEqual('excluded');
        });

        it('should return the className "geoExcluded" for a date with geo excluded', () => {
            const dated = Date.vnNew();

            controller.geoExclusions = [];
            controller.geoExclusions[dated.getTime()] = true;

            const result = controller.getClass(dated);

            expect(result).toEqual('geoExcluded');
        });
    });
});