import { __decorate, __metadata } from "tslib";
import { Host, h, } from "@stencil/core";
import Big from "big.js";
import { ariaBooleanToString } from "../../utils/aria";
import { inheritAttributes } from "../../utils/attributes";
import { BEM } from "../../utils/bem";
import { ListenToConfig, defaultConfig, } from "../../utils/config";
import { defaultBalAriaForm } from "../../utils/form";
import { inputListenOnClick, stopEventBubbling } from "../../utils/form-input";
import { debounceEvent, rIC } from "../../utils/helpers";
import { Logger } from "../../utils/log";
import { formatLocaleNumber } from "../../utils/number";
import { i18nBalInputStepper } from "./bal-input-stepper.i18n";
export class InputStepper {
    constructor() {
        this.inputId = `bal-input-stepper-${InputStepperIds++}`;
        this.inheritedAttributes = {};
        this.decreaseHasFocus = false;
        this.increaseHasFocus = false;
        this.focused = false;
        this.language = defaultConfig.language;
        this.region = defaultConfig.region;
        this.ariaForm = defaultBalAriaForm;
        /**
         * The name of the control, which is submitted with the form data.
         */
        this.name = this.inputId;
        /**
         * The min value the input can have
         */
        this.min = 0;
        /**
         * The max value the input can have
         */
        this.max = 10;
        /**
         * The steps in which the input increases or decreases
         */
        this.steps = 1;
        /**
         * If `true`, the element is not mutable, focusable, or even submitted with the form. The user can neither edit nor focus on the control, nor its form control descendants.
         */
        this.disabled = false;
        /**
         * If `true` the element can not mutated, meaning the user can not edit the control.
         */
        this.readonly = false;
        /**
         * If `true` the input is shown as invalid
         */
        this.invalid = false;
        /**
         * Set the amount of time, in milliseconds, to wait to trigger the `balChange` event after each keystroke. This also impacts form bindings such as `ngModel` or `v-model`.
         */
        this.debounce = 0;
        /**
         * The value of the input. Only allows values in the range of the min max attribute.
         */
        this.value = 0;
        this.initialValue = 0;
        /**
         * If `true`, in Angular reactive forms the control will not be set invalid
         */
        this.autoInvalidOff = false;
        this.onFocusDecrease = (ev) => {
            this.decreaseHasFocus = true;
            this.onFocus(ev);
        };
        this.onFocusIncrease = (ev) => {
            this.increaseHasFocus = true;
            this.onFocus(ev);
        };
        this.onFocus = (ev) => {
            stopEventBubbling(ev);
            this.balFocus.emit(ev.detail);
        };
        this.onBlurDecrease = (ev) => {
            stopEventBubbling(ev);
            this.decreaseHasFocus = false;
            rIC(() => this.onBlur(ev.detail));
        };
        this.onBlurIncrease = (ev) => {
            stopEventBubbling(ev);
            this.increaseHasFocus = false;
            rIC(() => this.onBlur(ev.detail));
        };
        this.onBlur = (ev) => {
            if (!(this.decreaseHasFocus || this.increaseHasFocus)) {
                this.balBlur.emit(ev);
            }
        };
    }
    createLogger(log) {
        this.log = log;
    }
    debounceChanged() {
        this.balChange = debounceEvent(this.balChange, this.debounce);
    }
    listenOnClick(ev) {
        inputListenOnClick(this, ev);
    }
    resetHandler(ev) {
        const formElement = ev.target;
        if (formElement === null || formElement === void 0 ? void 0 : formElement.contains(this.el)) {
            this.value = this.initialValue;
        }
    }
    connectedCallback() {
        this.debounceChanged();
        this.initialValue = this.value;
    }
    componentWillLoad() {
        this.inheritedAttributes = inheritAttributes(this.el, ['aria-label', 'tabindex', 'title']);
    }
    /**
     * @internal define config for the component
     */
    async configChanged(state) {
        this.language = state.language;
        this.region = state.region;
    }
    /**
     * Returns the native `<input>` element used under the hood.
     */
    getInputElement() {
        return Promise.resolve(this.nativeInput);
    }
    /**
     * @internal
     */
    async setAriaForm(ariaForm) {
        this.ariaForm = Object.assign({}, ariaForm);
    }
    increase() {
        if (!this.disabled && !this.readonly) {
            const newValue = new Big(this.value).plus(this.steps).toNumber();
            if (newValue <= this.max) {
                this.value = newValue;
                this.balInput.emit(newValue);
                this.balChange.emit(newValue);
                this.balIncrease.emit(newValue);
            }
        }
    }
    decrease() {
        if (!this.disabled && !this.readonly) {
            const newValue = new Big(this.value).minus(this.steps).toNumber();
            if (newValue >= this.min) {
                this.value = newValue;
                this.balInput.emit(newValue);
                this.balChange.emit(newValue);
                this.balDecrease.emit(newValue);
            }
        }
    }
    render() {
        const block = BEM.block('input-stepper');
        const elInput = block.element('input');
        const elInner = block.element('inner');
        const elText = elInner.element('text');
        const increaseLabel = i18nBalInputStepper[this.language].increase;
        const decreaseLabel = i18nBalInputStepper[this.language].decrease;
        return (h(Host, { key: 'b017edbea55108f2a839654ec284de97e833da65', "aria-disabled": ariaBooleanToString(this.disabled), "aria-focused": this.focused ? 'true' : null, class: Object.assign({}, block.class()) }, h("div", { key: 'd41f63eed88cd2f29901f23837978ff42cde96aa', class: Object.assign({}, elInner.class()) }, h("bal-button", { key: '7acb51cae824f1e30f3348685903b61d8dae2746', a11yTitle: decreaseLabel, a11yLabel: decreaseLabel, a11yControls: this.ariaForm.controlId || this.inputId, size: "small", square: true, "data-testid": "bal-input-stepper-decrease", outlined: !this.invalid, icon: "minus", color: this.invalid ? 'danger' : 'info', disabled: this.disabled || this.readonly || this.value <= this.min, onClick: _ => this.decrease(), onBalFocus: ev => this.onFocusDecrease(ev), onBalBlur: ev => this.onBlurDecrease(ev) }), h("span", { key: '5b14445f6049a7fc7786d780f9ec1e88e8ba73bc', "data-testid": "bal-input-stepper-text", class: Object.assign(Object.assign(Object.assign({}, elText.class()), elText.modifier('invalid').class(this.invalid)), elText.modifier('disabled').class(this.disabled || this.readonly)) }, formatLocaleNumber(this.value)), h("bal-button", { key: '286ba68697b2dafcf2d543ad545d79474adae092', a11yTitle: increaseLabel, a11yLabel: increaseLabel, a11yControls: this.ariaForm.controlId || this.inputId, size: "small", "data-testid": "bal-input-stepper-increase", square: true, outlined: !this.invalid, icon: "plus", color: this.invalid ? 'danger' : 'info', disabled: this.disabled || this.readonly || this.value >= this.max, onClick: _ => this.increase(), onBalFocus: ev => this.onFocusIncrease(ev), onBalBlur: ev => this.onBlurIncrease(ev) })), h("input", Object.assign({ key: '5dfc042c5452657a0d53ba55ca2b7bfc7d3e6d8c', class: Object.assign({}, elInput.class()), id: this.ariaForm.controlId || this.inputId, "aria-labelledby": this.ariaForm.labelId, "aria-describedby": this.ariaForm.messageId, "aria-invalid": this.invalid === true ? 'true' : 'false', "aria-disabled": ariaBooleanToString(this.disabled), "data-testid": "bal-input-stepper", type: "text", value: this.value, name: this.name, tabindex: "-1", ref: inputEl => (this.nativeInput = inputEl), readonly: this.readonly, disabled: this.disabled }, this.inheritedAttributes))));
    }
    static get is() { return "bal-input-stepper"; }
    static get originalStyleUrls() {
        return {
            "$": ["bal-input-stepper.sass"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["bal-input-stepper.css"]
        };
    }
    static get properties() {
        return {
            "name": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The name of the control, which is submitted with the form data."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "name",
                "defaultValue": "this.inputId"
            },
            "min": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The min value the input can have"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "min",
                "defaultValue": "0"
            },
            "max": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The max value the input can have"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "max",
                "defaultValue": "10"
            },
            "steps": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The steps in which the input increases or decreases"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "steps",
                "defaultValue": "1"
            },
            "disabled": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "If `true`, the element is not mutable, focusable, or even submitted with the form. The user can neither edit nor focus on the control, nor its form control descendants."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "disabled",
                "defaultValue": "false"
            },
            "readonly": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "If `true` the element can not mutated, meaning the user can not edit the control."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "readonly",
                "defaultValue": "false"
            },
            "invalid": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "If `true` the input is shown as invalid"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "invalid",
                "defaultValue": "false"
            },
            "debounce": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Set the amount of time, in milliseconds, to wait to trigger the `balChange` event after each keystroke. This also impacts form bindings such as `ngModel` or `v-model`."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "debounce",
                "defaultValue": "0"
            },
            "value": {
                "type": "number",
                "mutable": true,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The value of the input. Only allows values in the range of the min max attribute."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "value",
                "defaultValue": "0"
            },
            "autoInvalidOff": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "If `true`, in Angular reactive forms the control will not be set invalid"
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "auto-invalid-off",
                "defaultValue": "false"
            }
        };
    }
    static get states() {
        return {
            "focused": {},
            "language": {},
            "region": {},
            "ariaForm": {}
        };
    }
    static get events() {
        return [{
                "method": "balChange",
                "name": "balChange",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the input value has changed."
                },
                "complexType": {
                    "original": "BalEvents.BalInputStepperChangeDetail",
                    "resolved": "number",
                    "references": {
                        "BalEvents": {
                            "location": "global",
                            "id": "global::BalEvents"
                        }
                    }
                }
            }, {
                "method": "balInput",
                "name": "balInput",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the input value has changed."
                },
                "complexType": {
                    "original": "BalEvents.BalInputStepperInputDetail",
                    "resolved": "number",
                    "references": {
                        "BalEvents": {
                            "location": "global",
                            "id": "global::BalEvents"
                        }
                    }
                }
            }, {
                "method": "balIncrease",
                "name": "balIncrease",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the input value has increased."
                },
                "complexType": {
                    "original": "BalEvents.BalInputStepperIncreaseDetail",
                    "resolved": "number",
                    "references": {
                        "BalEvents": {
                            "location": "global",
                            "id": "global::BalEvents"
                        }
                    }
                }
            }, {
                "method": "balDecrease",
                "name": "balDecrease",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the input value has decreased."
                },
                "complexType": {
                    "original": "BalEvents.BalInputStepperDecreaseDetail",
                    "resolved": "number",
                    "references": {
                        "BalEvents": {
                            "location": "global",
                            "id": "global::BalEvents"
                        }
                    }
                }
            }, {
                "method": "balFocus",
                "name": "balFocus",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the input has focus."
                },
                "complexType": {
                    "original": "BalEvents.BalInputStepperFocusDetail",
                    "resolved": "FocusEvent",
                    "references": {
                        "BalEvents": {
                            "location": "global",
                            "id": "global::BalEvents"
                        }
                    }
                }
            }, {
                "method": "balBlur",
                "name": "balBlur",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when a keyboard input occurred."
                },
                "complexType": {
                    "original": "BalEvents.BalInputStepperBlurDetail",
                    "resolved": "FocusEvent",
                    "references": {
                        "BalEvents": {
                            "location": "global",
                            "id": "global::BalEvents"
                        }
                    }
                }
            }];
    }
    static get methods() {
        return {
            "configChanged": {
                "complexType": {
                    "signature": "(state: BalConfigState) => Promise<void>",
                    "parameters": [{
                            "name": "state",
                            "type": "BalConfigState",
                            "docs": ""
                        }],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        },
                        "BalConfigState": {
                            "location": "import",
                            "path": "../../utils/config",
                            "id": "src/utils/config/index.ts::BalConfigState"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "",
                    "tags": [{
                            "name": "internal",
                            "text": "define config for the component"
                        }]
                }
            },
            "getInputElement": {
                "complexType": {
                    "signature": "() => Promise<HTMLInputElement | undefined>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        },
                        "HTMLInputElement": {
                            "location": "global",
                            "id": "global::HTMLInputElement"
                        }
                    },
                    "return": "Promise<HTMLInputElement>"
                },
                "docs": {
                    "text": "Returns the native `<input>` element used under the hood.",
                    "tags": []
                }
            },
            "setAriaForm": {
                "complexType": {
                    "signature": "(ariaForm: BalAriaForm) => Promise<void>",
                    "parameters": [{
                            "name": "ariaForm",
                            "type": "BalAriaForm",
                            "docs": ""
                        }],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        },
                        "BalAriaForm": {
                            "location": "import",
                            "path": "../../utils/form",
                            "id": "src/utils/form.ts::BalAriaForm"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "",
                    "tags": [{
                            "name": "internal",
                            "text": undefined
                        }]
                }
            }
        };
    }
    static get elementRef() { return "el"; }
    static get watchers() {
        return [{
                "propName": "debounce",
                "methodName": "debounceChanged"
            }];
    }
    static get listeners() {
        return [{
                "name": "click",
                "method": "listenOnClick",
                "target": "document",
                "capture": true,
                "passive": false
            }, {
                "name": "reset",
                "method": "resetHandler",
                "target": "document",
                "capture": true,
                "passive": false
            }];
    }
}
__decorate([
    Logger('bal-input-stepper'),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Function]),
    __metadata("design:returntype", void 0)
], InputStepper.prototype, "createLogger", null);
__decorate([
    ListenToConfig(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], InputStepper.prototype, "configChanged", null);
let InputStepperIds = 0;
