import * as i0 from '@angular/core';
import { inject, Injector, Injectable, InjectionToken, NgModule } from '@angular/core';
import { AXPSessionService, AXP_PERMISSION_DEFINITION_PROVIDER } from '@acorex/platform/auth';
import { AXPSearchCommandProvider, AXP_MENU_PROVIDER, AXP_SETTING_DEFINITION_PROVIDER, AXP_SEARCH_PROVIDER } from '@acorex/platform/common';
import { AXPEntityService, AXP_ENTITY_ACTION_PLUGIN, AXP_ENTITY_DEFINITION_LOADER } from '@acorex/platform/layout/entity';
import { AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, AXPDataGenerator } from '@acorex/platform/core';

const config = {
    i18n: 'identifier-management',
};
const RootConfig = {
    config,
    module: {
        module: 'identifier-management',
        name: 'IdentifierManagement',
        title: `t('module-name', {scope:"${config.i18n}"})`,
        icon: 'fa-light fa-file-invoice',
    },
    entities: {
    // category: {
    //   name: 'Category',
    //  title: 't("category", { scope: "common" })',
    //  icon: 'fa-light fa-list'
    // },
    },
};

class AXMMenuProvider {
    constructor() {
        this.entityService = inject(AXPEntityService);
    }
    async provide(context) {
        const scope = RootConfig.config.i18n;
        const module = RootConfig.module;
        // context.addItems([
        //   {
        //     priority: 9001,
        //     text: `t('module-name', {scope:"${scope}"})`,
        //     icon: module.icon,
        //     children: [
        //       {
        //         text: `t("entity-name", { scope: "common" })`,
        //         path: this.entityService.createPath(module.name, RootConfig.entities.category.name),
        //         icon: RootConfig.entities.category.icon,
        //         priority: 1,
        //       }
        //     ],
        //   },
        // ]);
    }
}

class AXMEntityProvider {
    constructor() {
        this.injector = inject(Injector);
    }
    preload() {
        const module = RootConfig.module.name;
        return Array.from(Object.values(RootConfig.entities)).map((entity) => ({
            module: module,
            entity: entity.name,
        }));
    }
    async get(moduleName, entityName) {
        if (moduleName == RootConfig.module.name) {
            switch (entityName
            // case RootConfig.entities.sample.name:
            //   return (await import('./entities/sample/sample.entity')).factory(this.injector);
            ) {
            }
        }
        return null;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: AXMEntityProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: AXMEntityProvider }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: AXMEntityProvider, decorators: [{
            type: Injectable
        }] });

class AXMPermissionDefinitionProvider {
    async define(context) {
        // context.addPermissions([
        //   {
        //     name: 'view_templates',
        //     title: 'Permission to view templates',
        //     isArchived: false,
        //   },
        // ]);
    }
}

class AXMSettingProvider {
    async provide(context) {
        // context
        //   // Add Form Template Group
        //   .addGroup('form-template', 'Form Template', 'Settings related to form templates.', RootConfig.module.icon)
        //   // Start Interface Section
        //   .addSection('interface', 'UI Interface', 'Customize the user interface for forms.')
        //   .addSetting({
        //     key: 'history-panel',
        //     title: 'Show History Panel',
        //     scope: 'U',
        //     isInherited: true,
        //     defaultValue: false,
        //     widget: {
        //       type: AXPWidgetsCatalog.toggle,
        //     },
        //     description: 'Enable or disable the history panel for forms.',
        //     validationRules: [
        //       {
        //         rule: 'required',
        //       },
        //     ],
        //   })
        //   .endSection()
        //   .endGroup();
    }
}

class AXMSearchCommandProvider extends AXPSearchCommandProvider {
    constructor() {
        super(...arguments);
        this.commands = [
        // {
        //   group: 'command',
        //  title: 'New Form Template',
        //  icon: RootConfig.entities.template.icon,
        //  description: 'Create a new form template for designing reusable forms.', // Added description
        //  commands: {
        //    'create-entity': {
        //      entity: `${RootConfig.module.name}.${RootConfig.entities.template.name}`,
        //    },
        //  },
        // }
        ];
    }
}

