"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.MagicDataSource = void 0;
const core_1 = require("@midwayjs/core");
const constant_1 = require("../constant");
const core_2 = require("./core");
let MagicDataSource = class MagicDataSource {
    constructor() {
        this.type = 'datasource';
        this.idInMappingPath = new Map();
    }
    async init(reInit = false) {
        if (reInit) {
            this.logger.info('重新初始化MagicDataSource');
            for (const key of this.idInMappingPath.keys()) {
                await this.removeById(key);
            }
            this.idInMappingPath.clear();
        }
        else {
            this.logger.info('初始化MagicDataSource');
        }
        const resources = await this.magicResourceService.findByType(constant_1.RESOURCE_TYPE.DataSource);
        for (const resource of resources) {
            await this.add(resource);
        }
    }
    /**
     * 添加数据源
     * @param resource
     * @param isThrow 是否抛出异常
     */
    async add(resource, isThrow = false) {
        await this.removeById(resource.id);
        const { id, fileName, method, path } = resource;
        const { username, password, port, host, database, dialect, printSql, options, } = resource.definition;
        let _options;
        try {
            _options = JSON.parse(options || '{}');
        }
        catch (_a) {
            _options = {};
        }
        try {
            await this.dataSourceManager.createInstance({
                _dialect: dialect,
                _name: fileName,
                _key: path,
                _printSql: printSql,
                type: method,
                username,
                password,
                port,
                host,
                database,
                ..._options,
            }, path);
            this.idInMappingPath.set(id, path);
            this.logger.info('注册数据源:[%s %s]', fileName, path);
        }
        catch (e) {
            await this.removeById(id);
            this.logger.error('注册数据源失败[%s %s]：%s', fileName, path, e.message);
            if (isThrow) {
                throw e;
            }
        }
    }
    /**
     * 删除数据源
     * @param id 资源id
     */
    async removeById(id) {
        if (this.idInMappingPath.has(id)) {
            const mappingPath = this.idInMappingPath.get(id);
            this.idInMappingPath.delete(id);
            if (this.dataSourceManager.hasDataSource(mappingPath)) {
                const dataSource = this.dataSourceManager.getDataSource(mappingPath);
                await this.dataSourceManager.destroyDataSource(dataSource);
                this.dataSourceManager.dataSource.delete(mappingPath);
                this.logger.info('删除数据源成功:[%s]', mappingPath);
            }
        }
    }
    /**
     * 数据源是否连接
     * @param dataSourceName
     */
    async checkConnected(dataSourceName) {
        return await this.dataSourceManager.isConnected(dataSourceName);
    }
    /**
     * 获取默认数据源
     */
    getDefaultDataSource() {
        return this.getDataSource('default');
    }
    /**
     * 获取所有数据源key
     */
    getDataSourceNames() {
        return this.dataSourceManager
            .getDataSourceNames()
            .filter(key => key !== 'default');
    }
    /**
     * 获取数据源
     * @param dataSourceName
     */
    getDataSource(dataSourceName) {
        return this.dataSourceManager.getDataSource(dataSourceName);
    }
    /**
     * 测试数据源
     * @param resource
     */
    async testDataSource(resource) {
        resource.id = resource.path = '___TEST___';
        await this.add(resource, true);
        await this.removeById(resource.path);
    }
    /**
     * 生成定义
     */
    generateSpec() {
        return `declare interface SQLModule {
  ${this.getDataSourceNames()
            .map(m => `${m}: SQLModule;`)
            .join('\r\n')}
}`;
    }
};
__decorate([
    (0, core_1.Inject)('typeOrmDataSourceManager'),
    __metadata("design:type", Object)
], MagicDataSource.prototype, "dataSourceManager", void 0);
__decorate([
    (0, core_1.Inject)(),
    __metadata("design:type", core_2.MagicResourceService)
], MagicDataSource.prototype, "magicResourceService", void 0);
__decorate([
    (0, core_1.Logger)('magic'),
    __metadata("design:type", Object)
], MagicDataSource.prototype, "logger", void 0);
MagicDataSource = __decorate([
    (0, core_1.Provide)(),
    (0, core_1.Scope)(core_1.ScopeEnum.Singleton)
], MagicDataSource);
exports.MagicDataSource = MagicDataSource;
