"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); }
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RopidGtfsFacade = exports.DatasetEnum = void 0;
const precomputed_1 = require("./data-access/precomputed");
const shared_1 = require("../shared");
const const_1 = require("../../schema-definitions/const");
const ropid_gtfs_1 = require("../../schema-definitions/ropid-gtfs");
const CoreToken_1 = require("@golemio/core/dist/helpers/ioc/CoreToken");
const helpers_1 = require("@golemio/core/dist/integration-engine/helpers");
const golemio_errors_1 = require("@golemio/core/dist/shared/golemio-errors");
const sequelize_1 = __importDefault(require("@golemio/core/dist/shared/sequelize"));
const tsyringe_1 = require("@golemio/core/dist/shared/tsyringe");
const RopidGtfsMetadataRepository_1 = require("./RopidGtfsMetadataRepository");
const RopidGtfsRepository_1 = require("./data-access/RopidGtfsRepository");
const SourceTableSuffixEnum_1 = require("./helpers/SourceTableSuffixEnum");
const RopidGtfsContainerToken_1 = require("./ioc/RopidGtfsContainerToken");
const HelperTypes_1 = require("./workers/timetables/tasks/helpers/HelperTypes");
var DatasetEnum;
(function (DatasetEnum) {
    DatasetEnum["PID_GTFS"] = "PID_GTFS";
    DatasetEnum["CIS_STOPS"] = "CIS_STOPS";
    DatasetEnum["OIS_MAPPING"] = "OIS_MAPPING";
    DatasetEnum["RUN_NUMBERS"] = "RUN_NUMBERS";
    DatasetEnum["DEPARTURES_PRESETS"] = "DEPARTURES_PRESETS";
})(DatasetEnum || (exports.DatasetEnum = DatasetEnum = {}));
let RopidGtfsFacade = class RopidGtfsFacade {
    constructor(ropidGtfsRepository, ropidGtfsMetadataRepository, departureRepository, databaseConnector) {
        this.ropidGtfsRepository = ropidGtfsRepository;
        this.ropidGtfsMetadataRepository = ropidGtfsMetadataRepository;
        this.departureRepository = departureRepository;
        this.databaseConnector = databaseConnector;
        this.name = this.constructor.name;
        this.checkSavedTmpTables = async (dataset, version) => {
            const tables = await this.ropidGtfsMetadataRepository.getAllSaved(dataset, version);
            const tablesArray = [];
            tables.map((table) => {
                tablesArray.push(`'${ropid_gtfs_1.RopidGTFS[table.dataValues.tn].pgTableName}${SourceTableSuffixEnum_1.SourceTableSuffixEnum.Tmp}'`);
            });
            const connection = this.databaseConnector.getConnection();
            const result = await connection.query(`
            SELECT table_name AS name, count_rows(table_schema, table_name) AS total
            FROM information_schema.tables
            WHERE table_schema NOT IN ('pg_catalog', 'information_schema')
                AND table_type = 'BASE TABLE'
                AND table_name in (${tablesArray.join(",")})
                AND table_schema = '${const_1.PG_SCHEMA}';
            `, { type: sequelize_1.default.QueryTypes.SELECT });
            helpers_1.log.info(`Datasets: total rows for ${dataset}: ${JSON.stringify(result)}`);
            if (!result || !result.length || result.some((table) => table.total === 0)) {
                throw new golemio_errors_1.GeneralError("Empty table found", this.constructor.name);
            }
        };
        this.replaceTables = async (datasetInfo) => {
            const tables = await this.ropidGtfsMetadataRepository.find({
                attributes: [[sequelize_1.default.literal(`DISTINCT "key"`), "tn"]],
                where: {
                    [sequelize_1.default.Op.or]: datasetInfo.map((item) => ({
                        dataset: item.dataset,
                        type: shared_1.MetaTypeEnum.STATE,
                        value: shared_1.MetaStateEnum.SAVED,
                        version: item.version,
                    })),
                },
            });
            const connection = this.databaseConnector.getConnection();
            const t = await connection.transaction();
            try {
                await this.replaceStaticTables(tables, t);
                await this.replacePrecomputedTables(t);
                // save meta
                await this.ropidGtfsMetadataRepository.bulkCreate(datasetInfo.map((el) => ({
                    dataset: el.dataset,
                    key: shared_1.MetaDatasetInfoKeyEnum.DEPLOYED,
                    type: shared_1.MetaTypeEnum.DATASET_INFO,
                    value: "true",
                    version: el.version,
                })), { transaction: t });
                await this.ropidGtfsMetadataRepository.destroy({
                    transaction: t,
                    where: {
                        [sequelize_1.default.Op.or]: datasetInfo.map((item) => ({
                            dataset: item.dataset,
                            version: {
                                [sequelize_1.default.Op.and]: [
                                    // delete all versions older than ten versions back
                                    { [sequelize_1.default.Op.lt]: item.version - 10 },
                                    { [sequelize_1.default.Op.ne]: -1 },
                                ],
                            },
                        })),
                    },
                });
                await t.commit();
                return true;
            }
            catch (err) {
                helpers_1.log.error(err);
                await t.rollback();
                helpers_1.log.error(`Datasets: replacing failed ${err.toString()}`);
                throw new golemio_errors_1.GeneralError(this.name + ": replaceTables() failed.", undefined, err);
            }
        };
        this.replaceStaticTables = async (tables, t) => {
            const tablesArray = tables.map((table) => (0, HelperTypes_1.getTableNameFromModel)(table.dataValues.tn));
            await this.ropidGtfsRepository.replaceAllTable(tablesArray, t);
        };
        this.replacePrecomputedTables = async (t) => {
            await this.ropidGtfsRepository.replaceAllTable([
                this.servicesCalendarRepository["tableName"],
                this.minMaxStopSequencesRepository["tableName"],
                this.tripScheduleRepository["tableName"],
            ], t);
            await this.departureRepository.replaceByTmp(t);
        };
        this.minMaxStopSequencesRepository = new precomputed_1.MinMaxStopSequencesRepository();
        this.tripScheduleRepository = new precomputed_1.TripScheduleRepository();
        this.servicesCalendarRepository = new precomputed_1.ServicesCalendarRepository();
    }
};
exports.RopidGtfsFacade = RopidGtfsFacade;
exports.RopidGtfsFacade = RopidGtfsFacade = __decorate([
    (0, tsyringe_1.injectable)(),
    __param(0, (0, tsyringe_1.inject)(RopidGtfsContainerToken_1.RopidGtfsContainerToken.RopidGtfsRepository)),
    __param(1, (0, tsyringe_1.inject)(RopidGtfsContainerToken_1.RopidGtfsContainerToken.RopidGtfsMetadataRepository)),
    __param(2, (0, tsyringe_1.inject)(RopidGtfsContainerToken_1.RopidGtfsContainerToken.DepartureRepository)),
    __param(3, (0, tsyringe_1.inject)(CoreToken_1.CoreToken.PostgresConnector)),
    __metadata("design:paramtypes", [RopidGtfsRepository_1.RopidGtfsRepository,
        RopidGtfsMetadataRepository_1.RopidGtfsMetadataRepository,
        precomputed_1.DeparturesRepository, Object])
], RopidGtfsFacade);
//# sourceMappingURL=RopidGtfsFacade.js.map