//#region ----   Imports   ----
//#endregion
//#region ----   Main Port (UI)   ----
class AXPIdentifierService {
}
const AXP_IDENTIFIER_SERVICE = new InjectionToken('AXP_IDENTIFIER_SERVICE');
//#endregion
//#region ----   DI Tokens   ----
const AXP_IDENTIFIER_RULES = new InjectionToken('AXP_IDENTIFIER_RULES');
//#endregion

class AXMIdentifierEvaluatorScopeProvider {
    constructor() {
        this.identifierService = inject(AXP_IDENTIFIER_SERVICE);
        this.sessionService = inject(AXPSessionService);
    }
    async provide(context) {
        context.addScope('identifier', {
            peek: async (id) => {
                const identifier = await this.identifierService.peek({
                    id,
                    tenantId: this.sessionService.tenant?.id,
                    appId: this.sessionService.application?.id,
                });
                return identifier.code;
            },
            generate: async (id) => {
                const identifier = await this.identifierService.generate({
                    id,
                    tenantId: this.sessionService.tenant?.id,
                    appId: this.sessionService.application?.id,
                });
                return identifier.code;
            }
        });
    }
}

const identifierPlugin = {
    name: 'identifier',
    order: 40,
    apply: (ctx, options) => {
        if (!options?.field || !options?.rule)
            return;
        ctx.properties.find(options.field).update((p) => {
            const next = { ...p };
            next.schema = { ...(next.schema ?? {}) };
            next.schema.defaultValue = `{{ identifier.peek("${options.rule}") }}`;
            return next;
        });
        ctx.entity.extensions ??= {};
        ctx.entity.extensions.identifier = { field: options.field, rule: options.rule };
    },
};

class AXMIdentifierManagementModule {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: AXMIdentifierManagementModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.4", ngImport: i0, type: AXMIdentifierManagementModule }); }
    static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: AXMIdentifierManagementModule, providers: [
            {
                provide: AXP_ENTITY_ACTION_PLUGIN,
                useValue: identifierPlugin,
                multi: true,
            },
            {
                provide: AXP_MENU_PROVIDER,
                useClass: AXMMenuProvider,
                multi: true,
            },
            {
                provide: AXP_ENTITY_DEFINITION_LOADER,
                useClass: AXMEntityProvider,
                multi: true,
            },
            {
                provide: AXP_SETTING_DEFINITION_PROVIDER,
                useClass: AXMSettingProvider,
                multi: true,
            },
            {
                provide: AXP_SEARCH_PROVIDER,
                useClass: AXMSearchCommandProvider,
                multi: true,
            },
            {
                provide: AXP_PERMISSION_DEFINITION_PROVIDER,
                useClass: AXMPermissionDefinitionProvider,
                multi: true,
            },
            {
                provide: AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER,
                useClass: AXMIdentifierEvaluatorScopeProvider,
                multi: true,
            },
        ] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: AXMIdentifierManagementModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [],
                    exports: [],
                    declarations: [],
                    providers: [
                        {
                            provide: AXP_ENTITY_ACTION_PLUGIN,
                            useValue: identifierPlugin,
                            multi: true,
                        },
                        {
                            provide: AXP_MENU_PROVIDER,
                            useClass: AXMMenuProvider,
                            multi: true,
                        },
                        {
                            provide: AXP_ENTITY_DEFINITION_LOADER,
                            useClass: AXMEntityProvider,
                            multi: true,
                        },
                        {
                            provide: AXP_SETTING_DEFINITION_PROVIDER,
                            useClass: AXMSettingProvider,
                            multi: true,
                        },
                        {
                            provide: AXP_SEARCH_PROVIDER,
                            useClass: AXMSearchCommandProvider,
                            multi: true,
                        },
                        {
                            provide: AXP_PERMISSION_DEFINITION_PROVIDER,
                            useClass: AXMPermissionDefinitionProvider,
                            multi: true,
                        },
                        {
                            provide: AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER,
                            useClass: AXMIdentifierEvaluatorScopeProvider,
                            multi: true,
                        },
                    ]
                }]
        }] });

//#region ----   Token Contracts   ----
//#endregion
//#region ----   DI Tokens   ----
const AXP_TOKEN_HANDLERS = new InjectionToken('AXP_TOKEN_HANDLERS');
//#endregion

