"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TransferBoardFilter = void 0;
const GtfsStopParser_1 = require("../../../helpers/GtfsStopParser");
const RouteTypeEnums_1 = require("../../../helpers/RouteTypeEnums");
const DEFAULT_TRANSFER_TIME_MS = 60 * 1000;
const TRANSFER_TIMES_MS = new Map([
    [RouteTypeEnums_1.GTFSRouteTypeEnum.BUS, 60_000],
    [RouteTypeEnums_1.GTFSRouteTypeEnum.EXT_MISCELLANEOUS, 60_000],
    [RouteTypeEnums_1.GTFSRouteTypeEnum.FERRY, 120_000],
    [RouteTypeEnums_1.GTFSRouteTypeEnum.FUNICULAR, 120_000],
    [RouteTypeEnums_1.GTFSRouteTypeEnum.METRO, 120_000],
    [RouteTypeEnums_1.GTFSRouteTypeEnum.TRAIN, 120_000],
    [RouteTypeEnums_1.GTFSRouteTypeEnum.TRAM, 60_000],
    [RouteTypeEnums_1.GTFSRouteTypeEnum.TROLLEYBUS, 60_000],
]);
const DIFFERENT_STOP_NAME_ALLOWED = new Map([
    [RouteTypeEnums_1.GTFSRouteTypeEnum.BUS, false],
    [RouteTypeEnums_1.GTFSRouteTypeEnum.EXT_MISCELLANEOUS, true],
    [RouteTypeEnums_1.GTFSRouteTypeEnum.FERRY, true],
    [RouteTypeEnums_1.GTFSRouteTypeEnum.FUNICULAR, true],
    [RouteTypeEnums_1.GTFSRouteTypeEnum.METRO, true],
    [RouteTypeEnums_1.GTFSRouteTypeEnum.TRAIN, true],
    [RouteTypeEnums_1.GTFSRouteTypeEnum.TRAM, false],
    [RouteTypeEnums_1.GTFSRouteTypeEnum.TROLLEYBUS, false],
]);
const TRANSFER_LINE_TYPES_TO_KEEP = new Set([
    RouteTypeEnums_1.GTFSRouteTypeEnum.FERRY,
    RouteTypeEnums_1.GTFSRouteTypeEnum.FUNICULAR,
    RouteTypeEnums_1.GTFSRouteTypeEnum.METRO,
    RouteTypeEnums_1.GTFSRouteTypeEnum.TRAIN,
]);
const ONE_HOUR_IN_MS = 60 * 60 * 1000;
class TransferBoardFilter {
    static filterDepartures(transfers, limit, arrivalTimeMs, requestTimeFromMs) {
        const filteredDepartures = [];
        // compute minutes (as ms) between provided timeFrom and arrivalTime
        const msBetweenRequestAndArrival = arrivalTimeMs - requestTimeFromMs;
        const timeEndMs = requestTimeFromMs + msBetweenRequestAndArrival + ONE_HOUR_IN_MS;
        const seenTripIds = new Set();
        for (const transfer of transfers) {
            if (filteredDepartures.length === limit) {
                break;
            }
            if (seenTripIds.has(transfer.trip.id)) {
                continue;
            }
            if (!TransferBoardFilter.isInRange(transfer, requestTimeFromMs, timeEndMs)) {
                continue;
            }
            seenTripIds.add(transfer.trip.id);
            filteredDepartures.push(transfer);
        }
        // Departures are already sorted so that metro ones are first
        return filteredDepartures;
    }
    static shouldKeepTransferAlways(transfer) {
        return TRANSFER_LINE_TYPES_TO_KEEP.has(transfer.departure.route_type);
    }
    static filterOutKeepAlwaysTransfer(transfers) {
        return transfers.filter((t) => !TransferBoardFilter.shouldKeepTransferAlways(t));
    }
    static keepAlwaysLinesAndTripIds(transfers, tripIdsToKeep) {
        return transfers.filter((t) => {
            return TransferBoardFilter.shouldKeepTransferAlways(t) || tripIdsToKeep.has(t.departure.trip_id);
        });
    }
    static minimalTransferTime(transfers, delayedTimeFrom) {
        const arrivalTime = delayedTimeFrom.getTime();
        return transfers.filter((t) => {
            const transferTimeMs = TRANSFER_TIMES_MS.get(t.departure.route_type) || DEFAULT_TRANSFER_TIME_MS;
            if (t.departure.predictedDepartureTimestamp == null) {
                return false;
            }
            return arrivalTime + transferTimeMs < t.departure.predictedDepartureTimestamp;
        });
    }
    static sameStopNameTransfer(transfers, currentStop, allowedStopIds) {
        const allowedStopIdsAsws = allowedStopIds.map(GtfsStopParser_1.GtfsStopParser.normalizedStopId);
        const currentStopAsw = GtfsStopParser_1.GtfsStopParser.normalizedStopId(currentStop.stop_id);
        return transfers.filter((t) => {
            const departureStopAsw = GtfsStopParser_1.GtfsStopParser.normalizedStopId(t.departure.stop_id);
            if (departureStopAsw === currentStopAsw) {
                return true;
            }
            if (DIFFERENT_STOP_NAME_ALLOWED.get(t.departure.route_type)) {
                return true;
            }
            return allowedStopIdsAsws.includes(departureStopAsw);
        });
    }
    static isInRange(departure, timeRangeStart, timeRangeEnd) {
        // departureMinutes are relative to timeFrom request parameter
        const departureMinutes = departure.departure_timestamp.minutes[0] === "<1" ? 1 : Number(departure.departure_timestamp.minutes[0]);
        if (isNaN(departureMinutes))
            return false;
        // Calculate the departure time
        const departureTime = timeRangeStart + departureMinutes * 60 * 1000;
        // Check if departureTime is within the range
        return timeRangeStart <= departureTime && departureTime <= timeRangeEnd;
    }
}
exports.TransferBoardFilter = TransferBoardFilter;
//# sourceMappingURL=TransferBoardFilter.js.map