"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const config_1 = __importDefault(require("config"));
const fs_1 = __importDefault(require("fs"));
const mongodb_memory_server_1 = require("mongodb-memory-server");
const mongoose_1 = __importStar(require("mongoose"));
const Logger_1 = __importStar(require("./Logger"));
const path_1 = __importDefault(require("path"));
class Datastore {
    static async setupLocalMongoDb(ip, port, path) {
        if (path) {
            fs_1.default.mkdirSync(path, {
                recursive: true
            });
        }
        Datastore.mongoMemoryServer = await mongodb_memory_server_1.MongoMemoryServer.create({
            instance: {
                port,
                ip,
                dbPath: path,
                storageEngine: path ? 'wiredTiger' : 'ephemeralForTest',
                auth: false
            }
        });
    }
    static async connectMongoDb(connectionString) {
        await mongoose_1.default.connect(connectionString, { dbName: Datastore.DB_NAME });
    }
    static setupDataModels() {
        this.logger.info('Setting up database models.');
        this.setupHealthCheckSchema();
        this.setupScanningRequestSchema();
        this.setupGenerationRequestSchema();
        this.setupDealStateSchema();
        this.setupReplicationRequestSchema();
        this.setupProviderMetricSchema();
        this.setupDealTrackingStateSchema();
        this.setupInputFileListSchema();
        this.setupOutputFileListSchema();
    }
    static setupOutputFileListSchema() {
        const generatedFileInfoSchema = new mongoose_1.Schema({
            path: mongoose_1.Schema.Types.String,
            size: mongoose_1.Schema.Types.Number,
            start: mongoose_1.Schema.Types.Number,
            end: mongoose_1.Schema.Types.Number,
            dir: mongoose_1.Schema.Types.Boolean,
            cid: mongoose_1.Schema.Types.String,
            selector: [mongoose_1.Schema.Types.Number]
        });
        const schema = new mongoose_1.Schema({
            generationId: {
                type: mongoose_1.Schema.Types.String,
                index: 1
            },
            index: mongoose_1.Schema.Types.Number,
            generatedFileList: [generatedFileInfoSchema]
        });
        Datastore.OutputFileListModel = mongoose_1.default.model('OutputFileList', schema);
    }
    static setupInputFileListSchema() {
        const fileInfoSchema = new mongoose_1.Schema({
            path: mongoose_1.Schema.Types.String,
            size: mongoose_1.Schema.Types.Number,
            start: mongoose_1.Schema.Types.Number,
            end: mongoose_1.Schema.Types.Number
        });
        const schema = new mongoose_1.Schema({
            generationId: {
                type: mongoose_1.Schema.Types.String,
                index: 1
            },
            index: mongoose_1.Schema.Types.Number,
            fileList: [fileInfoSchema]
        });
        Datastore.InputFileListModel = mongoose_1.default.model('InputFileList', schema);
    }
    static setupDealTrackingStateSchema() {
        const dealTrackingStateSchema = new mongoose_1.Schema({
            stateType: mongoose_1.Schema.Types.String,
            stateKey: mongoose_1.Schema.Types.String,
            stateValue: mongoose_1.Schema.Types.Mixed
        });
        Datastore.DealTrackingStateModel = mongoose_1.default.model('DealTrackingState', dealTrackingStateSchema);
    }
    static setupProviderMetricSchema() {
        const providerMetricSchema = new mongoose_1.Schema({
            provider: mongoose_1.Schema.Types.String,
            key: mongoose_1.Schema.Types.String,
            value: mongoose_1.Schema.Types.Mixed
        });
        Datastore.ProviderMetricModel = mongoose_1.default.model('ProviderMetric', providerMetricSchema);
    }
    static setupReplicationRequestSchema() {
        const replicationRequestSchema = new mongoose_1.Schema({
            datasetId: mongoose_1.Schema.Types.String,
            maxReplicas: mongoose_1.Schema.Types.Number,
            criteria: mongoose_1.Schema.Types.String,
            client: mongoose_1.Schema.Types.String,
            urlPrefix: mongoose_1.Schema.Types.String,
            maxPrice: mongoose_1.Schema.Types.Number,
            maxNumberOfDeals: mongoose_1.Schema.Types.Number,
            isVerfied: mongoose_1.Schema.Types.Boolean,
            duration: mongoose_1.Schema.Types.Number,
            isOffline: mongoose_1.Schema.Types.Boolean,
            status: mongoose_1.Schema.Types.String,
            errorMessage: mongoose_1.Schema.Types.String
        }, {
            timestamps: true
        });
        Datastore.ReplicationRequestModel = mongoose_1.default.model('ReplicationRequest', replicationRequestSchema);
    }
    static setupDealStateSchema() {
        const dealStateSchema = new mongoose_1.Schema({
            client: mongoose_1.Schema.Types.String,
            provider: mongoose_1.Schema.Types.String,
            dealCid: mongoose_1.Schema.Types.String,
            dataCid: mongoose_1.Schema.Types.String,
            pieceCid: mongoose_1.Schema.Types.String,
            expiration: mongoose_1.Schema.Types.Number,
            duration: mongoose_1.Schema.Types.Number,
            price: mongoose_1.Schema.Types.Number,
            verified: mongoose_1.Schema.Types.Boolean,
            state: {
                type: mongoose_1.Schema.Types.String,
                index: true
            },
            replicationRequestId: mongoose_1.Schema.Types.String,
            datasetId: mongoose_1.Schema.Types.String,
            dealId: {
                type: mongoose_1.Schema.Types.Number,
                index: true
            },
            errorMessage: mongoose_1.Schema.Types.String
        }, {
            timestamps: true
        });
        dealStateSchema.index({ pieceCid: 1, provider: 1, client: 1, state: 1 });
        dealStateSchema.index({ client: 1, state: 1 });
        dealStateSchema.index({ pieceCid: 1, state: 1 });
        Datastore.DealStateModel = mongoose_1.default.model('DealState', dealStateSchema);
    }
    static setupGenerationRequestSchema() {
        const generationRequestSchema = new mongoose_1.Schema({
            datasetId: mongoose_1.Schema.Types.String,
            datasetName: mongoose_1.Schema.Types.String,
            path: mongoose_1.Schema.Types.String,
            index: mongoose_1.Schema.Types.Number,
            outDir: mongoose_1.Schema.Types.String,
            workerId: {
                type: mongoose_1.Schema.Types.String,
                index: 1
            },
            status: mongoose_1.Schema.Types.String,
            errorMessage: mongoose_1.Schema.Types.String,
            dataCid: mongoose_1.Schema.Types.String,
            carSize: mongoose_1.Schema.Types.Number,
            pieceCid: mongoose_1.Schema.Types.String,
            pieceSize: mongoose_1.Schema.Types.Number,
            filenameOverride: mongoose_1.Schema.Types.String,
            tmpDir: mongoose_1.Schema.Types.String
        }, {
            timestamps: true
        });
        Datastore.GenerationRequestModel = mongoose_1.default.model('GenerationRequest', generationRequestSchema);
    }
    static setupScanningRequestSchema() {
        const scanningRequestSchema = new mongoose_1.Schema({
            name: {
                type: mongoose_1.Schema.Types.String,
                unique: true
            },
            path: mongoose_1.Schema.Types.String,
            minSize: mongoose_1.Schema.Types.Number,
            maxSize: mongoose_1.Schema.Types.Number,
            outDir: mongoose_1.Schema.Types.String,
            workerId: {
                type: mongoose_1.Schema.Types.String,
                index: 1
            },
            status: mongoose_1.Schema.Types.String,
            errorMessage: mongoose_1.Schema.Types.String,
            tmpDir: mongoose_1.Schema.Types.String
        }, {
            timestamps: true
        });
        Datastore.ScanningRequestModel = mongoose_1.default.model('ScanningRequest', scanningRequestSchema);
    }
    static setupHealthCheckSchema() {
        const healthCheckSchema = new mongoose_1.Schema({
            workerId: {
                type: mongoose_1.Schema.Types.String,
                index: true,
                unique: true
            },
            updatedAt: {
                type: mongoose_1.Schema.Types.Date,
                index: 1,
                expires: 60
            }
        }, {
            timestamps: true
        });
        Datastore.HealthCheckModel = mongoose_1.default.model('HealthCheck', healthCheckSchema);
    }
    static async init(inMemory) {
        if (config_1.default.has('database.start_local') && config_1.default.get('database.start_local')) {
            const localPath = config_1.default.has('database.local_path') ? path_1.default.resolve(process.env.NODE_CONFIG_DIR, config_1.default.get('database.local_path')) : undefined;
            await Datastore.setupLocalMongoDb(config_1.default.get('database.local_bind'), config_1.default.get('database.local_port'), inMemory ? undefined : localPath);
        }
    }
    static async connect() {
        if (config_1.default.has('connection.database')) {
            await Datastore.connectMongoDb(config_1.default.get('connection.database'));
            Datastore.setupDataModels();
        }
    }
}
exports.default = Datastore;
Datastore.logger = Logger_1.default.getLogger(Logger_1.Category.Database);
Datastore.DB_NAME = 'singularity';
//# sourceMappingURL=Datastore.js.map