"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.MagicInterceptor = void 0;
const core_1 = require("@midwayjs/core");
const constant_1 = require("../constant");
const core_2 = require("./core");
const definition_1 = require("./definition");
const magic_api_1 = require("./magic.api");
let MagicInterceptor = class MagicInterceptor {
    constructor() {
        this.type = 'interceptor';
        this.interceptorMap = new Map();
        this.idInMappingPath = new Map();
        /**
         * 最终生成的拦截器数组
         */
        this.cacheMiddlewares = [];
    }
    async init(reInit = false) {
        if (reInit) {
            this.logger.info('重新初始化MagicInterceptor');
            this.interceptorMap.clear();
            this.idInMappingPath.clear();
        }
        else {
            this.logger.info('初始化MagicInterceptor');
        }
        const resources = await this.magicResourceService.findByType(constant_1.RESOURCE_TYPE.Interceptor);
        for (const resource of resources) {
            await this.add(resource);
        }
    }
    /**
     * 添加拦截器
     * @param resource
     */
    async add(resource) {
        const { id, definition } = resource;
        const { sort } = definition;
        await this.removeById(id);
        const mappingPath = await this.magicResourceService.getMappingPath(resource);
        const interceptorDefinition = (0, definition_1.InterceptorDefinition)(resource.script);
        this.interceptorMap.set(mappingPath, {
            sort,
            value: async (ctx, next) => {
                const route = this.magicApi.getRouterSpec(ctx.method, ctx.path);
                return await (0, definition_1.InterceptorHandler)(ctx, next, route, interceptorDefinition);
            },
        });
        this.idInMappingPath.set(id, mappingPath);
        this.calcCacheMiddleware();
        this.logger.info('注册拦截器:[%s]', mappingPath);
    }
    /**
     * 删除拦截器
     * @param id
     */
    async removeById(id) {
        if (this.idInMappingPath.has(id)) {
            const mappingPath = this.idInMappingPath.get(id);
            this.idInMappingPath.delete(id);
            if (this.interceptorMap.has(mappingPath)) {
                this.interceptorMap.delete(mappingPath);
                this.calcCacheMiddleware();
                this.logger.info('删除拦截器成功:[%s]', mappingPath);
            }
        }
    }
    /**
     * 拦截器变化时重新计算拦截器顺序
     */
    calcCacheMiddleware() {
        this.cacheMiddlewares = [...this.interceptorMap.values()]
            .sort((a, b) => {
            if (a.sort < b.sort) {
                return -1;
            }
            if (a.sort > b.sort) {
                return 1;
            }
            return 0;
        })
            .map(v => v.value);
    }
    /**
     * 拦截器中间件
     */
    middleware() {
        return async (ctx, next) => {
            return await (await this.middlewareService.compose(this.cacheMiddlewares, (0, core_1.getCurrentMainApp)()))(ctx, next);
        };
    }
};
__decorate([
    (0, core_1.Inject)(),
    __metadata("design:type", core_2.MagicResourceService)
], MagicInterceptor.prototype, "magicResourceService", void 0);
__decorate([
    (0, core_1.Logger)('magic'),
    __metadata("design:type", Object)
], MagicInterceptor.prototype, "logger", void 0);
__decorate([
    (0, core_1.Inject)(),
    __metadata("design:type", core_1.MidwayMiddlewareService)
], MagicInterceptor.prototype, "middlewareService", void 0);
__decorate([
    (0, core_1.Inject)(),
    __metadata("design:type", magic_api_1.MagicApi)
], MagicInterceptor.prototype, "magicApi", void 0);
MagicInterceptor = __decorate([
    (0, core_1.Provide)(),
    (0, core_1.Scope)(core_1.ScopeEnum.Singleton)
], MagicInterceptor);
exports.MagicInterceptor = MagicInterceptor;
