// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import { CrLitElement } from '//resources/lit/v3_0/lit.rollup.js';
import { getCss } from './cr_progress.css.js';
import { getHtml } from './cr_progress.html.js';
export class CrProgressElement extends CrLitElement {
    static get is() {
        return 'cr-progress';
    }
    static get styles() {
        return getCss();
    }
    render() {
        return getHtml.bind(this)();
    }
    static get properties() {
        return {
            /**
             * The number that represents the current value.
             */
            value: { type: Number },
            /**
             * The number that indicates the minimum value of the range.
             */
            min: { type: Number },
            /**
             * The number that indicates the maximum value of the range.
             */
            max: { type: Number },
            /**
             * Specifies the value granularity of the range's value.
             */
            step: { type: Number },
            /**
             * Use an indeterminate progress indicator.
             */
            indeterminate: {
                type: Boolean,
                reflect: true,
            },
            /**
             * True if the progress is disabled.
             */
            disabled: {
                type: Boolean,
                reflect: true,
            },
        };
    }
    #value_accessor_storage = 0;
    get value() { return this.#value_accessor_storage; }
    set value(value) { this.#value_accessor_storage = value; }
    #min_accessor_storage = 0;
    get min() { return this.#min_accessor_storage; }
    set min(value) { this.#min_accessor_storage = value; }
    #max_accessor_storage = 100;
    get max() { return this.#max_accessor_storage; }
    set max(value) { this.#max_accessor_storage = value; }
    #step_accessor_storage = 1;
    get step() { return this.#step_accessor_storage; }
    set step(value) { this.#step_accessor_storage = value; }
    #indeterminate_accessor_storage = false;
    get indeterminate() { return this.#indeterminate_accessor_storage; }
    set indeterminate(value) { this.#indeterminate_accessor_storage = value; }
    #disabled_accessor_storage = false;
    get disabled() { return this.#disabled_accessor_storage; }
    set disabled(value) { this.#disabled_accessor_storage = value; }
    willUpdate(changedProperties) {
        super.willUpdate(changedProperties);
        // Clamp the value to the range.
        if (changedProperties.has('min') || changedProperties.has('max') ||
            changedProperties.has('value') || changedProperties.has('step')) {
            const previous = changedProperties.get('value') || 0;
            const clampedValue = this.clampValue_(this.value);
            this.value = Number.isNaN(clampedValue) ? previous : clampedValue;
        }
    }
    firstUpdated(changedProperties) {
        super.firstUpdated(changedProperties);
        if (!this.hasAttribute('role')) {
            this.setAttribute('role', 'progressbar');
        }
    }
    updated(changedProperties) {
        super.updated(changedProperties);
        if (changedProperties.has('min') || changedProperties.has('max') ||
            changedProperties.has('value') || changedProperties.has('step')) {
            const ratio = (this.value - this.min) / (this.max - this.min);
            this.$.primaryProgress.style.transform = `scaleX(${ratio})`;
            this.setAttribute('aria-valuemin', this.min.toString());
            this.setAttribute('aria-valuemax', this.max.toString());
        }
        if (changedProperties.has('indeterminate') ||
            changedProperties.has('value')) {
            if (this.indeterminate) {
                this.removeAttribute('aria-valuenow');
            }
            else {
                this.setAttribute('aria-valuenow', this.value.toString());
            }
        }
        if (changedProperties.has('disabled')) {
            this.setAttribute('aria-disabled', this.disabled ? 'true' : 'false');
        }
    }
    clampValue_(value) {
        return Math.min(this.max, Math.max(this.min, this.calcStep_(value)));
    }
    calcStep_(value) {
        value = Number.parseFloat(value.toString());
        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;
        }
        else {
            return numSteps * this.step + this.min;
        }
    }
}
customElements.define(CrProgressElement.is, CrProgressElement);
