"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AbstractPropagateDelayTask = void 0;
const integration_engine_1 = require("@golemio/core/dist/integration-engine");
const const_1 = require("../../../../../../const");
const PositionsRepository_1 = require("../../data-access/PositionsRepository");
const TripsRepository_1 = require("../../data-access/TripsRepository");
class AbstractPropagateDelayTask extends integration_engine_1.AbstractTask {
    constructor(queuePrefix) {
        super(queuePrefix);
        this.queueTtl = 5 * 60 * 1000; // 5 minutes
        /**
         * Takes all newly computed positions search for next trips in near future and propagate delay for them
         */
        this.propagateDelayForGtfsTrip = async (data) => {
            const trips = await this.tripsRepository.getPropagateDelayTripsWithPositions(data);
            if (!trips.length)
                return;
            let tripsToUpdate = new Map();
            let positionsToUpdate = [];
            let turnTimeAcc = (new Date(trips[0].start_timestamp).getTime() - new Date(data.currentEndTime).getTime()) / 1000;
            for (let i = 0; i < trips.length; i++) {
                const trip = trips[i];
                const lastPosition = trip.last_position;
                const requiredTurnaroundSeconds = data.nextGtfsTrips.find((gtfsTrip) => gtfsTrip.trip_id === trip.gtfs_trip_id)?.requiredTurnaroundSeconds ?? 0;
                let delayInSeconds = data.currentDelay;
                // If trips are not connected through block_id, subtract the time that the vehicle is expected to wait between trips
                // otherwise delay should be propagated to next trips as is
                if (!data.currentGtfsBlockId || !trip.gtfs_block_id || data.currentGtfsBlockId !== trip.gtfs_block_id) {
                    if (i === 0) {
                        turnTimeAcc -= requiredTurnaroundSeconds;
                    }
                    else {
                        const previousTrip = trips[i - 1];
                        const startTimestamp = new Date(trip.start_timestamp).getTime();
                        const endTimestamp = new Date(previousTrip.end_timestamp).getTime();
                        turnTimeAcc += (startTimestamp - endTimestamp) / 1000 - requiredTurnaroundSeconds;
                    }
                    delayInSeconds = Math.max(0, delayInSeconds - turnTimeAcc);
                }
                tripsToUpdate.set(trip.id, {
                    id: trip.id,
                    last_position_id: lastPosition.id,
                    last_position_context: {
                        ...trip.last_position_context,
                        lastPositionLat: typeof lastPosition.lat === "string" ? parseFloat(lastPosition.lat) : lastPosition.lat,
                        lastPositionLng: typeof lastPosition.lng === "string" ? parseFloat(lastPosition.lng) : lastPosition.lng,
                        lastPositionState: const_1.StatePositionEnum.BEFORE_TRACK_DELAYED,
                        lastPositionStateChange: new Date().toISOString(),
                        lastPositionBeforeTrackDelayed: {
                            delay: delayInSeconds,
                            origin_timestamp: lastPosition.origin_timestamp,
                        },
                    },
                });
                positionsToUpdate.push({
                    id: lastPosition.id,
                    delay: delayInSeconds,
                    state_position: const_1.StatePositionEnum.BEFORE_TRACK_DELAYED,
                    state_process: const_1.StateProcessEnum.PROCESSED,
                    origin_timestamp: lastPosition.origin_timestamp,
                    bearing: data.currentBearing,
                    origin_position_id: data.originPositionId,
                });
            }
            await this.positionsRepository.bulkSave(positionsToUpdate);
            await this.tripsRepository.bulkSave(Array.from(tripsToUpdate.values()));
        };
        this.tripsRepository = new TripsRepository_1.TripsRepository();
        this.positionsRepository = new PositionsRepository_1.PositionsRepository();
    }
}
exports.AbstractPropagateDelayTask = AbstractPropagateDelayTask;
//# sourceMappingURL=AbstractPropagateDelayTask.js.map