import { __esDecorate, __runInitializers } from "tslib";
import { property } from 'lit/decorators.js';
import { floatConverter } from '../../../lib/AttributeConverters.js';
import { UiElement } from '../../UiElement.js';
/**
 * @fires ratiochange - When `ratio` computation is ready.
 */
let UiRange = (() => {
    let _classSuper = UiElement;
    let _value_decorators;
    let _value_initializers = [];
    let _value_extraInitializers = [];
    let _min_decorators;
    let _min_initializers = [];
    let _min_extraInitializers = [];
    let _max_decorators;
    let _max_initializers = [];
    let _max_extraInitializers = [];
    let _step_decorators;
    let _step_initializers = [];
    let _step_extraInitializers = [];
    let _indeterminate_decorators;
    let _indeterminate_initializers = [];
    let _indeterminate_extraInitializers = [];
    return class UiRange extends _classSuper {
        static {
            const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
            _value_decorators = [property({ type: Number, converter: floatConverter })];
            _min_decorators = [property({ type: Number, converter: floatConverter })];
            _max_decorators = [property({ type: Number, converter: floatConverter })];
            _step_decorators = [property({ type: Number, converter: floatConverter })];
            _indeterminate_decorators = [property({ reflect: true, type: Boolean })];
            __esDecorate(this, null, _value_decorators, { kind: "accessor", name: "value", static: false, private: false, access: { has: obj => "value" in obj, get: obj => obj.value, set: (obj, value) => { obj.value = value; } }, metadata: _metadata }, _value_initializers, _value_extraInitializers);
            __esDecorate(this, null, _min_decorators, { kind: "accessor", name: "min", static: false, private: false, access: { has: obj => "min" in obj, get: obj => obj.min, set: (obj, value) => { obj.min = value; } }, metadata: _metadata }, _min_initializers, _min_extraInitializers);
            __esDecorate(this, null, _max_decorators, { kind: "accessor", name: "max", static: false, private: false, access: { has: obj => "max" in obj, get: obj => obj.max, set: (obj, value) => { obj.max = value; } }, metadata: _metadata }, _max_initializers, _max_extraInitializers);
            __esDecorate(this, null, _step_decorators, { kind: "accessor", name: "step", static: false, private: false, access: { has: obj => "step" in obj, get: obj => obj.step, set: (obj, value) => { obj.step = value; } }, metadata: _metadata }, _step_initializers, _step_extraInitializers);
            __esDecorate(this, null, _indeterminate_decorators, { kind: "accessor", name: "indeterminate", static: false, private: false, access: { has: obj => "indeterminate" in obj, get: obj => obj.indeterminate, set: (obj, value) => { obj.indeterminate = value; } }, metadata: _metadata }, _indeterminate_initializers, _indeterminate_extraInitializers);
            if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
        }
        ratioInternal = 0;
        debounceInternal;
        oldValue;
        /**
         * @returns the ratio of the value.
         */
        get ratio() {
            return this.ratioInternal;
        }
        #value_accessor_storage = __runInitializers(this, _value_initializers, 0
        /**
         * The number that indicates the minimum value of the range.
         * @attribute
         */
        );
        /**
         * The number that represents the current value.
         * @attribute
         */
        get value() { return this.#value_accessor_storage; }
        set value(value) { this.#value_accessor_storage = value; }
        #min_accessor_storage = (__runInitializers(this, _value_extraInitializers), __runInitializers(this, _min_initializers, 0
        /**
         * The number that indicates the maximum value of the range.
         * @attribute
         */
        ));
        /**
         * The number that indicates the minimum value of the range.
         * @attribute
         */
        get min() { return this.#min_accessor_storage; }
        set min(value) { this.#min_accessor_storage = value; }
        #max_accessor_storage = (__runInitializers(this, _min_extraInitializers), __runInitializers(this, _max_initializers, 100
        /**
         * Specifies the value granularity of the range's value.
         * @attribute
         */
        ));
        /**
         * The number that indicates the maximum value of the range.
         * @attribute
         */
        get max() { return this.#max_accessor_storage; }
        set max(value) { this.#max_accessor_storage = value; }
        #step_accessor_storage = (__runInitializers(this, _max_extraInitializers), __runInitializers(this, _step_initializers, 1
        /**
         * Use an indeterminate progress indicator.
         * @attribute
         */
        ));
        /**
         * Specifies the value granularity of the range's value.
         * @attribute
         */
        get step() { return this.#step_accessor_storage; }
        set step(value) { this.#step_accessor_storage = value; }
        #indeterminate_accessor_storage = (__runInitializers(this, _step_extraInitializers), __runInitializers(this, _indeterminate_initializers, void 0));
        /**
         * Use an indeterminate progress indicator.
         * @attribute
         */
        get indeterminate() { return this.#indeterminate_accessor_storage; }
        set indeterminate(value) { this.#indeterminate_accessor_storage = value; }
        connectedCallback() {
            super.connectedCallback();
            if (!this.hasAttribute('role')) {
                this.setAttribute('role', 'progressbar');
            }
        }
        willUpdate(cp) {
            if (cp.has('value') || cp.has('min') || cp.has('max') || cp.has('step') || cp.has('indeterminate')) {
                this.rangeChanged();
            }
            if (cp.has('min')) {
                this.setAttribute('aria-valuemin', String(this.min));
            }
            if (cp.has('max')) {
                this.setAttribute('aria-valuemax', String(this.max));
            }
            if (cp.has('indeterminate') || cp.has('value')) {
                if (this.indeterminate) {
                    this.removeAttribute('aria-valuenow');
                }
                else {
                    this.setAttribute('aria-valuenow', String(this.value));
                }
            }
            super.willUpdate(cp);
        }
        rangeChanged() {
            this.validateValue();
            const ratio = this.computeRatio(this.value) * 100;
            if (this.ratioInternal !== ratio) {
                this.ratioInternal = ratio;
                this.dispatchEvent(new Event('ratiochange'));
            }
        }
        /**
         * Makes sure the value is in the right format.
         * @returns True when the value has changed.
         */
        validateValue() {
            const v = this.clampValue(this.value);
            this.oldValue = Number.isNaN(v) ? this.oldValue : v;
            this.value = this.oldValue || 0;
            return this.value !== v;
        }
        clampValue(value) {
            return Math.min(this.max, Math.max(this.min, this.computeStep(value)));
        }
        computeStep(step) {
            const value = step;
            if (!this.step) {
                return value;
            }
            const numSteps = Math.round((value - this.min) / this.step);
            if (this.step < 1) {
                /**
                 * For small values of this.step, if we calculate the step using
                 * `Math.round(value / step) * step` we may hit a precision point issue
                 * eg. 0.1 * 0.2 =  0.020000000000000004
                 * http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
                 *
                 * as a work around we can divide by the reciprocal of `step`
                 */
                return numSteps / (1 / this.step) + this.min;
            }
            return numSteps * this.step + this.min;
        }
        computeRatio(value) {
            const denominator = this.max - this.min;
            if (denominator === 0) {
                return 0;
            }
            return (this.clampValue(value) - this.min) / (this.max - this.min);
        }
        constructor() {
            super(...arguments);
            __runInitializers(this, _indeterminate_extraInitializers);
        }
    };
})();
export { UiRange };
//# sourceMappingURL=Range.js.map