//#region ----   Imports   ----
//#endregion
class AXPTokenRegistryService {
    constructor() {
        //#region ----   Fields   ----
        this.handlers = new Map();
        this.providerHandlers = inject(AXP_TOKEN_HANDLERS, { optional: true }) ?? [];
    }
    //#endregion
    //#region ----   Public API   ----
    register(handler) {
        const existing = this.handlers.get(handler.name);
        if (!existing || (handler.priority ?? 0) > (existing.priority ?? 0)) {
            this.handlers.set(handler.name, handler);
        }
    }
    unregister(name) {
        this.handlers.delete(name);
    }
    get(name) {
        // provider-provided take precedence by priority
        const fromProviders = this.providerHandlers
            .filter((h) => h.name === name)
            .sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0))[0];
        if (fromProviders)
            return fromProviders;
        return this.handlers.get(name);
    }
    list() {
        const map = new Map();
        const put = (h) => {
            const prev = map.get(h.name);
            if (!prev || (h.priority ?? 0) > (prev.priority ?? 0))
                map.set(h.name, h);
        };
        this.providerHandlers.forEach(put);
        Array.from(this.handlers.values()).forEach(put);
        return Array.from(map.values()).sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: AXPTokenRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: AXPTokenRegistryService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: AXPTokenRegistryService, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }] });

//#region ----   Imports   ----
//#endregion
//#region ----   Simple Pattern Engine Impl   ----
const TOKEN_REGEX = /\{([^{}]+)\}/g; // matches {token[:args]}
class AXPSimplePatternEngine {
    constructor() {
        this.registry = inject(AXPTokenRegistryService);
    }
    compile(pattern) {
        const tokens = [];
        let match;
        let index = 0;
        let lastIndex = 0;
        while ((match = TOKEN_REGEX.exec(pattern)) !== null) {
            // push any literal text before this token
            const literal = pattern.slice(lastIndex, match.index);
            if (literal) {
                tokens.push({ type: 'literal', text: literal });
            }
            const raw = match[0];
            const inner = match[1];
            const [name, ...args] = inner.split(':');
            const token = {
                name: name.trim(),
                args: args.length ? inner.substring(inner.indexOf(':') + 1).split(':') : [],
                raw,
                index: index++,
            };
            const handler = this.registry.get(token.name);
            if (!handler) {
                throw new Error(`Unknown token: ${token.name}`);
            }
            handler.validate?.(token);
            tokens.push(token);
            lastIndex = match.index + raw.length;
        }
        // trailing literal
        const tail = pattern.slice(lastIndex);
        if (tail) {
            tokens.push({ type: 'literal', text: tail });
        }
        return { pattern, tokens };
    }
    async evaluate(compiled, ctx) {
        let built = '';
        for (const frag of compiled.tokens) {
            if (frag.type === 'literal') {
                built += frag.text;
                continue;
            }
            const token = frag;
            ctx.cache.set('__acc__', built);
            const handler = this.registry.get(token.name);
            if (!handler) {
                throw new Error(`Unknown token at eval: ${token.name}`);
            }
            const fragment = await handler.eval(token, ctx);
            built += fragment;
        }
        return built;
    }
}
//#endregion

//#region ----   Imports   ----
//#endregion
//#region ----   Utility Functions   ----
function buildScopeHash(parts) {
    return parts.filter(Boolean).join('|');
}
function padNumber(num, size) {
    const s = String(num);
    if (s.length >= size)
        return s;
    return '0'.repeat(size - s.length) + s;
}
function uuid() {
    return AXPDataGenerator.uuid();
}
//#endregion

//#endregion
//#region ----   Built-in Token Handlers (Injectable)   ----
class DateToken {
    constructor() {
        this.name = 'date';
        this.meta = { title: 'Date', description: 'Formats current date', argHints: ['YYYY', 'YYYYMM', 'YYYYMMDD'] };
    }
    async eval(token, ctx) {
        const fmt = token.args[0] ?? 'YYYYMMDD';
        const d = ctx.services.clock?.now() ?? ctx.now;
        const y = String(d.getFullYear());
        const m = padNumber(d.getMonth() + 1, 2);
        const day = padNumber(d.getDate(), 2);
        switch (fmt) {
            case 'YYYY':
                return y;
            case 'YYYYMM':
                return y + m;
            case 'YYYYMMDD':
            default:
                return y + m + day;
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: DateToken, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: DateToken }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: DateToken, decorators: [{
            type: Injectable
        }] });
