import { MXInputBaseValueComponent, MXLookComponent, AXComponent, AXFocusableComponent, AXValuableComponent } from '@acorex/cdk/common';
import * as i3 from '@acorex/components/form';
import { AXFormModule } from '@acorex/components/form';
import { AXSelectBoxModule } from '@acorex/components/select-box';
import * as i1 from '@acorex/components/text-box';
import { AXTextBoxModule } from '@acorex/components/text-box';
import { AXTimeDurationFormatter } from '@acorex/core/date-time';
import { AXTranslationService } from '@acorex/core/translation';
import * as i0 from '@angular/core';
import { input, signal, inject, afterNextRender, effect, forwardRef, HostBinding, ViewEncapsulation, ChangeDetectionStrategy, Component, NgModule } from '@angular/core';
import * as i2 from '@angular/forms';
import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
import { classes } from 'polytype';

class AXTimeDurationComponent extends classes((MXInputBaseValueComponent), MXLookComponent) {
    constructor() {
        super(...arguments);
        this.valueStart = input('YEAR', ...(ngDevMode ? [{ debugName: "valueStart" }] : []));
        this.valueEnd = input('MILLISECOND', ...(ngDevMode ? [{ debugName: "valueEnd" }] : []));
        this.label = input(true, ...(ngDevMode ? [{ debugName: "label" }] : []));
        this.maskDigits = input('00:00:00:00:00:00:00:000', ...(ngDevMode ? [{ debugName: "maskDigits" }] : []));
        this.minValue = input(null, ...(ngDevMode ? [{ debugName: "minValue" }] : []));
        this.maxValue = input(null, ...(ngDevMode ? [{ debugName: "maxValue" }] : []));
        this.mask = signal(null, ...(ngDevMode ? [{ debugName: "mask" }] : []));
        this.maskPlaceHolder = signal(null, ...(ngDevMode ? [{ debugName: "maskPlaceHolder" }] : []));
        this.translationService = inject(AXTranslationService);
        this.timeDurationFormatter = inject(AXTimeDurationFormatter);
        this.onInputFire = false;
        this.onInternalValueChangedFire = false;
        this.YEAR = signal(null, ...(ngDevMode ? [{ debugName: "YEAR" }] : []));
        this.MONTH = signal(null, ...(ngDevMode ? [{ debugName: "MONTH" }] : []));
        this.WEEK = signal(null, ...(ngDevMode ? [{ debugName: "WEEK" }] : []));
        this.DAY = signal(null, ...(ngDevMode ? [{ debugName: "DAY" }] : []));
        this.HOUR = signal(null, ...(ngDevMode ? [{ debugName: "HOUR" }] : []));
        this.MINUTE = signal(null, ...(ngDevMode ? [{ debugName: "MINUTE" }] : []));
        this.SECOND = signal(null, ...(ngDevMode ? [{ debugName: "SECOND" }] : []));
        this.MILLISECOND = signal(null, ...(ngDevMode ? [{ debugName: "MILLISECOND" }] : []));
        this.isTranslationInit = signal(false, ...(ngDevMode ? [{ debugName: "isTranslationInit" }] : []));
        this.#init = afterNextRender(async () => {
            await this.initTranslation();
        });
        this.#effect = effect(() => {
            // Depend on label as well
            void this.label();
            if (this.valueStart() && this.valueEnd() && this.isTranslationInit()) {
                this.updateMask();
            }
        }, ...(ngDevMode ? [{ debugName: "#effect" }] : []));
        this.validateFn = async (val) => {
            if (this.minValue() && this.minValue() > val) {
                const normalizedMaskMin = await this.timeDurationFormatter.millisecondsToMask(this.minValue(), this.valueStart(), this.valueEnd(), true, this.maskDigits(), true);
                const message = await this.translationService.translateAsync('@acorex:validation.messages.min', {
                    params: { value: normalizedMaskMin },
                });
                return {
                    rule: 'callback',
                    result: false,
                    message,
                    value: val,
                };
            }
            if (this.maxValue() && this.maxValue() < val) {
                const normalizedMaskMax = await this.timeDurationFormatter.millisecondsToMask(this.maxValue(), this.valueStart(), this.valueEnd(), true, this.maskDigits(), true);
                const message = await this.translationService.translateAsync('@acorex:validation.messages.max', {
                    params: { value: normalizedMaskMax },
                });
                return {
                    rule: 'callback',
                    result: false,
                    message,
                    value: val,
                };
            }
            return {
                rule: 'callback',
                result: true,
                value: val,
            };
        };
    }
    #init;
    #effect;
    async initTranslation() {
        this.YEAR.set((await this.translationService.translateAsync('@acorex:dateTime.units.year')).toLocaleUpperCase());
        this.MONTH.set((await this.translationService.translateAsync('@acorex:dateTime.units.month')).toLocaleUpperCase());
        this.WEEK.set((await this.translationService.translateAsync('@acorex:dateTime.units.week')).toLocaleUpperCase());
        this.DAY.set((await this.translationService.translateAsync('@acorex:dateTime.units.day')).toLocaleUpperCase());
        this.HOUR.set((await this.translationService.translateAsync('@acorex:dateTime.units.hour')).toLocaleUpperCase());
        this.MINUTE.set((await this.translationService.translateAsync('@acorex:dateTime.units.minute')).toLocaleUpperCase());
        this.SECOND.set((await this.translationService.translateAsync('@acorex:dateTime.units.second')).toLocaleUpperCase());
        this.MILLISECOND.set((await this.translationService.translateAsync('@acorex:dateTime.units.millisecond')).toLocaleUpperCase());
        this.isTranslationInit.set(true);
    }
    async onInput(event) {
        if (this.disabled)
            return;
        if (this.onInternalValueChangedFire)
            return;
        this.onInputFire = true;
        const milliseconds = this.maskToMilliseconds(event.value);
        this.commitValue(milliseconds, true);
        this.onInputFire = false;
    }
    async internalValueChanged(value) {
        if (this.disabled)
            return;
        if (this.onInputFire)
            return;
        this.onInternalValueChangedFire = true;
        const normalizedMask = await this.timeDurationFormatter.millisecondsToMask(value, this.valueStart(), this.valueEnd(), this.label(), this.maskDigits(), true);
        this.inputValue = normalizedMask;
        setTimeout(() => {
            this.onInternalValueChangedFire = false;
        });
    }
    replacePersianLabels(input) {
        const replacements = {
            [this.YEAR()]: 'YEAR',
            [this.MONTH()]: 'MONTH',
            [this.WEEK()]: 'WEEK',
            [this.DAY()]: 'DAY',
            [this.HOUR()]: 'HOUR',
            [this.MINUTE()]: 'MINUTE',
            [this.SECOND()]: 'SECOND',
            [this.MILLISECOND()]: 'MILLISECOND',
        };
        return Object.entries(replacements).reduce((str, [fa, en]) => {
            return str.replace(`(${fa})`, `(${en})`);
        }, input);
    }
    maskToMilliseconds(maskValue) {
        const timeUnits = {
            YEAR: 365 * 24 * 60 * 60 * 1000,
            MONTH: 30 * 24 * 60 * 60 * 1000,
            WEEK: 7 * 24 * 60 * 60 * 1000,
            DAY: 24 * 60 * 60 * 1000,
            HOUR: 60 * 60 * 1000,
            MINUTE: 60 * 1000,
            SECOND: 1000,
            MILLISECOND: 1,
        };
        let totalMs = 0;
        if (this.label()) {
            // Parse labeled format: "00 (YEAR) : 00 (MONTH) : 00 (DAY)"
            const transformedMaskValue = this.replacePersianLabels(maskValue);
            const regex = /(\d+)\s*\((YEAR|MONTH|WEEK|DAY|HOUR|MINUTE|SECOND|MILLISECOND)\)/g;
            let match;
            while ((match = regex.exec(transformedMaskValue)) !== null) {
                const value = parseInt(match[1], 10);
                const unit = match[2];
                if (timeUnits[unit] !== undefined) {
                    totalMs += value * timeUnits[unit];
                }
            }
        }
        else {
            // Parse unlabeled format: "00:00:00" (colon-separated numbers)
            const allUnits = ['YEAR', 'MONTH', 'WEEK', 'DAY', 'HOUR', 'MINUTE', 'SECOND', 'MILLISECOND'];
            const startIndex = allUnits.indexOf(this.valueStart());
            const endIndex = allUnits.indexOf(this.valueEnd());
            if (startIndex !== -1 && endIndex !== -1 && endIndex >= startIndex) {
                const selectedUnits = allUnits.slice(startIndex, endIndex + 1);
                const numbers = maskValue.split(':').map((num) => parseInt(num.trim(), 10));
                for (let i = 0; i < Math.min(numbers.length, selectedUnits.length); i++) {
                    const value = numbers[i];
                    const unit = selectedUnits[i];
                    if (!isNaN(value) && timeUnits[unit] !== undefined) {
                        totalMs += value * timeUnits[unit];
                    }
                }
            }
        }
        return totalMs;
    }
    updateMask() {
        const allUnits = ['YEAR', 'MONTH', 'WEEK', 'DAY', 'HOUR', 'MINUTE', 'SECOND', 'MILLISECOND'];
        const startIndex = allUnits.indexOf(this.valueStart());
        const endIndex = allUnits.indexOf(this.valueEnd());
        if (startIndex === -1 || endIndex === -1 || endIndex < startIndex) {
            this.mask.set(null);
            return null;
        }
        const selectedUnits = allUnits.slice(startIndex, endIndex + 1);
        let maskParts;
        const yearDigits = this.maskDigits().split(':')[0];
        const monthDigits = this.maskDigits().split(':')[1];
        const weekDigits = this.maskDigits().split(':')[2];
        const dayDigits = this.maskDigits().split(':')[3];
        const hourDigits = this.maskDigits().split(':')[4];
        const minuteDigits = this.maskDigits().split(':')[5];
        const secondDigits = this.maskDigits().split(':')[6];
        const millisecondDigits = this.maskDigits().split(':')[7];
        if (this.label()) {
            // With labels
            const unitPatterns = {
                YEAR: `${yearDigits} (${this.YEAR()})`,
                MONTH: `${monthDigits} (${this.MONTH()})`,
                WEEK: `${weekDigits} (${this.WEEK()})`,
                DAY: `${dayDigits} (${this.DAY()})`,
                HOUR: `${hourDigits} (${this.HOUR()})`,
                MINUTE: `${minuteDigits} (${this.MINUTE()})`,
                SECOND: `${secondDigits} (${this.SECOND()})`,
                MILLISECOND: `${millisecondDigits} (${this.MILLISECOND()})`,
            };
            maskParts = selectedUnits.map((unit) => {
                return unitPatterns[unit];
            });
        }
        else {
            // Without labels - just numbers
            const unitPatterns = {
                YEAR: yearDigits,
                MONTH: monthDigits,
                WEEK: weekDigits,
                DAY: dayDigits,
                HOUR: hourDigits,
                MINUTE: minuteDigits,
                SECOND: secondDigits,
                MILLISECOND: millisecondDigits,
            };
            maskParts = selectedUnits.map((unit) => {
                return unitPatterns[unit];
            });
        }
        let result;
        if (this.label()) {
            if (this.translationService.getActiveLang() === 'fa-IR') {
                result = maskParts.reverse().join(' : ');
            }
            else {
                result = maskParts.join(' : ');
            }
        }
        else {
            result = maskParts.join(':');
        }
        const convert = result.replace(/0/g, '#');
        this.mask.set(convert);
        this.maskPlaceHolder.set(result);
    }
    focusHandler(e) {
        this.onFocus.emit(e);
    }
    blurHandler(e) {
        this.onBlur.emit(e);
    }
    get __hostName() {
        return this.name;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXTimeDurationComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.16", type: AXTimeDurationComponent, isStandalone: true, selector: "ax-time-duration", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: false, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: false, isRequired: false, transformFunction: null }, look: { classPropertyName: "look", publicName: "look", isSignal: false, isRequired: false, transformFunction: null }, valueStart: { classPropertyName: "valueStart", publicName: "valueStart", isSignal: true, isRequired: false, transformFunction: null }, valueEnd: { classPropertyName: "valueEnd", publicName: "valueEnd", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, maskDigits: { classPropertyName: "maskDigits", publicName: "maskDigits", isSignal: true, isRequired: false, transformFunction: null }, minValue: { classPropertyName: "minValue", publicName: "minValue", isSignal: true, isRequired: false, transformFunction: null }, maxValue: { classPropertyName: "maxValue", publicName: "maxValue", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onValueChanged: "onValueChanged" }, host: { properties: { "attr.name": "this.__hostName" } }, providers: [
            { provide: AXComponent, useExisting: AXTimeDurationComponent },
            { provide: AXFocusableComponent, useExisting: AXTimeDurationComponent },
            { provide: AXValuableComponent, useExisting: AXTimeDurationComponent },
            {
                provide: NG_VALUE_ACCESSOR,
                useExisting: forwardRef(() => AXTimeDurationComponent),
                multi: true,
            },
        ], usesInheritance: true, ngImport: i0, template: "<ax-text-box\n  [look]=\"look\"\n  [placeholder]=\"maskPlaceHolder()\"\n  [maskPattern]=\"mask()\"\n  [(ngModel)]=\"inputValue\"\n  (onValueChanged)=\"onInput($event)\"\n  class=\"ax-time-duration-text\"\n  [disabled]=\"disabled\"\n  [tabIndex]=\"tabIndex\"\n  [readonly]=\"readonly\"\n  (onFocus)=\"focusHandler($event)\"\n  (onBlur)=\"blurHandler($event)\"\n>\n</ax-text-box>\n<ax-validation-rule rule=\"callback\" [options]=\"{ validate: validateFn }\"></ax-validation-rule>\n", dependencies: [{ kind: "ngmodule", type: AXTextBoxModule }, { kind: "component", type: i1.AXTextBoxComponent, selector: "ax-text-box", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "id", "placeholder", "maxLength", "allowNull", "type", "autoComplete", "look", "maskPattern", "customTokens", "class"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXSelectBoxModule }, { kind: "ngmodule", type: AXFormModule }, { kind: "directive", type: i3.AXValidationRuleDirective, selector: "ax-validation-rule", inputs: ["rule", "options", "message", "disabled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXTimeDurationComponent, decorators: [{
            type: Component,
            args: [{ selector: 'ax-time-duration', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [AXTextBoxModule, FormsModule, AXSelectBoxModule, AXFormModule], inputs: ['disabled', 'tabIndex', 'readonly', 'look'], outputs: ['onValueChanged'], providers: [
                        { provide: AXComponent, useExisting: AXTimeDurationComponent },
                        { provide: AXFocusableComponent, useExisting: AXTimeDurationComponent },
                        { provide: AXValuableComponent, useExisting: AXTimeDurationComponent },
                        {
                            provide: NG_VALUE_ACCESSOR,
                            useExisting: forwardRef(() => AXTimeDurationComponent),
                            multi: true,
                        },
                    ], template: "<ax-text-box\n  [look]=\"look\"\n  [placeholder]=\"maskPlaceHolder()\"\n  [maskPattern]=\"mask()\"\n  [(ngModel)]=\"inputValue\"\n  (onValueChanged)=\"onInput($event)\"\n  class=\"ax-time-duration-text\"\n  [disabled]=\"disabled\"\n  [tabIndex]=\"tabIndex\"\n  [readonly]=\"readonly\"\n  (onFocus)=\"focusHandler($event)\"\n  (onBlur)=\"blurHandler($event)\"\n>\n</ax-text-box>\n<ax-validation-rule rule=\"callback\" [options]=\"{ validate: validateFn }\"></ax-validation-rule>\n" }]
        }], propDecorators: { valueStart: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueStart", required: false }] }], valueEnd: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueEnd", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], maskDigits: [{ type: i0.Input, args: [{ isSignal: true, alias: "maskDigits", required: false }] }], minValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "minValue", required: false }] }], maxValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxValue", required: false }] }], __hostName: [{
                type: HostBinding,
                args: ['attr.name']
            }] } });

const COMPONENT = [AXTimeDurationComponent];
const MODULES = [];
class AXTimeDurationModule {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXTimeDurationModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.16", ngImport: i0, type: AXTimeDurationModule, imports: [AXTimeDurationComponent], exports: [AXTimeDurationComponent] }); }
    static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXTimeDurationModule, imports: [MODULES, COMPONENT] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXTimeDurationModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [...MODULES, ...COMPONENT],
                    exports: [...COMPONENT],
                    providers: [],
                }]
        }] });

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

export { AXTimeDurationComponent, AXTimeDurationModule };
//# sourceMappingURL=acorex-components-time-duration.mjs.map
