import { Host, h } from "@stencil/core";
export class CpslCodeInput {
    constructor() {
        this.handleInput = (ind, ev) => {
            const inputElements = this.inputs;
            // If getting an insertFromPaste remove the last element value since the value setting is handled in the paste event
            if (ev.inputType === 'insertFromPaste') {
                inputElements[Math.min(this.length - 1, ind)].value = '';
                return;
            }
            if (ev.inputType === 'insertText') {
                if (this.type === 'number' && isNaN(parseInt(ev.data))) {
                    ev.preventDefault();
                    inputElements[ind].value = '';
                    return;
                }
                // Prevent the default behavior FIRST
                ev.preventDefault();
                // Build the new code from the current component state, not the DOM
                const currentCode = this.code || '';
                // Insert the new character at the focused position, not at the end
                const beforeFocused = currentCode.substring(0, ind);
                const afterFocused = currentCode.substring(ind + 1);
                const newCode = beforeFocused + ev.data + afterFocused;
                // Prevent input beyond the maximum length
                if (newCode.length > this.length) {
                    return;
                }
                // Update the component state and emit event
                this.cpslInput.emit({ value: newCode });
                this.code = newCode;
                // Update the specific input that was typed in
                inputElements[ind].value = ev.data;
                // Focus next input if not at the end
                if (ind < this.length - 1) {
                    // Set flag to prevent handleFocus from interfering
                    this.isArrowNavigation = true;
                    setTimeout(() => {
                        inputElements[ind + 1].focus();
                        this.isArrowNavigation = false;
                    }, 0);
                }
            }
        };
        this.isArrowNavigation = false;
        this.handleKeyDown = (ind, ev) => {
            const inputElements = this.inputs;
            switch (ev.key) {
                case 'Backspace': {
                    let newCode;
                    if (!inputElements[ind].value) {
                        // If current input is empty, move to previous and clear it
                        if (ind > 0) {
                            inputElements[ind - 1].value = '';
                            setTimeout(() => {
                                inputElements[ind - 1].focus();
                            }, 0);
                            // Remove character at previous position
                            const currentCode = this.code || '';
                            newCode = currentCode.substring(0, ind - 1) + currentCode.substring(ind);
                        }
                        else {
                            newCode = this.code;
                        }
                    }
                    else {
                        // Clear current input and remove character at current position
                        inputElements[ind].value = '';
                        const currentCode = this.code || '';
                        newCode = currentCode.substring(0, ind) + currentCode.substring(ind + 1);
                    }
                    this.cpslInput.emit({ value: newCode });
                    this.code = newCode;
                    break;
                }
                case 'ArrowLeft': {
                    ev.preventDefault();
                    if (ind > 0) {
                        this.isArrowNavigation = true;
                        setTimeout(() => {
                            inputElements[ind - 1].focus();
                            this.isArrowNavigation = false;
                        }, 0);
                    }
                    break;
                }
                case 'ArrowRight': {
                    ev.preventDefault();
                    if (ind < this.length - 1) {
                        this.isArrowNavigation = true;
                        setTimeout(() => {
                            inputElements[ind + 1].focus();
                            this.isArrowNavigation = false;
                        }, 0);
                    }
                    break;
                }
                default: {
                    break;
                }
            }
        };
        this.handleFocus = (ind) => {
            const inputElements = this.inputs;
            // Don't interfere with arrow key navigation
            if (this.isArrowNavigation) {
                setTimeout(() => {
                    inputElements[ind].setSelectionRange(1, 1);
                }, 0);
                return;
            }
            // If the focused input already has a value, allow it to stay focused (user clicked on it)
            if (inputElements[ind].value) {
                setTimeout(() => {
                    inputElements[ind].setSelectionRange(1, 1);
                }, 0);
                return;
            }
            // Otherwise, use the default focus logic (find first empty or go to last)
            for (const input of inputElements) {
                if (!input.value) {
                    input.focus();
                    break;
                }
                else if (input.id === `code-input-${this.length - 1}`) {
                    input.focus();
                    break;
                }
            }
            setTimeout(() => {
                inputElements[ind].setSelectionRange(1, 1);
            }, 0);
        };
        this.handlePaste = (e) => {
            const inputElements = this.inputs;
            let pastedCode = e.clipboardData.getData('text');
            // Filter based on type
            if (this.type === 'number') {
                // Remove all non-numeric characters
                pastedCode = pastedCode.replace(/\D/g, '');
                // If no valid numbers remain, clear and return
                if (!pastedCode) {
                    setTimeout(() => {
                        inputElements[0].value = '';
                    }, 0);
                    return;
                }
            }
            // Truncate pasted code to match the expected length
            const truncatedCode = pastedCode.substring(0, this.length);
            this.cpslInput.emit({
                value: truncatedCode,
            });
            inputElements.forEach((input, index) => {
                input.value = truncatedCode.charAt(index) || '';
            });
            inputElements[Math.min(this.length - 1, truncatedCode.length)].focus();
        };
        this.code = undefined;
        this.errorText = undefined;
        this.helperText = undefined;
        this.length = undefined;
        this.type = 'number';
    }
    watchCodeProp(newCode) {
        // Update the input values when the code prop changes externally
        const inputElements = this.inputs;
        if (inputElements.length > 0) {
            inputElements.forEach((input, index) => {
                input.value = (newCode === null || newCode === void 0 ? void 0 : newCode[index]) || '';
            });
        }
    }
    get inputs() {
        return Array.from(this.el.shadowRoot.querySelectorAll('input'));
    }
    render() {
        var _a;
        return (h(Host, { key: '16e16cc803f099963c784ed7bbd688afb7b8a59f' }, h("div", { key: 'b3f3a0ba95daf12f4e504bf91e9d8e57b3d97b44', class: "code-container" }, new Array(this.length).fill(0).map((_, i) => {
            var _a, _b;
            return (h("input", { class: { 'code-input': true, 'error': Boolean(this.errorText), 'has-value': ((_a = this.code) === null || _a === void 0 ? void 0 : _a[i]) !== undefined }, id: `code-input-${i}`, onKeyDown: ev => this.handleKeyDown(i, ev), onInput: ev => this.handleInput(i, ev), onFocus: () => this.handleFocus(i), onPaste: this.handlePaste, min: 0, max: 9, value: (_b = this.code) === null || _b === void 0 ? void 0 : _b[i], inputMode: this.type === 'number' ? 'numeric' : 'text' }));
        })), (this.errorText || this.helperText) && (h("div", { key: '8f01ee92d99bbdde0f0b501640bb3136e4e134f8', class: { 'helper-text-container': true, 'error-text': Boolean(this.errorText) } }, h("cpsl-icon", { key: '52a8d308da8c4fad19eec139510df8439a39b6d7', icon: this.errorText ? 'alertCircle' : 'infoCircle' }), h("span", { key: '2d87ea9d774e51055774e76f71074e0eb0d60b10' }, (_a = this.errorText) !== null && _a !== void 0 ? _a : this.helperText)))));
    }
    static get is() { return "cpsl-code-input"; }
    static get encapsulation() { return "shadow"; }
    static get originalStyleUrls() {
        return {
            "$": ["cpsl-code-input.scss"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["cpsl-code-input.css"]
        };
    }
    static get properties() {
        return {
            "code": {
                "type": "string",
                "mutable": true,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Value of the code."
                },
                "attribute": "code",
                "reflect": false
            },
            "errorText": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Error text to show below the input. If this is provided the input will enter an error state."
                },
                "attribute": "error-text",
                "reflect": false
            },
            "helperText": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Helper text to show below the input. If `\"errorText\"` is provided that will take precedence."
                },
                "attribute": "helper-text",
                "reflect": false
            },
            "length": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Length of the code."
                },
                "attribute": "length",
                "reflect": false
            },
            "type": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "'number' | 'string'",
                    "resolved": "\"number\" | \"string\"",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Type of characters to accept in the code.\nDefaults to number."
                },
                "attribute": "type",
                "reflect": false,
                "defaultValue": "'number'"
            }
        };
    }
    static get events() {
        return [{
                "method": "cpslInput",
                "name": "cpslInput",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "The `cpslInput` event is fired each time the user modifies the input's value."
                },
                "complexType": {
                    "original": "CodeChangeEventDetail",
                    "resolved": "CodeChangeEventDetail",
                    "references": {
                        "CodeChangeEventDetail": {
                            "location": "import",
                            "path": "./code-change-interface.js",
                            "id": "src/components/cpsl-code-input/code-change-interface.ts::CodeChangeEventDetail"
                        }
                    }
                }
            }];
    }
    static get elementRef() { return "el"; }
    static get watchers() {
        return [{
                "propName": "code",
                "methodName": "watchCodeProp"
            }];
    }
}
//# sourceMappingURL=cpsl-code-input.js.map
