"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.InsideRestService = exports.InsideRestRepositoryProvider = void 0;
const tslib_1 = require("tslib");
const core_1 = require("@loopback/core");
const service_proxy_1 = require("@loopback/service-proxy");
const lodash_1 = require("lodash");
const application_service_1 = require("./../application.service");
const entity_intercept_service_1 = require("./../entity-intercept/entity-intercept.service");
const inside_rest_const_1 = require("./inside-rest.const");
const inside_rest_datasource_1 = require("./inside-rest.datasource");
const inside_rest_provider_1 = require("./inside-rest.provider");
let InsideRestRepositoryProvider = class InsideRestRepositoryProvider {
    constructor(
    // insideRest must match the name property in the datasource json file
    dataSource = new inside_rest_datasource_1.InsideRestDataSource()) {
        this.dataSource = dataSource;
    }
    value() {
        return service_proxy_1.getService(this.dataSource);
    }
};
InsideRestRepositoryProvider = tslib_1.__decorate([
    tslib_1.__param(0, core_1.inject(inside_rest_const_1.DATASTORE_INSIDE_REST)),
    tslib_1.__metadata("design:paramtypes", [inside_rest_datasource_1.InsideRestDataSource])
], InsideRestRepositoryProvider);
exports.InsideRestRepositoryProvider = InsideRestRepositoryProvider;
class InsideRestInterceptor {
    constructor(insideRestService) {
        this.insideRestService = insideRestService;
        this.providerId = inside_rest_const_1.INSIDE_REST_PROVIDER;
        this.serviceId = 'InsideRestService';
        this.description = 'Initialize Inside Rest call request cache';
    }
    async interceptRequest(ctx) {
        this.insideRestService.startSharedResults(ctx);
    }
}
class InsideRestFinalTreatment {
    constructor(insideRestService) {
        this.insideRestService = insideRestService;
        this.providerId = inside_rest_const_1.INSIDE_REST_PROVIDER;
        this.serviceId = 'InsideRestService';
        this.description = 'Free Inside Rest call request cache';
    }
    async finallyRequest(ctx) {
        this.insideRestService.endSharedResults(ctx);
    }
}
class InsideRestContext {
}
let InsideRestService = class InsideRestService {
    constructor(insideRestRepository, entityInterceptService, applicationService) {
        this.insideRestRepository = insideRestRepository;
        this.entityInterceptService = entityInterceptService;
        this.applicationService = applicationService;
        this.insideRestInterceptor = new InsideRestInterceptor(this);
        this.insideRestFinalTreatment = new InsideRestFinalTreatment(this);
        this.entityInterceptService.registerAllInterceptorService(this.insideRestInterceptor);
        this.entityInterceptService.registerAllFinalTreatmentService(this.insideRestFinalTreatment);
    }
    get runningRequestLoadedUris() {
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        const appCtx = this.applicationService.getExtensionContext(inside_rest_provider_1.InsideRestProvider);
        if (!('runningRequestLoadedUris' in appCtx)) {
            appCtx.runningRequestLoadedUris = {};
        }
        return appCtx.runningRequestLoadedUris;
    }
    getOpenedSessionId(ctx) {
        return lodash_1.isString(ctx.uriContext.uri.value.headers.sessionid) &&
            'null' !== ctx.uriContext.uri.value.headers.sessionid &&
            '' !== ctx.uriContext.uri.value.headers.sessionid &&
            'undefined' !== ctx.uriContext.uri.value.headers.sessionid
            ? ctx.uriContext.uri.value.headers.sessionid
            : undefined;
    }
    startSharedResults(ctx) {
        const insideRestCtx = this.getCtx(ctx);
        const sessionid = this.getOpenedSessionId(ctx);
        if (sessionid) {
            insideRestCtx.loadedUris = this.runningRequestLoadedUris[sessionid];
            insideRestCtx.id = sessionid;
            return;
        }
        insideRestCtx.id = '' + Math.ceil(Math.random() * 1000000000000000000000);
        this.runningRequestLoadedUris[insideRestCtx.id] = {};
        insideRestCtx.loadedUris = this.runningRequestLoadedUris[insideRestCtx.id];
    }
    endSharedResults(ctx) {
        if (this.getOpenedSessionId(ctx)) {
            return;
        }
        const insideRestCtx = this.getCtx(ctx);
        insideRestCtx.loadedUris = {};
        if (insideRestCtx.id && insideRestCtx.id in this.runningRequestLoadedUris) {
            delete this.runningRequestLoadedUris[insideRestCtx.id];
        }
    }
    getCtx(ctx) {
        if (!ctx.insideRestContext) {
            ctx.insideRestContext = {
                copyToChildContext: true,
                loadedUris: {},
            };
        }
        return ctx.insideRestContext;
    }
    getLoadedEntity(uriId, insideRestCtx) {
        if (uriId in insideRestCtx.loadedUris) {
            return insideRestCtx.loadedUris[uriId];
        }
        for (const runningRequest of Object.keys(this.runningRequestLoadedUris)) {
            if (uriId in this.runningRequestLoadedUris[runningRequest]) {
                return this.runningRequestLoadedUris[runningRequest][uriId];
            }
        }
        return undefined;
    }
    setLoadedEntity(entity, uriId, insideRestCtx) {
        for (const runningRequest of Object.keys(this.runningRequestLoadedUris)) {
            if (uriId in this.runningRequestLoadedUris[runningRequest]) {
                this.runningRequestLoadedUris[runningRequest][uriId] = entity;
            }
        }
        insideRestCtx.loadedUris[uriId] = entity;
        return insideRestCtx.loadedUris[uriId];
    }
    async read(uri, ctx, forceNewRead = false) {
        const uriId = uri +
            '-' +
            (lodash_1.isString(ctx.accessRightsContext.authorization.value)
                ? ctx.accessRightsContext.authorization.value
                : 'anonymous') +
            '-' +
            ctx.uriContext.uri.value.acceptLanguage;
        const insideRestCtx = this.getCtx(ctx);
        if (!forceNewRead) {
            const result = this.getLoadedEntity(uriId, insideRestCtx);
            if (result) {
                return result;
            }
        }
        try {
            return this.setLoadedEntity(await this.insideRestRepository.read(uri, ctx.accessRightsContext.authorization.value, ctx.uriContext.uri.value.acceptLanguage, insideRestCtx.id), uriId, insideRestCtx);
        }
        catch (error) {
            console.trace('failed to load', uriId, error);
            throw error;
        }
    }
};
InsideRestService = tslib_1.__decorate([
    core_1.injectable({ scope: core_1.BindingScope.SINGLETON }),
    tslib_1.__param(0, core_1.inject('services.InsideRestRepository')),
    tslib_1.__param(1, core_1.service(entity_intercept_service_1.EntityInterceptService)),
    tslib_1.__param(2, core_1.service(application_service_1.ApplicationService)),
    tslib_1.__metadata("design:paramtypes", [Object, entity_intercept_service_1.EntityInterceptService,
        application_service_1.ApplicationService])
], InsideRestService);
exports.InsideRestService = InsideRestService;
//# sourceMappingURL=inside-rest.service.js.map