"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DelayComputationRedisRepository = void 0;
const RedisJsonParser_1 = require("../../../../helpers/RedisJsonParser");
const Di_1 = require("../../ioc/Di");
const DelayComputationDtoSchema_1 = require("../../../../schema-definitions/ropid-gtfs/redis/schemas/DelayComputationDtoSchema");
const const_1 = require("../../../../schema-definitions/vehicle-positions/redis/const");
const CoreToken_1 = require("@golemio/core/dist/helpers/ioc/CoreToken");
const RedisModel_1 = require("@golemio/core/dist/integration-engine/models/RedisModel");
const golemio_errors_1 = require("@golemio/core/dist/shared/golemio-errors");
const golemio_validator_1 = require("@golemio/core/dist/shared/golemio-validator");
class DelayComputationRedisRepository extends RedisModel_1.RedisModel {
    constructor() {
        super("GTFSDelayComputationRedisRepository", {
            decodeDataAfterGet: JSON.parse,
            encodeDataBeforeSave: JSON.stringify,
            isKeyConstructedFromData: true,
            prefix: DelayComputationRedisRepository.NAMESPACE_PREFIX,
        }, new golemio_validator_1.JSONSchemaValidator("GTFSDelayComputationRedisRepositoryValidator", DelayComputationDtoSchema_1.DelayComputationDtoSchema));
        this.logger = Di_1.RopidGtfsContainer.resolve(CoreToken_1.CoreToken.Logger);
    }
    async expire(keys, ttlInSeconds) {
        const pipeline = this.connection.pipeline();
        for (const key of keys) {
            const redisKey = `${this.prefix}:${key}`;
            pipeline.expire(redisKey, ttlInSeconds);
        }
        try {
            await pipeline.exec();
        }
        catch (err) {
            throw new golemio_errors_1.GeneralError("Error while expiring keys in Redis", this.constructor.name, err);
        }
    }
    async expirePxat(tripIdsWithTtl) {
        const pipeline = this.connection.pipeline();
        for (const trip of tripIdsWithTtl) {
            const redisKey = `${this.prefix}:${trip.tripId}`;
            pipeline.pexpireat(redisKey, trip.expirationTtl);
        }
        try {
            await pipeline.exec();
        }
        catch (err) {
            throw new golemio_errors_1.GeneralError("Error while expiring keys in Redis", this.constructor.name, err);
        }
    }
    async cacheTripDataBatch(trips, positions) {
        const pipeline = this.connection.pipeline();
        for (const trip of trips) {
            const expirationTtl = this.calculateExpirationTtl(positions, trip.id);
            const redisKey = `${DelayComputationRedisRepository.NAMESPACE_PREFIX}:${trip.gtfs_trip_id}`;
            pipeline.call("JSON.SET", redisKey, "$", JSON.stringify(trip.gtfsData));
            pipeline.pexpireat(redisKey, expirationTtl);
        }
        try {
            await pipeline.exec();
        }
        catch (err) {
            throw new golemio_errors_1.GeneralError("Error while setting caches in Redis with pipeline", this.constructor.name, err);
        }
    }
    async getTripPropertiesBatch(tripIds, properties) {
        if (tripIds.length === 0) {
            return [];
        }
        const pipeline = this.connection.pipeline();
        for (const tripId of tripIds) {
            const redisKey = `${this.prefix}:${tripId}`;
            const propertyPaths = [];
            for (const prop of properties) {
                propertyPaths.push(`$.${String(prop)}`);
            }
            pipeline.call("JSON.GET", redisKey, ...propertyPaths);
        }
        try {
            const responses = await pipeline.exec();
            if (!responses) {
                return tripIds.map(() => null);
            }
            const result = [];
            for (let index = 0; index < responses.length; index++) {
                const [error, redisResult] = responses[index];
                if (error) {
                    this.logger.warn({
                        error,
                        result: redisResult,
                    }, `${this.constructor.name}: Failed to fetch trip '${tripIds[index]}' from Redis`);
                    result.push(null);
                    continue;
                }
                if (redisResult === null || redisResult === undefined) {
                    result.push(null);
                    continue;
                }
                result.push(RedisJsonParser_1.RedisJsonParser.parse(redisResult, this.constructor.name));
            }
            return result;
        }
        catch (err) {
            throw new golemio_errors_1.GeneralError("Error while fetching trip properties batch from Redis", this.constructor.name, err);
        }
    }
    calculateExpirationTtl(positions, tripId) {
        const now = new Date();
        const expirationLimit = new Date(now.getTime() + 30 * 60 * 1000); // 30 minutes
        const tripPositions = positions.find((p) => p.context.tripId === tripId);
        let validTo = null;
        if (tripPositions) {
            const { lastPositionId } = tripPositions.context;
            const lastPosition = tripPositions.positions.find((p) => p?.id === lastPositionId);
            validTo = lastPosition?.valid_to ?? null;
        }
        return validTo ? Math.min(new Date(validTo).getTime(), expirationLimit.getTime()) : expirationLimit.getTime();
    }
}
exports.DelayComputationRedisRepository = DelayComputationRedisRepository;
DelayComputationRedisRepository.NAMESPACE_PREFIX = const_1.GTFS_DELAY_COMPUTATION_NAMESPACE_PREFIX;
//# sourceMappingURL=DelayComputationRedisRepository.js.map