"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);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DeparturesRepository = void 0;
const RouteTypeEnums_1 = require("../../../../helpers/RouteTypeEnums");
const const_1 = require("../../../../schema-definitions/const");
const precomputed_1 = require("../../../../schema-definitions/ropid-gtfs/models/precomputed");
const CoreToken_1 = require("@golemio/core/dist/helpers/ioc/CoreToken");
const models_1 = require("@golemio/core/dist/integration-engine/models");
const golemio_errors_1 = require("@golemio/core/dist/shared/golemio-errors");
const golemio_validator_1 = require("@golemio/core/dist/shared/golemio-validator");
const sequelize_1 = require("@golemio/core/dist/shared/sequelize");
const tsyringe_1 = require("@golemio/core/dist/shared/tsyringe");
const SourceTableSuffixEnum_1 = require("../../helpers/SourceTableSuffixEnum");
let DeparturesRepository = class DeparturesRepository extends models_1.PostgresModel {
    constructor(config, logger) {
        super("DeparturesRepository", {
            pgTableName: precomputed_1.DeparturesModel.TABLE_NAME,
            pgSchema: const_1.PG_SCHEMA,
            outputSequelizeAttributes: precomputed_1.DeparturesModel.attributeModel,
            attributesToRemove: ["id", "created_at", "updated_at"],
            savingType: "insertOnly",
        }, new golemio_validator_1.JSONSchemaValidator("DeparturesRepository", precomputed_1.DeparturesModel.jsonSchema));
        this.config = config;
        this.logger = logger;
        this.createAndPopulate = async (sourceTableSuffix) => {
            const nodeEnv = this.config.getValue("env.NODE_ENV", "development");
            const timeConstraintLiteral = nodeEnv !== "test" ? `WHERE gtfs_timestamp(t.arrival_time, t4.date) > now() - interval '6 hours'` : "";
            /* eslint-disable max-len */
            const sql = `
            SELECT
                t.stop_sequence,
                t.stop_headsign,
                t.pickup_type,
                t.drop_off_type,
                t.arrival_time,
                gtfs_timestamp(t.arrival_time, t4.date) AS arrival_datetime,
                t.departure_time,
                gtfs_timestamp(t.departure_time, t4.date) AS departure_datetime,
                t0.stop_id,
                t0.stop_name,
                t0.platform_code,
                t0.wheelchair_boarding,
                t1.min_stop_sequence,
                t1.max_stop_sequence,
                t2.trip_id,
                t2.trip_headsign,
                t2.trip_short_name,
                t2.wheelchair_accessible,
                t3.service_id,
                t4.date,
                t5.route_short_name,
                coalesce(t5.route_type, :defaultRouteType) AS route_type,
                t5.route_id,
                t5.is_night,
                t5.is_regional,
                t5.is_substitute_transport,
                t6.stop_sequence AS next_stop_sequence,
                t6.stop_id AS next_stop_id,
                t7.stop_sequence AS last_stop_sequence,
                t7.stop_id AS last_stop_id,
                cis_stop.cis AS cis_stop_group_id
            FROM ropidgtfs_stop_times${sourceTableSuffix} t
                LEFT JOIN ropidgtfs_stops${sourceTableSuffix} t0 ON t.stop_id = t0.stop_id
                LEFT JOIN ropidgtfs_trips${sourceTableSuffix} t2 ON t.trip_id = t2.trip_id
                INNER JOIN ropidgtfs_precomputed_services_calendar_tmp t4 ON t2.service_id = t4.service_id
                INNER JOIN ropidgtfs_precomputed_minmax_stop_sequences_tmp t1 ON t.trip_id = t1.trip_id
                LEFT JOIN ropidgtfs_calendar${sourceTableSuffix} t3 ON t2.service_id = t3.service_id
                LEFT JOIN ropidgtfs_routes${sourceTableSuffix} t5 ON t2.route_id = t5.route_id
                LEFT JOIN ropidgtfs_stop_times${sourceTableSuffix} t6 ON t.trip_id = t6.trip_id AND t6.stop_sequence = t.stop_sequence + 1
                LEFT JOIN ropidgtfs_stop_times${sourceTableSuffix} t7 ON t.trip_id = t7.trip_id AND t7.stop_sequence = t.stop_sequence - 1
                LEFT JOIN ropidgtfs_cis_stops cis_stop on cis_stop.id = t0.computed_cis_stop_id
            ${timeConstraintLiteral}`;
            /* eslint-enable max-len */
            try {
                const tableName = precomputed_1.DeparturesModel.TABLE_NAME;
                const tmpTableName = tableName + SourceTableSuffixEnum_1.SourceTableSuffixEnum.Tmp;
                await this.sequelizeModel.sequelize.query(`
                SET LOCAL search_path TO ${const_1.PG_SCHEMA};
                DROP TABLE IF EXISTS ${tmpTableName};
                CREATE TABLE ${tmpTableName} (LIKE ${tableName} including all);
                INSERT INTO ${tmpTableName} ${sql};`, {
                    replacements: {
                        defaultRouteType: RouteTypeEnums_1.GTFSRouteTypeEnum.EXT_MISCELLANEOUS,
                    },
                });
            }
            catch (err) {
                this.logger.error(err);
                throw err;
            }
        };
        this.countDeparturesForPublicCache = async (intervalParams) => {
            try {
                return await this.sequelizeModel.count({
                    where: {
                        [sequelize_1.Op.and]: {
                            departure_datetime: {
                                [sequelize_1.Op.between]: [
                                    sequelize_1.Sequelize.literal(`now() + interval '${intervalParams.intervalFromHours} hours'`),
                                    sequelize_1.Sequelize.literal(`now() + interval '${intervalParams.intervalToHours} hours'`),
                                ],
                            },
                            next_stop_sequence: {
                                [sequelize_1.Op.not]: null,
                            },
                        },
                    },
                });
            }
            catch (err) {
                throw new golemio_errors_1.GeneralError("Error while getting number of departures", this.constructor.name, err);
            }
        };
        this.getDepaturesForPublicCache = async (page, pageSize, intervalParams) => {
            try {
                return await this.sequelizeModel.findAll({
                    attributes: [
                        "stop_id",
                        "departure_datetime",
                        "arrival_datetime",
                        "route_short_name",
                        "route_type",
                        "trip_id",
                        "stop_sequence",
                        "platform_code",
                        "trip_headsign",
                        "stop_headsign",
                    ],
                    where: {
                        departure_datetime: {
                            [sequelize_1.Op.between]: [
                                sequelize_1.Sequelize.literal(`now() + interval '${intervalParams.intervalFromHours} hours'`),
                                sequelize_1.Sequelize.literal(`now() + interval '${intervalParams.intervalToHours} hours'`),
                            ],
                        },
                        next_stop_sequence: { [sequelize_1.Op.not]: null },
                        pickup_type: { [sequelize_1.Op.ne]: "1" },
                        stop_sequence: {
                            [sequelize_1.Op.ne]: sequelize_1.Sequelize.col("max_stop_sequence"),
                        },
                    },
                    order: [["departure_datetime", "ASC"]],
                    offset: page * pageSize,
                    limit: pageSize,
                    raw: true,
                });
            }
            catch (err) {
                throw new golemio_errors_1.GeneralError("Error while getting departures for public cache", this.constructor.name, err);
            }
        };
        this.replaceByTmp = async (transaction) => {
            try {
                const tableName = precomputed_1.DeparturesModel.TABLE_NAME;
                const tmpTableName = tableName + SourceTableSuffixEnum_1.SourceTableSuffixEnum.Tmp;
                const dropTableName = tableName + SourceTableSuffixEnum_1.SourceTableSuffixEnum.Drop;
                await this.sequelizeModel.sequelize.query(`
                SET LOCAL search_path TO ${const_1.PG_SCHEMA};
                LOCK ${tableName} IN EXCLUSIVE MODE;
                ALTER TABLE ${tableName} RENAME TO ${dropTableName};
                ALTER TABLE ${tmpTableName} RENAME TO ${tableName};
                DROP TABLE ${dropTableName} CASCADE;`, { transaction });
            }
            catch (err) {
                this.logger.error(err);
                throw err;
            }
        };
        this.analyze = async () => {
            try {
                await this.sequelizeModel.sequelize.query(`analyze ${const_1.PG_SCHEMA}.${precomputed_1.DeparturesModel.TABLE_NAME}${SourceTableSuffixEnum_1.SourceTableSuffixEnum.Tmp};`);
            }
            catch (err) {
                this.logger.error(err);
                throw err;
            }
        };
    }
};
exports.DeparturesRepository = DeparturesRepository;
exports.DeparturesRepository = DeparturesRepository = __decorate([
    (0, tsyringe_1.injectable)(),
    __param(0, (0, tsyringe_1.inject)(CoreToken_1.CoreToken.SimpleConfig)),
    __param(1, (0, tsyringe_1.inject)(CoreToken_1.CoreToken.Logger)),
    __metadata("design:paramtypes", [Object, Object])
], DeparturesRepository);
//# sourceMappingURL=DeparturesRepository.js.map