import { h, Host } from "@stencil/core";
import { FormRangeClass, FormRangeSizes } from "./constants";
import { govHost, toBoolAttr, toBoolAttrIfDefined } from "../../../helpers/Dom/template";
import { validateProp } from "../../../helpers/Validate/props";
import { AttributeObserver } from "../../../helpers/Dom/attribute";
import { govForm } from "../../../helpers/Dom/form";
import { tick } from "../../../utils/stencil.utils";
import { isNumber } from "../../../utils/helpers.types";
import { createID } from "../../../utils/string.utils";
import { ariaAttributes } from "../../../helpers/Accessibility/attributes";
import { inheritAriaAttributes } from "../../../helpers/Accessibility/accessibility";
export class GovFormRange {
    constructor() {
        /**
         * Range’s size
         */
        this.size = "m";
        /**
         * Show tooltip with current value
         */
        this.tooltip = false;
        /**
         * Show input with current value
         */
        this.input = false;
        /**
         * Set whether the range is required or not
         */
        this.required = false;
        /**
         * Makes the range component disabled
         */
        this.disabled = false;
        this.inheritedAttributes = {};
        this.h = govHost(this.host);
        this.f = govForm(this.h);
        this.inputId = createID("GovInput");
    }
    validateSize(newValue) {
        validateProp(FormRangeSizes, newValue, FormRangeClass.root);
    }
    watchValue() {
        this.controlOutputPosition();
    }
    watchControlAttrs() {
        this.passControlAttrs();
    }
    passControlAttrs() {
        this.f.passAttrToControl("size", this.size);
        this.f.passAttrToControl("success", toBoolAttr(this.success));
        this.f.passAttrToControl("disabled", toBoolAttr(this.disabled));
        this.f.passAttrToControl("invalid", toBoolAttr(this.invalid));
    }
    get getThumbWidth() {
        const styles = window.getComputedStyle(this.inputRef);
        return parseFloat(styles.getPropertyValue('--thumb-size')) || 1;
    }
    controlOutputPosition() {
        const valueInt = +this.value;
        const min = +this.inputRef.min;
        const max = +this.inputRef.max;
        const thumbWidth = (this.getThumbWidth * 16);
        const rangeWidth = this.inputRef.offsetWidth;
        const percentage = ((valueInt - min) / (max - min)) * 100;
        let tooltipOffset = ((percentage / 100) * (rangeWidth - thumbWidth)) + (thumbWidth / 2);
        if (this.outputRef) {
            this.outputRef.textContent = this.value;
            const outputWidth = this.outputRef.offsetWidth / 2;
            this.outputRef.style.left = `${tooltipOffset - outputWidth}px`;
        }
        if (this.fillRef) {
            this.fillRef.style.width = `${tooltipOffset}px`;
        }
    }
    componentDidLoad() {
        this.attributeObserver = new AttributeObserver(this.host, (attributeName, newValue) => {
            this.onAriaAttributeChange(attributeName, newValue);
        });
        this.attributeObserver.startObserving(ariaAttributes);
    }
    componentWillLoad() {
        this.validateSize(this.size);
        this.inheritedAttributes = inheritAriaAttributes(this.host);
    }
    componentDidRender() {
        this.passControlAttrs();
        this.f.passAttrToLabel("required", String(this.required));
        tick(this.controlOutputPosition.bind(this));
    }
    onAriaAttributeChange(attributeName, newValue) {
        this.host.removeAttribute(attributeName);
        this.inheritedAttributes = Object.assign(Object.assign({}, this.inheritedAttributes), { [attributeName]: newValue });
    }
    disconnectedCallback() {
        var _a;
        (_a = this.attributeObserver) === null || _a === void 0 ? void 0 : _a.stopObserving();
    }
    render() {
        return (h(Host, { key: '52936cc832e35b7f79520c2f89b2a119e769b994', class: FormRangeClass.root, size: this.size }, this.h.hasSlot("prefix") && h("slot", { key: '1f5d3e1d537be5f431cbf4ba366627d82c2daa01', name: "prefix" }), h("span", { key: 'cbabb9ff252fbabdd8b2f813de71b31c1a1444e6', class: "element" }, h("input", Object.assign({ key: '02dd3f62cb518c965c0f5529ae3b213a9c6fd649', type: "range", ref: el => (this.inputRef = el), onInput: this.onInputHandler.bind(this), onFocus: this.onFocusHandler.bind(this), onBlur: this.onBlurHandler.bind(this), id: this.identifier || this.inputId, name: this.name, min: this.min, max: this.max, step: this.step, list: this.listIdentifier, value: this.value, required: this.required, disabled: this.disabled }, this.inheritedAttributes, { "aria-required": toBoolAttrIfDefined(this.required), "aria-invalid": toBoolAttrIfDefined(this.invalid), "aria-disabled": toBoolAttrIfDefined(this.disabled) })), h("div", { key: 'fff23dd770c71878eae67df3f96b514c3f55ea2e', class: FormRangeClass.fill, ref: el => (this.fillRef = el) }), this.tooltip ?
            h("output", { htmlFor: this.name, ref: el => (this.outputRef = el) }, this.value)
            : null, h("slot", { key: '32a7919602b2527a97bf019ec74744bedd0ef51f', name: "datalist" })), this.h.hasSlot("sufix") && h("slot", { key: 'e9efd215bb9895a6c11666eb694b6c47f8132f12', name: "sufix" }), this.input ?
            h("gov-form-input", Object.assign({ "on-gov-input": this.onCustomInputHandler.bind(this), class: FormRangeClass.input, size: this.size, value: this.value, disabled: this.disabled }, this.inheritedAttributes))
            : null));
    }
    onCustomInputHandler(e) {
        const value = e.target.value;
        if (this.step && isNumber(+this.step)) {
            const numValue = +value;
            const numMin = +this.min;
            const numMax = +this.max;
            const numStep = +this.step;
            if (isNaN(numValue)) {
                return false;
            }
            if (numValue < numMin || numValue > numMax) {
                return false;
            }
            const diff = numValue - numMin;
            if (diff % numStep !== 0) {
                return false;
            }
            this.value = value;
            this.govInput.emit({
                component: FormRangeClass.root,
                value: this.value,
                originalEvent: e,
            });
        }
    }
    onInputHandler(e) {
        this.value = e.target.value;
        e.stopPropagation();
        this.govInput.emit({
            component: FormRangeClass.root,
            value: this.value,
            originalEvent: e,
        });
    }
    onFocusHandler(e) {
        e.stopPropagation();
        this.govFocus.emit({
            component: FormRangeClass.root,
            value: this.value,
            originalEvent: e,
        });
    }
    onBlurHandler(e) {
        e.stopPropagation();
        this.govBlur.emit({
            component: FormRangeClass.root,
            value: this.value,
            originalEvent: e,
        });
    }
    /**
     * Returns the current state of the component
     */
    async setFocus(options) {
        return this.inputRef.focus(options);
    }
    /**
     * Sets the ordered value of the element
     */
    async setValue(value) {
        this.value = value;
    }
    /**
     * Clears input value
     */
    async clearValue() {
        this.value = "";
        this.inputRef.value = "";
    }
    /**
     * Returns an instance of the native html input element
     */
    async getRef() {
        return this.inputRef;
    }
    static get is() { return "gov-form-range"; }
    static get properties() {
        return {
            "size": {
                "type": "string",
                "attribute": "size",
                "mutable": false,
                "complexType": {
                    "original": "FormRangeSizesType",
                    "resolved": "\"l\" | \"m\" | \"s\"",
                    "references": {
                        "FormRangeSizesType": {
                            "location": "import",
                            "path": "./constants",
                            "id": "../../../packages/core/src/components/gov-form/range/constants.ts::FormRangeSizesType"
                        }
                    }
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Range\u2019s size"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "\"m\""
            },
            "value": {
                "type": "string",
                "attribute": "value",
                "mutable": true,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Value of range"
                },
                "getter": false,
                "setter": false,
                "reflect": true
            },
            "identifier": {
                "type": "string",
                "attribute": "identifier",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Custom range identifier"
                },
                "getter": false,
                "setter": false,
                "reflect": false
            },
            "name": {
                "type": "string",
                "attribute": "name",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Name of the range"
                },
                "getter": false,
                "setter": false,
                "reflect": false
            },
            "min": {
                "type": "any",
                "attribute": "min",
                "mutable": false,
                "complexType": {
                    "original": "string | number",
                    "resolved": "number | string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Minimum value that is acceptable"
                },
                "getter": false,
                "setter": false,
                "reflect": false
            },
            "max": {
                "type": "any",
                "attribute": "max",
                "mutable": false,
                "complexType": {
                    "original": "string | number",
                    "resolved": "number | string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Maximum value that is acceptable"
                },
                "getter": false,
                "setter": false,
                "reflect": false
            },
            "step": {
                "type": "any",
                "attribute": "step",
                "mutable": false,
                "complexType": {
                    "original": "string | number",
                    "resolved": "number | string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Defines size of each step"
                },
                "getter": false,
                "setter": false,
                "reflect": false
            },
            "tooltip": {
                "type": "boolean",
                "attribute": "tooltip",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Show tooltip with current value"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "false"
            },
            "input": {
                "type": "boolean",
                "attribute": "input",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Show input with current value"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "false"
            },
            "listIdentifier": {
                "type": "string",
                "attribute": "list-identifier",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Links a <datalist/> element to a <input type=\"range\">, providing value markers as guidance for the user"
                },
                "getter": false,
                "setter": false,
                "reflect": false
            },
            "required": {
                "type": "boolean",
                "attribute": "required",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Set whether the range is required or not"
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "defaultValue": "false"
            },
            "success": {
                "type": "boolean",
                "attribute": "success",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Indicates the entered value of child form element does conform to the format expected by the application"
                },
                "getter": false,
                "setter": false,
                "reflect": true
            },
            "invalid": {
                "type": "boolean",
                "attribute": "invalid",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Indicates the entered value does not conform to the format expected by the application"
                },
                "getter": false,
                "setter": false,
                "reflect": true
            },
            "disabled": {
                "type": "boolean",
                "attribute": "disabled",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Makes the range component disabled"
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "defaultValue": "false"
            }
        };
    }
    static get states() {
        return {
            "inheritedAttributes": {}
        };
    }
    static get events() {
        return [{
                "method": "govFocus",
                "name": "gov-focus",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the input has focus."
                },
                "complexType": {
                    "original": "FormInputEvent",
                    "resolved": "FormInputEvent",
                    "references": {
                        "FormInputEvent": {
                            "location": "import",
                            "path": "../input/gov-form-input.types",
                            "id": "../../../packages/core/src/components/gov-form/input/gov-form-input.types.ts::FormInputEvent"
                        }
                    }
                }
            }, {
                "method": "govBlur",
                "name": "gov-blur",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the input loses focus."
                },
                "complexType": {
                    "original": "FormInputEvent",
                    "resolved": "FormInputEvent",
                    "references": {
                        "FormInputEvent": {
                            "location": "import",
                            "path": "../input/gov-form-input.types",
                            "id": "../../../packages/core/src/components/gov-form/input/gov-form-input.types.ts::FormInputEvent"
                        }
                    }
                }
            }, {
                "method": "govInput",
                "name": "gov-input",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the input change value."
                },
                "complexType": {
                    "original": "FormInputEvent",
                    "resolved": "FormInputEvent",
                    "references": {
                        "FormInputEvent": {
                            "location": "import",
                            "path": "../input/gov-form-input.types",
                            "id": "../../../packages/core/src/components/gov-form/input/gov-form-input.types.ts::FormInputEvent"
                        }
                    }
                }
            }];
    }
    static get methods() {
        return {
            "setFocus": {
                "complexType": {
                    "signature": "(options?: FocusOptions) => Promise<void>",
                    "parameters": [{
                            "name": "options",
                            "type": "FocusOptions",
                            "docs": ""
                        }],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        },
                        "FocusOptions": {
                            "location": "global",
                            "id": "global::FocusOptions"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Returns the current state of the component",
                    "tags": []
                }
            },
            "setValue": {
                "complexType": {
                    "signature": "(value: string) => Promise<void>",
                    "parameters": [{
                            "name": "value",
                            "type": "string",
                            "docs": ""
                        }],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Sets the ordered value of the element",
                    "tags": []
                }
            },
            "clearValue": {
                "complexType": {
                    "signature": "() => Promise<void>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Clears input value",
                    "tags": []
                }
            },
            "getRef": {
                "complexType": {
                    "signature": "() => Promise<HTMLInputElement>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        },
                        "HTMLInputElement": {
                            "location": "global",
                            "id": "global::HTMLInputElement"
                        }
                    },
                    "return": "Promise<HTMLInputElement>"
                },
                "docs": {
                    "text": "Returns an instance of the native html input element",
                    "tags": []
                }
            }
        };
    }
    static get elementRef() { return "host"; }
    static get watchers() {
        return [{
                "propName": "size",
                "methodName": "validateSize"
            }, {
                "propName": "value",
                "methodName": "watchValue"
            }, {
                "propName": "disabled",
                "methodName": "watchControlAttrs"
            }, {
                "propName": "invalid",
                "methodName": "watchControlAttrs"
            }, {
                "propName": "success",
                "methodName": "watchControlAttrs"
            }, {
                "propName": "size",
                "methodName": "watchControlAttrs"
            }];
    }
}
//# sourceMappingURL=gov-form-range.js.map
