// #region Imports
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
import { on } from '@breadstone/mosaik-elements';
import { DomServiceLocator } from '../../../../../Dom/Dom';
import { Attribute } from '../../../../Decorators/AttributeDecorator';
import { SpinDirection } from '../../../../Types/SpinDirection';
import { UpDownSpinnerElement } from '../../UpDownSpinner/UpDownSpinnerElement';
import { UpDownBaseElement } from './Abstracts/UpDownBaseElement';
// #endregion
/**
 * NumberUpDownElement - A number updown represents a control that enables users to select a number from a given minimum and maximum range.
 *
 * @public
 */
export class NumberUpDownElement extends UpDownBaseElement {
    // #region Fields
    _max;
    _min;
    _step;
    _decimalPlaces;
    _spinnerSpinedSubscription;
    // #endregion
    // #region Ctor
    /**
     * Constructs a new instance of the `NumberUpDownElement` class.
     *
     * @public
     */
    constructor() {
        super();
        this._step = 1;
        this._decimalPlaces = 0;
        this._min = Number.MIN_SAFE_INTEGER;
        this._max = Number.MAX_SAFE_INTEGER;
        this._spinnerSpinedSubscription = null;
    }
    // #endregion
    // #region Properties
    /**
     * Gets or sets the `min` property.
     *
     * @public
     * @attr
     */
    get min() {
        return this._min;
    }
    set min(value) {
        if (this._min !== value) {
            this._min = typeof value === 'number' ? value : parseFloat(value);
            this.requestUpdate('min');
        }
    }
    /**
     * Gets or sets the `max` property.
     *
     * @public
     * @attr
     */
    get max() {
        return this._max;
    }
    set max(value) {
        if (this._max !== value) {
            this._max = typeof value === 'number' ? value : parseFloat(value);
            this.requestUpdate('max');
        }
    }
    /**
     * Gets or sets the `step` property.
     *
     * @public
     * @attr
     */
    get step() {
        return this._step;
    }
    set step(value) {
        if (this._step !== value) {
            this._step = typeof value === 'number' ? value : parseFloat(value);
            this.requestUpdate('step');
        }
    }
    /**
     * Gets or sets the `decimalPlaces` property.
     *
     * @public
     * @attr
     */
    get decimalPlaces() {
        return this._decimalPlaces;
    }
    set decimalPlaces(value) {
        if (this._decimalPlaces !== value) {
            this._decimalPlaces = typeof value === 'number' ? value : parseFloat(value);
            this.requestUpdate('decimalPlaces');
        }
    }
    // #endregion
    // #region Methods
    /**
     * @public
     * @override
     */
    disconnectedCallback() {
        super.disconnectedCallback();
        this._spinnerSpinedSubscription?.dispose();
    }
    /**
     * @protected
     * @override
     */
    onApplyTemplate() {
        super.onApplyTemplate();
        const spinner = this.shadowRoot
            ? DomServiceLocator.current.findDescendant(this.shadowRoot, UpDownSpinnerElement.is)
            : null;
        if (spinner) {
            this._spinnerSpinedSubscription = on(spinner, 'spinned', (x) => this.onSpinned(x));
        }
    }
    /**
     * @protected
     */
    onInputChanged(event) {
        const input = event.target;
        const min = this.convertToNumber(input.min, Number.MIN_SAFE_INTEGER);
        const max = this.convertToNumber(input.max, Number.MAX_SAFE_INTEGER);
        const value = this.convertToNumber(input.value, 0);
        const imposedValue = this.imposeMinMax(value, min, max);
        const spinner = this.shadowRoot
            ? DomServiceLocator.current.findDescendant(this.shadowRoot, UpDownSpinnerElement.is)
            : null;
        if (spinner) {
            spinner.increaseDisabled = !(value < max);
            spinner.decreaseDisabled = !(value > min);
        }
        if (value !== imposedValue || input.valueAsNumber !== imposedValue) {
            this.setInputValue(imposedValue.toFixed(this._decimalPlaces));
        }
    }
    /**
     * @private
     */
    onSpinned(event) {
        const input = this.input;
        const spinner = this.shadowRoot
            ? DomServiceLocator.current.findDescendant(this.shadowRoot, UpDownSpinnerElement.is)
            : null;
        if (input && spinner) {
            input.focus();
            const min = this.convertToNumber(input.min, Number.MIN_SAFE_INTEGER);
            const max = this.convertToNumber(input.max, Number.MAX_SAFE_INTEGER);
            let value = this.convertToNumber(input.value, 0);
            value = this.imposeMinMax(value, min, max);
            if (event.detail.direction === SpinDirection.Increase) {
                const newValue = Number.parseFloat((value + this._step).toFixed(this._decimalPlaces));
                if (newValue < max) {
                    this.setInputValue(newValue.toString());
                    spinner.increaseDisabled = false;
                }
                else {
                    this.setInputValue(max.toString());
                    spinner.increaseDisabled = event.detail.cancel = true;
                }
            }
            if (event.detail.direction === SpinDirection.Decrease) {
                const newValue = Number.parseFloat((value - this._step).toFixed(this._decimalPlaces));
                if (newValue > min) {
                    this.setInputValue(newValue.toString());
                    spinner.decreaseDisabled = false;
                }
                else {
                    this.setInputValue(min.toString());
                    spinner.decreaseDisabled = event.detail.cancel = true;
                }
            }
        }
    }
    /**
     * @private
     */
    convertToNumber(value, fallback) {
        const float = Number.parseFloat(Number.parseFloat(value).toFixed(this._decimalPlaces));
        return Number.isNaN(float)
            ? fallback
            : float;
    }
    /**
     * @private
     */
    imposeMinMax(value, min, max) {
        return value < min
            ? min
            : value > max
                ? max
                : value;
    }
}
__decorate([
    Attribute({ type: Number }),
    __metadata("design:type", Number),
    __metadata("design:paramtypes", [Number])
], NumberUpDownElement.prototype, "min", null);
__decorate([
    Attribute({ type: Number }),
    __metadata("design:type", Number),
    __metadata("design:paramtypes", [Number])
], NumberUpDownElement.prototype, "max", null);
__decorate([
    Attribute({ type: Number }),
    __metadata("design:type", Number),
    __metadata("design:paramtypes", [Number])
], NumberUpDownElement.prototype, "step", null);
__decorate([
    Attribute({ type: Number }),
    __metadata("design:type", Number),
    __metadata("design:paramtypes", [Number])
], NumberUpDownElement.prototype, "decimalPlaces", null);
//# sourceMappingURL=NumberUpDownElement.js.map