import {
    Component,
    EventEmitter,
    Inject,
    Input,
    OnChanges,
    Output,
    SimpleChanges,
} from '@angular/core';
import { IWeekTabValue } from '@components/dates-selectors/week-tabs/week-tabs.component';
import { ScheduleStateService } from '@schedule/services/state.service';
import { IScheduleRouteDirectionParams } from '@schedule/services/url/types';
import { ViewType } from '@shared/enumerators/flight-request-type.enum';
import {
    AppSettings,
    ScheduleItemModel,
    ScheduleSortMode,
} from '@shared/models-legacy';
import { APP_SETTINGS } from '@shared/services';
import { FeatureFlagsService } from '@shared/services/feature-flags.service';
import { IUrlTimeRange } from '@typings/common/url';
import { IFlight } from '../../../../../../../typings/flight/flight';
import { getEndOfTheWeek, getStartOfTheWeek } from '@utils/date';
import { ScheduleDirection } from '@typings/enums';

@Component({
    selector: 'schedule-search-view',
    templateUrl: './schedule-search-view.component.html',
    styleUrls: ['./schedule-search-view.component.scss'],
})
export class ScheduleSearchViewComponent implements OnChanges {
    Direction = ScheduleDirection;
    ViewType = ViewType;

    @Input() schedule: ScheduleItemModel[];
    @Input() returnSchedule: ScheduleItemModel[];
    @Input() loading: boolean;
    @Input() routeParams: IScheduleRouteDirectionParams;
    @Input() returnRouteParams: IScheduleRouteDirectionParams;
    @Input() isReturnSchedule: boolean;

    @Output() toDetails = new EventEmitter<IFlight>();
    @Output() cancel = new EventEmitter<boolean>();
    @Output() routeParamsChange =
        new EventEmitter<IScheduleRouteDirectionParams>();
    @Output() returnRouteParamsChange =
        new EventEmitter<IScheduleRouteDirectionParams>();

    timeRange: IUrlTimeRange;
    returnTimeRange: IUrlTimeRange;
    sortBy: ScheduleSortMode;
    maxScheduleDate: Date;
    minScheduleDate: Date;

    constructor(
        public featureFlags: FeatureFlagsService,
        private scheduleState: ScheduleStateService,
        @Inject(APP_SETTINGS) public settings: AppSettings,
    ) {}

    ngOnChanges(changes: SimpleChanges) {
        if ('routeParams' in changes) {
            this.handleRouteParamsChange();
            this.setThresholds();
        }

        if ('returnRouteParams' in changes) {
            this.handleReturnRouteParamsChange();
            this.setThresholds();
        }
    }

    get direction(): ScheduleDirection {
        return this.scheduleState.isReturnSchedule
            ? ScheduleDirection.INBOUND
            : ScheduleDirection.OUTBOUND;
    }

    get isDirect() {
        return this.direction === ScheduleDirection.OUTBOUND;
    }

    get currentSchedule() {
        return this.isDirect ? this.schedule : this.returnSchedule;
    }

    get isCurrentScheduleEmpty() {
        return this.isScheduleEmpty(this.currentSchedule);
    }

    get selectedDate() {
        return this.isDirect
            ? this.routeParams.dateFrom
            : this.returnRouteParams?.dateFrom;
    }

    get withReturnFlights() {
        return !!this.returnRouteParams;
    }

    handleToDetailsEvent(flight: IFlight) {
        this.toDetails.emit(flight);
    }

    handleDateChanged({ dateFrom, dateTo }: IWeekTabValue) {
        if (this.isDirect) {
            this.routeParamsChange.emit({
                ...this.routeParams,
                dateFrom,
                dateTo,
            });
        } else {
            this.returnRouteParamsChange.emit({
                ...this.returnRouteParams,
                dateFrom,
                dateTo,
            });
        }
    }

    handleTimeChanged(): void {
        this.routeParamsChange.emit({
            ...this.routeParams,
            ...this.timeRange,
        });
    }

    handleReturnTimeChanged(): void {
        this.returnRouteParamsChange.emit({
            ...this.returnRouteParams,
            ...this.returnTimeRange,
        });
    }

    handleCancelEvent() {
        this.cancel.emit(true);
    }

    handleDirectionChange(direction: ScheduleDirection) {
        this.scheduleState.isReturnSchedule =
            direction === ScheduleDirection.INBOUND;
    }

    private getMaxScheduleDate() {
        if (this.isDirect) {
            return (
                this.returnRouteParams?.dateTo || this.settings.scheduleMaxDate
            );
        }

        return this.settings.scheduleMaxDate;
    }

    private getMinScheduleDate() {
        if (this.isDirect) {
            return this.settings.scheduleMinDate;
        }

        return this.routeParams.dateFrom || this.settings.scheduleMinDate;
    }

    private setThresholds() {
        this.minScheduleDate = getStartOfTheWeek(this.getMinScheduleDate());
        this.maxScheduleDate = getEndOfTheWeek(this.getMaxScheduleDate());
    }

    private handleRouteParamsChange() {
        this.timeRange = {
            timeFrom: this.routeParams.timeFrom,
            timeTo: this.routeParams.timeTo,
        };
    }

    private handleReturnRouteParamsChange() {
        if (!this.returnRouteParams) {
            this.returnTimeRange = undefined;
            return;
        }

        this.returnTimeRange = {
            timeFrom: this.returnRouteParams.timeFrom,
            timeTo: this.returnRouteParams.timeTo,
        };
    }

    private isScheduleEmpty(schedule: ScheduleItemModel[]) {
        return schedule.every((scheduleItem) => {
            return !scheduleItem.flights.length;
        });
    }
}
