import { Injectable } from '@angular/core';
import {
    ActivatedRouteSnapshot,
    CanActivate,
    Params,
    Router,
} from '@angular/router';
import { RootNavigationService } from '@shared/services/navigation.service';
import {
    IScheduleRouteParamsValidationResult,
    ScheduleRouteParamsValidationService,
} from '@schedule/services/route-params-validation.service';
import { ScheduleUrlParserService } from '@schedule/services/url/url-parser.service';
import { CanActivateRedirrect } from './can-activate-redirrect-to-not-found';

@Injectable()
export class CanActivateScheduleRouteSearch implements CanActivate {
    constructor(
        private rootNavigationService: RootNavigationService,
        private urlService: ScheduleUrlParserService,
        private routeParamsValidator: ScheduleRouteParamsValidationService,
        private router: Router,
        private canRedirrect: CanActivateRedirrect,
    ) { }

    async canActivate(route: ActivatedRouteSnapshot) {
        let redirrected = false;
        const { params, returnParams } = this.getRouteParams(route.params);
        const result = await this.routeParamsValidator.validateRoute(
            params,
            returnParams,
        );

        if (!this.canRedirrect.validateTimeRange(params.timeFrom, params.timeTo)
            || !this.canRedirrect.validateStation(params.arrival)
            || !this.canRedirrect.validateStation(params.departure)
            || (params.connections !== undefined && isNaN(params.connections))
            || !params.dateFrom
            || !params.dateTo) {
            this.rootNavigationService.toNotFound();
            redirrected = true;
        }

        if (returnParams) {
            if (!this.canRedirrect.validateTimeRange(returnParams.timeFrom, returnParams.timeTo)
                || !this.canRedirrect.validateStation(returnParams.arrival)
                || !this.canRedirrect.validateStation(returnParams.departure)
                || (returnParams.connections !== undefined && isNaN(returnParams.connections))
                || !returnParams.dateFrom
                || !returnParams.dateTo) {
                this.rootNavigationService.toNotFound();
                redirrected = true;
            }
        }

        return this.handleValidation(result, redirrected);
    }

    private getRouteParams(routeParams: Params) {
        const { params, returnParams } = routeParams;

        return {
            params: this.urlService.parseRouteParams(params),
            returnParams:
                returnParams && this.urlService.parseRouteParams(returnParams),
        };
    }

    private handleValidation(result: IScheduleRouteParamsValidationResult, redirrected: boolean) {
        if (result.isValid) {
            return true;
        }

        if (redirrected) {
            return false;
        }

        if (!result.areStationsValid) {
            return this.rootNavigationService.toNotFound();
        }

        return this.router.navigateByUrl(this.urlService.base);
    }
}