class ConstToken {
    constructor() {
        this.name = 'const';
        this.meta = { title: 'Constant', description: 'Fixed literal value' };
    }
    async eval(token) {
        return token.args.join(':');
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: ConstToken, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: ConstToken }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: ConstToken, decorators: [{
            type: Injectable
        }] });
class FieldToken {
    constructor() {
        this.name = 'field';
        this.meta = { title: 'Field', description: 'Reads a value from request.payload' };
    }
    async eval(token, ctx) {
        const key = token.args[0];
        if (!key)
            return '';
        const value = ctx.request.payload?.[key];
        return value == null ? '' : String(value);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: FieldToken, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: FieldToken }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: FieldToken, decorators: [{
            type: Injectable
        }] });
class TenantToken {
    constructor() {
        this.name = 'tenant';
        this.meta = { title: 'Tenant', description: 'Tenant scope identifier' };
    }
    async eval(_t, ctx) {
        return ctx.request.tenantId ?? '';
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: TenantToken, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: TenantToken }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: TenantToken, decorators: [{
            type: Injectable
        }] });
class AppToken {
    constructor() {
        this.name = 'app';
        this.meta = { title: 'App', description: 'Application scope identifier' };
    }
    async eval(_t, ctx) {
        return ctx.request.appId ?? '';
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: AppToken, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: AppToken }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: AppToken, decorators: [{
            type: Injectable
        }] });
class SeqToken {
    constructor() {
        this.name = 'seq';
        this.meta = { title: 'Sequence', description: 'Auto-increment sequence', argHints: ['pad'] };
    }
    async eval(token, ctx) {
        const pad = Number(token.args[0] ?? '0') || 0;
        const consume = ctx.evaluationMode === 'commit';
        const ruleId = ctx.cache.get('ruleId');
        const n = await ctx.services.sequence.next(ctx.cache.get('scopeHash'), ruleId, { pad, consume });
        return pad ? padNumber(n, pad) : String(n);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: SeqToken, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: SeqToken }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: SeqToken, decorators: [{
            type: Injectable
        }] });
class CheckToken {
    constructor() {
        this.name = 'check';
        this.meta = { title: 'Checksum', description: 'Checksum of the string built so far', argHints: ['luhn|mod11'] };
    }
    async eval(token, ctx) {
        const algo = token.args[0] ?? 'luhn';
        const acc = String(ctx.cache.get('__acc__') ?? '');
        return ctx.services.checksum.compute(algo, acc);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: CheckToken, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: CheckToken }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: CheckToken, decorators: [{
            type: Injectable
        }] });

const AXP_DEFAULT_TOKEN_PROVIDERS = [
    { provide: AXP_TOKEN_HANDLERS, useClass: DateToken, multi: true },
    { provide: AXP_TOKEN_HANDLERS, useClass: ConstToken, multi: true },
    { provide: AXP_TOKEN_HANDLERS, useClass: FieldToken, multi: true },
    { provide: AXP_TOKEN_HANDLERS, useClass: TenantToken, multi: true },
    { provide: AXP_TOKEN_HANDLERS, useClass: AppToken, multi: true },
    { provide: AXP_TOKEN_HANDLERS, useClass: SeqToken, multi: true },
    { provide: AXP_TOKEN_HANDLERS, useClass: CheckToken, multi: true },
];

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

export { AXMEntityProvider, AXMIdentifierManagementModule, AXMMenuProvider, AXMSearchCommandProvider, AXMSettingProvider, AXPIdentifierService, AXPSimplePatternEngine, AXPTokenRegistryService, AXP_DEFAULT_TOKEN_PROVIDERS, AXP_IDENTIFIER_RULES, AXP_IDENTIFIER_SERVICE, AXP_TOKEN_HANDLERS, AppToken, CheckToken, ConstToken, DateToken, FieldToken, RootConfig, SeqToken, TenantToken, buildScopeHash, padNumber, uuid };
//# sourceMappingURL=acorex-modules-identifier-management.mjs.map
