import * as i0 from '@angular/core';
import { InjectionToken, Inject, Injectable, Input, Directive } from '@angular/core';
import { ArrayUtilities } from '@sd-angular/core/utilities/extensions';
import * as i1 from '@sd-angular/core/services/cache';

const SD_PERMISSION_CONFIGURATION = new InjectionToken('sd-permission.configuration');

class SdPermissionService {
    configuration;
    cacheService;
    #permission = {};
    #permissions;
    #loaded = false;
    constructor(configuration, cacheService) {
        this.configuration = configuration;
        this.cacheService = cacheService;
        this.#permissions = this.cacheService.create('212a51fa-38d5-43b2-bd46-922d85950ba3', {
            type: 'session',
            default: [],
        });
    }
    loadPermissions = async () => {
        if (!this.#loaded) {
            const permissions = await this.configuration.loadPermissions().catch(err => {
                console.error(err);
                return [];
            });
            this.#permissions.set(ArrayUtilities.distinct(permissions));
            // Chuyển thành Object để đảm bảo kiểm tra permisison không cần phải loop array
            this.#permission = {};
            permissions.forEach(permission => (this.#permission[permission] = true));
            this.#loaded = true;
        }
    };
    hasPermission = (permission) => {
        if (!permission?.toString()) {
            return true;
        }
        if (this.configuration.disabled) {
            return true;
        }
        const permissions = Array.isArray(permission) ? permission : [permission];
        return permissions.some(permission => this.#permission[permission]);
    };
    getToken = async () => {
        if (!this.configuration.getToken) {
            throw new Error('[Permission] Method getToken');
        }
        const token = this.configuration.getToken();
        if (token instanceof Promise) {
            return await token;
        }
        return token;
    };
    decodeToken = async () => {
        const token = await this.getToken();
        if (!token) {
            return null;
        }
        try {
            const payload = token.split('.')[1];
            const base64 = payload.replace(/-/g, '+').replace(/_/g, '/');
            const jsonPayload = decodeURIComponent(atob(base64)
                .split('')
                .map(c => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2))
                .join(''));
            return JSON.parse(jsonPayload);
        }
        catch (error) {
            console.error('Invalid token', error);
            return null;
        }
    };
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdPermissionService, deps: [{ token: SD_PERMISSION_CONFIGURATION }, { token: i1.SdCacheService }], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdPermissionService, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdPermissionService, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }], ctorParameters: () => [{ type: undefined, decorators: [{
                    type: Inject,
                    args: [SD_PERMISSION_CONFIGURATION]
                }] }, { type: i1.SdCacheService }] });

class SdPermissionDirective {
    templateRef;
    viewContainerRef;
    permissionService;
    // Nếu là mảng thì chỉ cần có 1 permission trong mảng đó xem như có quyền
    set sdPermission(permission) {
        // Nếu không gắn permisison thì render
        if (!permission?.toString()) {
            this.viewContainerRef.createEmbeddedView(this.templateRef);
            return;
        }
        // Kiểm tra permisison
        if (this.permissionService.hasPermission(permission)) {
            this.viewContainerRef.createEmbeddedView(this.templateRef);
        }
    }
    constructor(templateRef, viewContainerRef, permissionService) {
        this.templateRef = templateRef;
        this.viewContainerRef = viewContainerRef;
        this.permissionService = permissionService;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdPermissionDirective, deps: [{ token: i0.TemplateRef }, { token: i0.ViewContainerRef }, { token: SdPermissionService }], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.17", type: SdPermissionDirective, isStandalone: true, selector: "[sdPermission]", inputs: { sdPermission: "sdPermission" }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdPermissionDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[sdPermission]',
                }]
        }], ctorParameters: () => [{ type: i0.TemplateRef }, { type: i0.ViewContainerRef }, { type: SdPermissionService }], propDecorators: { sdPermission: [{
                type: Input
            }] } });

class SdPermissionGuard {
    configuration;
    permissionService;
    constructor(configuration, permissionService) {
        this.configuration = configuration;
        this.permissionService = permissionService;
    }
    canActivate = async (next, state) => {
        // Đảm bảo permission đã được loaded
        await this.permissionService.loadPermissions().catch(console.error);
        return true;
    };
    canActivateChild = async (activatedRoute, state) => {
        const permission = activatedRoute.data['permission'];
        if (this.permissionService.hasPermission(permission)) {
            return true;
        }
        //
        this.configuration?.onForbiden?.();
        return false;
    };
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdPermissionGuard, deps: [{ token: SD_PERMISSION_CONFIGURATION }, { token: SdPermissionService }], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdPermissionGuard, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdPermissionGuard, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }], ctorParameters: () => [{ type: undefined, decorators: [{
                    type: Inject,
                    args: [SD_PERMISSION_CONFIGURATION]
                }] }, { type: SdPermissionService }] });

/**
 * Generated bundle index. Do not edit.
 */

export { SD_PERMISSION_CONFIGURATION, SdPermissionDirective, SdPermissionGuard, SdPermissionService };
//# sourceMappingURL=sd-angular-core-guards-permission.mjs.map
