import { Host, h } from "@stencil/core";
import { Lang } from "../../services/lang";
import { cls, getId, isEmpty, tinyMDtoHTML } from "../../utils/helpers";
export class XInputOtp {
    constructor() {
        /**
         * Element ID for internal reference
         */
        this.inputId = getId('otp');
        this.name = undefined;
        this.required = undefined;
        this.paste = undefined;
        this.grouped = undefined;
        this.length = 6;
        this.value = undefined;
        this.type = 'numeric';
        this.isValid = true;
        this.isDisabled = undefined;
        this.isFocused = undefined;
    }
    /**
     * Watch changes in value property
     */
    watchValue(value) {
        var _a;
        this.internals.setFormValue(value);
        this.el.dispatchEvent(new InputEvent('input', { bubbles: false }));
        this.formValidateCallback(true);
        (_a = this.internals.form) === null || _a === void 0 ? void 0 : _a.dispatchEvent(new InputEvent('input', { bubbles: false }));
    }
    /**
     * This is called when the 'disabled' attribute of the element or or an ancestor <fieldset> is updated
     *
     * @param disabled
     */
    formDisabledCallback(disabled) {
        this.isDisabled = disabled;
    }
    /**
     * This is called when the parent/owner form is reset
     */
    formResetCallback() {
        this.isValid = true;
        this.value = '';
    }
    /**
     * This is called when the input is validated
     */
    formValidateCallback(dispatchValidation) {
        if (this.required && isEmpty(this.value)) {
            this.internals.setValidity({ valueMissing: true }, Lang.get('fields.validation.value-missing'));
        }
        else if (!isEmpty(this.value) && this.value.length < this.length && !this.isFocused) {
            this.internals.setValidity({ rangeUnderflow: true }, Lang.get('fields.validation.range-underflow', { min: this.length }));
        }
        else {
            this.internals.setValidity({});
        }
        if (dispatchValidation) {
            this.isValid = this.internals.validity.valid;
            this.onValidateInputEvent.emit(this.internals);
        }
    }
    /**
     * This is called on component did load
     */
    componentDidLoad() {
        setTimeout(() => this.formValidateCallback(), 0);
    }
    /**
     * Distribute the value to correct input by index
     */
    getValueIndex(i) {
        var _a;
        if (((_a = this.value) === null || _a === void 0 ? void 0 : _a.length) >= i + 1) {
            return this.value[i];
        }
        return '';
    }
    /**
     * Clean the input value to input
     */
    filterValue(value) {
        if (!value) {
            return '';
        }
        switch (this.type) {
            case 'numeric':
                return value.replace(/\D/g, '');
            case 'alpha':
                return value.replace(/[^a-zA-Z]/g, '').toUpperCase();
            case 'alphanumeric':
                return value.replace(/[^a-zA-Z0-9]/g, '').toUpperCase();
            case 'hex':
                return value.replace(/[^a-fA-F0-9]/g, '').toUpperCase();
            default:
                return value.toUpperCase();
        }
    }
    /**
     * Set element value by event
     *
     * @param event
     */
    onInput(event, index) {
        const input = event.target;
        if (input.value.length == 1 && index + 1 < this.length) {
            input.nextElementSibling.focus();
        }
        this.value = Array.from(this.el.querySelectorAll('input'))
            .map(el => this.filterValue(el.value))
            .join('');
    }
    /**
     * Paste the clipboard content to the input
     */
    onPasteClipboard(event) {
        event.preventDefault();
        navigator.clipboard.readText().then((text) => {
            this.value = this.filterValue(text);
            this.internals.setFormValue(this.value);
            this.el.dispatchEvent(new InputEvent('input', { bubbles: false }));
        });
    }
    /**
     * This called on input field was changed
     *
     * @param event
     */
    onKeyUpInput(event, index) {
        const input = event.target;
        const key = event.key;
        if (key === 'ArrowLeft' && index > 0) {
            input.previousElementSibling.focus();
            event.preventDefault();
            return;
        }
        if (key === 'ArrowRight' && index + 1 < this.length) {
            input.nextElementSibling.focus();
            event.preventDefault();
            return;
        }
        if ((key === 'Backspace' || key === 'Delete') && input.value === '' && index > 0) {
            input.previousElementSibling.focus();
            event.preventDefault();
            return;
        }
        if (key.length === 1) {
            let allowed = false;
            switch (this.type) {
                case 'numeric':
                    allowed = /^\d$/.test(key);
                    break;
                case 'alpha':
                    allowed = /^[a-zA-Z]$/.test(key);
                    break;
                case 'alphanumeric':
                    allowed = /^[a-zA-Z0-9]$/.test(key);
                    break;
                case 'hex':
                    allowed = /^[a-fA-F0-9]$/.test(key);
                    break;
            }
            if (!allowed) {
                event.preventDefault();
            }
            if (allowed && input.value.length == 1) {
                event.preventDefault();
                input.value = key;
                input.dispatchEvent(new InputEvent('input', { bubbles: false }));
                index + 1 < this.length && input.nextElementSibling.focus();
            }
        }
    }
    /**
     * This called on input field is unfocused
     */
    onBlurInput() {
        this.blurTimeout = setTimeout(() => {
            this.isFocused = false;
            this.formValidateCallback(true);
        }, 100);
    }
    /**
     * This called on input field is focused
     */
    onFocusInput() {
        clearTimeout(this.blurTimeout);
        this.isFocused = true;
    }
    /**
     * Render element
     */
    render() {
        return h(Host, { key: 'd06858086cf5ead70fdc2bb92084d9e6b84f65cf', class: cls({
                'invalid': !this.isValid,
                "focus": this.isFocused,
                'disabled': this.isDisabled,
                'required': this.required,
                'grouped': this.grouped,
            }), "data-for": this.name }, h("div", { key: 'ac62394b7630cb4b71ff32629501aea2ece149f5' }, [...Array(this.length || 0).keys()].map(i => h("input", { class: cls({ 'invalid': !this.isValid }), key: i, id: `${this.inputId}-${i}`, "data-index": i, value: this.getValueIndex(i), placeholder: this.type == 'alpha' ? 'X' : '0', maxlength: 1, disabled: this.isDisabled, autoFocus: i == 0, enterKeyHint: i + 1 >= this.length ? 'send' : 'next', autoComplete: "one-time-code", inputMode: this.type == 'numeric' ? 'numeric' : 'text', onFocus: () => this.onFocusInput(), onBlur: () => this.onBlurInput(), onPaste: e => this.onPasteClipboard(e), onInput: e => this.onInput(e, i), onKeyDown: e => this.onKeyUpInput(e, i) }))), this.paste && h("button", { key: '2aab8741ec89710222ee42028a41b89105432309', type: "button", onClick: e => this.onPasteClipboard(e) }, h("small", { key: 'aeb85d65c8f47377ec7a03eb97e91926d481d05b', innerHTML: tinyMDtoHTML(Lang.get("fields.paste-here")) })));
    }
    static get is() { return "x-input-otp"; }
    static get formAssociated() { return true; }
    static get originalStyleUrls() {
        return {
            "$": ["./style.scss"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["style.css"]
        };
    }
    static get properties() {
        return {
            "name": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Element input name for forms keys"
                },
                "attribute": "name",
                "reflect": false
            },
            "required": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Element input required for forms validations"
                },
                "attribute": "required",
                "reflect": false
            },
            "paste": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Element show paste disclosure"
                },
                "attribute": "paste",
                "reflect": false
            },
            "grouped": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Element grouped style"
                },
                "attribute": "grouped",
                "reflect": false
            },
            "length": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Element input maximun count of characters"
                },
                "attribute": "length",
                "reflect": false,
                "defaultValue": "6"
            },
            "value": {
                "type": "string",
                "mutable": true,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Element input value"
                },
                "attribute": "value",
                "reflect": false
            },
            "type": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "InputOTPType",
                    "resolved": "\"alpha\" | \"alphanumeric\" | \"hex\" | \"numeric\"",
                    "references": {
                        "InputOTPType": {
                            "location": "local",
                            "path": "/opt/atlassian/pipelines/agent/build/src/components/x-input/component-otp.tsx",
                            "id": "src/components/x-input/component-otp.tsx::InputOTPType"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Element input type"
                },
                "attribute": "type",
                "reflect": false,
                "defaultValue": "'numeric'"
            }
        };
    }
    static get states() {
        return {
            "isValid": {},
            "isDisabled": {},
            "isFocused": {}
        };
    }
    static get events() {
        return [{
                "method": "onValidateInputEvent",
                "name": "validated",
                "bubbles": false,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "On validate input event"
                },
                "complexType": {
                    "original": "ElementInternals",
                    "resolved": "ElementInternals",
                    "references": {
                        "ElementInternals": {
                            "location": "global",
                            "id": "global::ElementInternals"
                        }
                    }
                }
            }];
    }
    static get elementRef() { return "el"; }
    static get watchers() {
        return [{
                "propName": "value",
                "methodName": "watchValue"
            }];
    }
    static get attachInternalsMemberName() { return "internals"; }
}
