import { Component, Inject, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { ScheduleDetailsDataSourceService } from '@schedule/services/data-source/details-data-source.service';
import { ScheduleNavigationService } from '@schedule/services/navigation.service';
import { ScheduleStateService } from '@schedule/services/state.service';
import { FLIGHTS_INFO_PARAM } from '@schedule/services/url/flights-info-param';
import {
    IScheduleDetailsParams,
    IScheduleRouteDirectionParams,
    IScheduleRouteParams,
} from '@schedule/services/url/types';
import { IScheduleRequestData, IScheduleRouteData } from '@schedule/types';
import { ScheduleItemModel } from '@shared/models-legacy';
import { IFlight } from '@typings/flight/flight';
import { getFlightArrivalCityCode } from '@utils/flight/arrival/city-code';
import { getFlightDepartureCityCode } from '@utils/flight/departure/city-code';
import { CurrentScheduleService } from './services/current-schedule.service';
import { DetailsScheduleDatesService } from './services/details-schedule-dates.service';

@Component({
    selector: 'schedule-flight-details',
    templateUrl: './schedule-flight-details-page.component.html',
    providers: [DetailsScheduleDatesService, CurrentScheduleService],
})
export class ScheduleFlightDetailsPageComponent implements OnInit {
    public schedule: ScheduleItemModel[];
    private request: IScheduleRouteParams;
    private requestQueryParam: string;

    constructor(
        public dataSource: ScheduleDetailsDataSourceService,
        private route: ActivatedRoute,
        private navigationService: ScheduleNavigationService,
        private dateService: DetailsScheduleDatesService,
        private scheduleState: ScheduleStateService,
        private currentScheduleService: CurrentScheduleService,
        @Inject(FLIGHTS_INFO_PARAM) private flightsInfoParamName,
    ) {}

    ngOnInit(): void {
        this.route.data.subscribe((data: IScheduleRouteData) => {
            if (data.urlParams?.details) {
                this.dataSource
                    .loadFlightDetails(data.urlParams.details)
                    .then(() => {
                        this.schedule =
                            this.currentScheduleService.getCurrentSchedule();
                    })
                    .catch(() => {
                        return this.navigationService.toNotFound();
                    });
            }

            if (data.urlParams?.details && data.requestData) {
                this.handleRequestChange(
                    data.requestData,
                    data.urlParams.details,
                );
            }
        });
    }

    async handleRedirectToScheduleDate(date: Date) {
        this.scheduleState.selectedDate = date;
        const datesRange = await this.dateService.getScheduleDatesRange(date);

        let routeParams: IScheduleRouteDirectionParams;
        let returnRouteParams: IScheduleRouteDirectionParams | undefined;

        this.navigationService.toDetailsPage(this.dataSource.flight, this.requestQueryParam, date);
/*
        // There are three cases of navigation:
        // - User loaded page without 'request' query param.
        // - User loaded page with param and flag isReturnSchedule is true.
        // - User loaded page with param and flag isReturnSchedule is false.

        // The first case. We cannot get arrival/departure from request,
        // so we generate them from loaded flight.
        if (!this.request) {
            routeParams = {
                arrival: getFlightArrivalCityCode(this.dataSource.flight),
                departure: getFlightDepartureCityCode(this.dataSource.flight),
                ...datesRange,
            };

            this.navigationService.toRoutePage(routeParams);
            return;
        }

        if (this.scheduleState.isReturnSchedule) {
            // The second case. We need to set new dates only for
            // return route params.
            routeParams = this.request.outbound;
            returnRouteParams = {
                ...this.request.inbound,
                ...datesRange,
            };
        } else {
            // The third case. We need to set new dates only for
            // route params.
            routeParams = {
                ...this.request.outbound,
                ...datesRange,
            };
            returnRouteParams = this.request.inbound;
        }

        this.navigationService.toRoutePage(routeParams, returnRouteParams);
*/
    }

    handleRedirectToFlightDetails(flight: IFlight) {
        this.navigationService.toDetailsPage(flight, this.requestQueryParam);
    }

    private async handleRequestChange(
        requestData: IScheduleRequestData,
        detailsParams: IScheduleDetailsParams,
    ) {
        this.requestQueryParam = requestData.raw;
        this.request = requestData.parsed;

        // Compute dates range for mini list: [-1 day, first flight date, +1 day].
        // If some date in range exceeds schedule validation range it'll be
        // discarded.
        const datesRange = await this.dateService.getMiniListDatesRange(
            detailsParams.flights[0].date,
        );

        // Generate route params with new dates.
        const routeParams: IScheduleRouteDirectionParams = {
            ...this.request.outbound,
            dateFrom: datesRange.dateFrom,
            dateTo: datesRange.dateTo,
        };

        let returnRouteParams: IScheduleRouteDirectionParams;

        // We need to generate return route params only if
        // it exists in request
        if (this.request.inbound) {
            returnRouteParams = {
                ...this.request.inbound,
                dateFrom: datesRange.dateFrom,
                dateTo: datesRange.dateTo,
            };
        }

        this.dataSource
            .loadFlightsByRoute(routeParams, returnRouteParams)
            .then(() => {
                this.schedule =
                    this.currentScheduleService.getCurrentSchedule();
            });
    }
}
