import * as moment from 'moment';
import { ILegContract } from './contracts';
import { calculateLegState, calculateRemainingDuration, createLeg } from './populate.logic';

describe('PopulateLogic', () => {
    beforeEach(() => {
        jasmine.clock().install().mockDate(new Date(2021, 11, 26, 12, 35, 30));
    });

    afterEach(() => {
        jasmine.clock().uninstall();
    });
    const _7h30minBack = () =>
        moment()
            .add(-(7 * 60 + 30), 'minutes')
            .toDate();
    const _8h40minBack = () =>
        moment()
            .add(-(8 * 60 + 40), 'minutes')
            .toDate();
    const _1hBack = () =>
        moment()
            .add(-(1 * 60), 'minutes')
            .toDate();
    const _5h10minForth = () =>
        moment()
            .add(5 * 60 + 10, 'minutes')
            .toDate();
    const _6h20minForth = () =>
        moment()
            .add(6 * 60 + 20, 'minutes')
            .toDate();
    const _1hForth = () =>
        moment()
            .add(1 * 60, 'minutes')
            .toDate();

    describe('calculateRemainingDuration', () => {
        it('should calculate remaining duration using estimated arrival time when both scheduled and estimated given', () => {
            const legContract = {
                departure: {
                    times: {
                        actualBlockOff: { utc: _7h30minBack() },
                        scheduledDeparture: { utc: _8h40minBack() },
                        estimatedBlockOff: { utc: _8h40minBack() },
                    },
                },
                arrival: { times: { scheduledArrival: { utc: _6h20minForth() }, estimatedBlockOn: { utc: _5h10minForth() } } },
                status: 'InFlight',
            } as any as ILegContract;

            const leg = createLeg(legContract);

            expect(calculateRemainingDuration(leg)).toEqual({ days: 0, hours: 5, minutes: 10 });
        });

        it('should calculate remaining duration using scheduled arrival time when no estimated time given', () => {
            const legContract = {
                departure: {
                    times: {
                        actualBlockOff: { utc: _7h30minBack() },
                        scheduledDeparture: { utc: _8h40minBack() },
                        estimatedBlockOff: { utc: _8h40minBack() },
                    },
                },
                arrival: { times: { scheduledArrival: { utc: _6h20minForth() } } },
                status: 'InFlight',
            } as any as ILegContract;

            const leg = createLeg(legContract);

            expect(calculateRemainingDuration(leg)).toEqual({ days: 0, hours: 6, minutes: 20 });
        });

        it('should use zero as remaining for already passed', () => {
            const leg = {
                departure: { times: { actual: { utc: _5h10minForth() } } },
                arrival: { times: { scheduled: { utc: _6h20minForth() } } },
            } as any;
            expect(calculateRemainingDuration(leg)).toEqual({ days: 0, hours: 0, minutes: 0 });

            const leg2 = {
                departure: { times: { actual: { utc: _8h40minBack() } } },
                arrival: { times: { scheduled: { utc: _7h30minBack() } } },
            } as any;
            expect(calculateRemainingDuration(leg2)).toEqual({ days: 0, hours: 0, minutes: 0 });
        });
    });

    describe('calculateFlightTimePercent', () => {
        it('should calculate percent using estimated arrival time if both estimated and scheduled times are given', () => {
            const legContract = {
                departure: {
                    times: {
                        scheduledDeparture: { utc: _8h40minBack() },
                        actualBlockOff: { utc: _1hBack() },
                    },
                },
                arrival: { times: { scheduledArrival: { utc: _6h20minForth() }, estimatedBlockOn: { utc: _1hForth() } } },
                status: 'InFlight',
            } as any as ILegContract;

            const leg = createLeg(legContract);
            calculateLegState(leg);

            expect(leg.flightPercent).toEqual(50);
        });

        it('should have flight percent eq 0 for future flights', () => {
            const legContract = {
                departure: { times: { scheduledDeparture: { utc: _5h10minForth() } } },
                arrival: { times: { scheduledArrival: { utc: _6h20minForth() } } },
            } as any as ILegContract;

            const leg = createLeg(legContract);
            calculateLegState(leg);

            expect(leg.flightPercent).toEqual(0);
        });

        it('should have flight percent eq 100% for completed flights', () => {
            const legContract = {
                departure: { times: { scheduledDeparture: { utc: _8h40minBack() }, actualBlockOff: { utc: _8h40minBack() } } },
                arrival: { times: { scheduledArrival: { utc: _7h30minBack() }, actualTouchDown: { utc: _7h30minBack() } } },
            } as any as ILegContract;

            const leg = createLeg(legContract);
            calculateLegState(leg);

            expect(leg.flightPercent).toEqual(100);
        });
    });
});
