"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProcessMetroRunMessagesTask = void 0;
const cache_1 = require("../../../../ropid-gtfs/data-access/cache");
const precomputed_1 = require("../../../../ropid-gtfs/data-access/precomputed");
const PositionsRepository_1 = require("../../vehicle-positions/data-access/PositionsRepository");
const TripsRepository_1 = require("../../vehicle-positions/data-access/TripsRepository");
const GTFSTripRunManagerFactory_1 = require("../../vehicle-positions/helpers/gtfs-trip-run/GTFSTripRunManagerFactory");
const vehicle_positions_1 = require("../../../../../schema-definitions/vehicle-positions");
const integration_engine_1 = require("@golemio/core/dist/integration-engine");
const helpers_1 = require("@golemio/core/dist/integration-engine/helpers");
const golemio_errors_1 = require("@golemio/core/dist/shared/golemio-errors");
const sequelize_1 = require("@golemio/core/dist/shared/sequelize");
const CommonRunsRepository_1 = require("../data-access/CommonRunsRepository");
const MetroMessageFilter_1 = require("../helpers/MetroMessageFilter");
const MetroTransformedRunsSchema_1 = require("../schema/MetroTransformedRunsSchema");
const MetroRunsMessageProcessingTransformation_1 = require("../transformations/MetroRunsMessageProcessingTransformation");
const constants_1 = require("../constants");
const tsyringe_1 = require("@golemio/core/dist/shared/tsyringe");
const MetroRailtrackGPSRepository_1 = require("../../../../ropid-gtfs/workers/timetables/tasks/data-access/MetroRailtrackGPSRepository");
let ProcessMetroRunMessagesTask = class ProcessMetroRunMessagesTask extends integration_engine_1.AbstractTask {
    constructor() {
        super(constants_1.WORKER_NAME);
        this.queueName = "processMetroRunMessages";
        this.queueTtl = 10 * 60 * 1000; // 10 minutes
        this.schema = MetroTransformedRunsSchema_1.MetroTransformedRunsValidationSchema;
        this.processingTransformation = new MetroRunsMessageProcessingTransformation_1.MetroRunsMessageProcessingTransformation();
        this.railtrackGPSRepository = new MetroRailtrackGPSRepository_1.MetroRailtrackGPSRepository();
        this.positionsRepository = new PositionsRepository_1.PositionsRepository();
        this.tripsRepository = new TripsRepository_1.TripsRepository();
        this.runsRepository = new CommonRunsRepository_1.CommonRunsRepository();
        this.runTripsRedisRepository = new cache_1.RunTripsRedisRepository();
        this.tripScheduleRepository = new precomputed_1.TripScheduleRepository();
        this.gtfsTripRunManager = GTFSTripRunManagerFactory_1.GTFSTripRunManagerFactory.create(GTFSTripRunManagerFactory_1.GTFSTripRunType.Metro, this.positionsRepository, this.tripsRepository, this.runsRepository, this.runTripsRedisRepository);
    }
    async execute({ routeName, messages }, msgProperties) {
        const { filteredMessages, trackIds } = MetroMessageFilter_1.MetroMessageFilter.getValidMessagesWithTrackIds(messages);
        if (filteredMessages.length === 0) {
            return;
        }
        const gpsData = await this.railtrackGPSRepository.findCoordinates(routeName, trackIds);
        for (const message of filteredMessages) {
            await this.processMessage(message, gpsData, msgProperties?.timestamp);
        }
    }
    async processMessage(message, gpsData, firstMessageCreatedAt) {
        const data = await this.processingTransformation.transform({ message, gpsData });
        if (!data) {
            return;
        }
        let enhancedMessage = null;
        try {
            enhancedMessage = await this.enrichRunMessage(data.runInput);
        }
        catch (err) {
            throw new golemio_errors_1.GeneralError(`processMessage: error while fetching trip schedule`, this.constructor.name, err);
        }
        if (!enhancedMessage) {
            helpers_1.log.verbose(`processMessage: no trip_id for metro run: ${JSON.stringify(data.runInput)}`);
            return;
        }
        const scheduledTrips = await this.gtfsTripRunManager.setAndReturnScheduledTrips({
            ...data.runSchedule,
            // try to use internal run number if available (input run message is not always reliable)
            run_number: enhancedMessage.internalRunNumber ?? data.runSchedule.run_number,
        });
        if (scheduledTrips.length === 0) {
            helpers_1.log.verbose(`processMessage: no schedule for metro run: ${JSON.stringify(data.runSchedule)}`);
            return;
        }
        const delayMsg = await this.gtfsTripRunManager.generateDelayMsg(scheduledTrips, enhancedMessage);
        if (delayMsg.updatedTrips.length > 0) {
            await integration_engine_1.QueueManager.sendMessageToExchange(`${integration_engine_1.config.RABBIT_EXCHANGE_NAME}.${vehicle_positions_1.VehiclePositions.name.toLowerCase()}`, "updateDelay", delayMsg, { timestamp: firstMessageCreatedAt });
        }
    }
    async enrichRunMessage(runInput) {
        const tripSchedule = await this.tripScheduleRepository.findOne({
            attributes: ["trip_id", "run_number"],
            where: {
                trip_number: runInput.trainNumber,
                route_id: `L${runInput.routeId}`,
                [sequelize_1.Op.and]: [sequelize_1.Sequelize.literal("start_timestamp::date = current_date")],
            },
        });
        if (!tripSchedule) {
            return null;
        }
        return {
            ...runInput,
            tripId: tripSchedule.trip_id,
            internalRunNumber: tripSchedule.run_number,
        };
    }
};
exports.ProcessMetroRunMessagesTask = ProcessMetroRunMessagesTask;
exports.ProcessMetroRunMessagesTask = ProcessMetroRunMessagesTask = __decorate([
    (0, tsyringe_1.injectable)(),
    __metadata("design:paramtypes", [])
], ProcessMetroRunMessagesTask);
//# sourceMappingURL=ProcessMetroRunMessagesTask.js.map