/**
 * @license
 * Copyright 2023 Tyler Technologies, Inc. 
 * License: Apache-2.0
 */
import { BaseAdapter } from '../core/base/base-adapter';
import { getShadowElement } from '@tylertech/forge-core';
import { QUANTITY_FIELD_CONSTANTS } from './quantity-field-constants';
export class QuantityFieldAdapter extends BaseAdapter {
    constructor(component) {
        super(component);
        this._rootElement = getShadowElement(component, QUANTITY_FIELD_CONSTANTS.selectors.ROOT);
        this._incrementButtonSlot = getShadowElement(this._component, QUANTITY_FIELD_CONSTANTS.selectors.INCREMENT_BUTTON_SLOT);
        this._decrementButtonSlot = getShadowElement(this._component, QUANTITY_FIELD_CONSTANTS.selectors.DECREMENT_BUTTON_SLOT);
    }
    initializeButtons() {
        if (this._incrementButton && !this._incrementButton.hasAttribute('tabindex')) {
            this._incrementButton.tabIndex = -1;
        }
        if (this._decrementButton && !this._decrementButton.hasAttribute('tabindex')) {
            this._decrementButton.tabIndex = -1;
        }
    }
    addRootClass(name) {
        this._rootElement.classList.add(name);
    }
    removeRootClass(name) {
        this._rootElement.classList.remove(name);
    }
    inputHasAttribute(name) {
        if (!this.inputElement) {
            return false;
        }
        return this.inputElement.hasAttribute(name);
    }
    addIncrementButtonSlotListener(listener) {
        this._incrementButtonSlot.addEventListener('slotchange', listener);
    }
    removeIncrementButtonSlotListener(listener) {
        if (this._incrementButtonSlot) {
            this._incrementButtonSlot.removeEventListener('slotchange', listener);
        }
    }
    addDecrementButtonSlotListener(listener) {
        this._decrementButtonSlot.addEventListener('slotchange', listener);
    }
    removeDecrementButtonSlotListener(listener) {
        if (this._decrementButtonSlot) {
            this._decrementButtonSlot.removeEventListener('slotchange', listener);
        }
    }
    addTextFieldAttribute(name, value = '') {
        if (this._textFieldComponent) {
            this._textFieldComponent.setAttribute(name, value);
        }
    }
    removeTextFieldAttribute(name) {
        if (this._textFieldComponent) {
            this._textFieldComponent.removeAttribute(name);
        }
    }
    addIncrementEventListener(event, callback) {
        this._incrementButtonElement.addEventListener(event, callback);
    }
    removeIncrementEventListener(event, callback) {
        if (this._incrementButtonElement) {
            this._incrementButtonElement.removeEventListener(event, callback);
        }
    }
    addDecrementEventListener(event, callback) {
        this._decrementButtonElement.addEventListener(event, callback);
    }
    removeDecrementEventListener(event, callback) {
        if (this._decrementButtonElement) {
            this._decrementButtonElement.removeEventListener(event, callback);
        }
    }
    addIncrementButtonAttribute(name, value = '') {
        this._incrementButtonElement.setAttribute(name, value);
    }
    removeIncrementButtonAttribute(name) {
        this._incrementButtonElement.removeAttribute(name);
    }
    addDecrementButtonAttribute(name, value = '') {
        this._decrementButtonElement.setAttribute(name, value);
    }
    removeDecrementButtonAttribute(name) {
        this._decrementButtonElement.removeAttribute(name);
    }
    increment() {
        const input = this.inputElement;
        if (!input) {
            return;
        }
        const curValue = +input.value;
        const precision = this._calcPrecision(this._inputStep);
        let newValue = parseFloat((curValue + this._inputStep).toFixed(precision));
        if (!!this._inputMax && this._inputMax < newValue) {
            newValue = this._inputMax;
        }
        this._setInputValue(newValue);
    }
    decrement() {
        const input = this.inputElement;
        if (!input) {
            return;
        }
        const curValue = +input.value;
        const precision = this._calcPrecision(this._inputStep);
        let newValue = parseFloat((curValue - this._inputStep).toFixed(precision));
        if (!!this._inputMin && this._inputMin > newValue) {
            newValue = this._inputMin;
        }
        this._setInputValue(newValue);
    }
    addInputDisabledAttributeChangeListener(callback) {
        this._setupInputDisabledAttributeMutationObserver(callback);
    }
    removeInputDisabledAttributeChangeListener() {
        this._cleanupInputDisabledAttributeMutationObserver();
    }
    _setInputValue(value) {
        if (!this.inputElement) {
            return;
        }
        this.inputElement.value = `${value}`;
        this.inputElement.dispatchEvent(new Event('input'));
        this.inputElement.dispatchEvent(new Event('change'));
    }
    _isNullOrUndefinedOrEmpty(value) {
        return value == null || value === '';
    }
    _setupInputDisabledAttributeMutationObserver(callback) {
        if (!this.inputElement) {
            return;
        }
        this._cleanupInputDisabledAttributeMutationObserver();
        const mutationCallback = (mutationRecords) => this._inputDisabledAttributeMutationCallback(mutationRecords, callback);
        this._inputAttributeMutationObserver = new MutationObserver(mutationCallback);
        const mutationOptions = {
            attributes: true,
            attributeOldValue: true,
            attributeFilter: [QUANTITY_FIELD_CONSTANTS.attributes.DISABLED]
        };
        this._inputAttributeMutationObserver.observe(this.inputElement, mutationOptions);
    }
    _cleanupInputDisabledAttributeMutationObserver() {
        if (this._inputAttributeMutationObserver) {
            this._inputAttributeMutationObserver.disconnect();
            delete this._inputAttributeMutationObserver;
        }
    }
    _inputDisabledAttributeMutationCallback(mutationRecords, callback) {
        for (const mutationRecord of mutationRecords) {
            // Skip:
            //   - Non-attribute mutations.
            //   - Mutations without an attribute name.
            //   - Mutations without a matching attribute name.
            //   - Mutations that did not change the attribute value.
            if (mutationRecord.type !== 'attributes'
                || !mutationRecord.attributeName
                || mutationRecord.attributeName !== QUANTITY_FIELD_CONSTANTS.attributes.DISABLED
                || mutationRecord.target[mutationRecord.attributeName] === mutationRecord.oldValue) {
                continue;
            }
            callback();
        }
    }
    get _incrementButtonElement() {
        if (!this._incrementButton) {
            this._incrementButton = this._component.querySelector(QUANTITY_FIELD_CONSTANTS.selectors.INCREMENT_BUTTON);
        }
        return this._incrementButton;
    }
    get _decrementButtonElement() {
        if (!this._decrementButton) {
            this._decrementButton = this._component.querySelector(QUANTITY_FIELD_CONSTANTS.selectors.DECREMENT_BUTTON);
        }
        return this._decrementButton;
    }
    get _textFieldComponent() {
        if (!this._textField) {
            this._textField = this._component.querySelector(QUANTITY_FIELD_CONSTANTS.selectors.TEXT_FIELD);
        }
        return this._textField;
    }
    get inputElement() {
        if (!this._inputElement) {
            this._inputElement = this._component.querySelector(QUANTITY_FIELD_CONSTANTS.selectors.INPUT);
        }
        return this._inputElement;
    }
    get _inputStep() {
        const input = this.inputElement;
        if (!input || this._isNullOrUndefinedOrEmpty(input.step)) {
            return 1;
        }
        return +input.step;
    }
    get _inputMax() {
        const input = this.inputElement;
        if (!input || this._isNullOrUndefinedOrEmpty(input.max)) {
            return null;
        }
        return +input.max;
    }
    get _inputMin() {
        const input = this.inputElement;
        if (!input || this._isNullOrUndefinedOrEmpty(input.min)) {
            return null;
        }
        return +input.min;
    }
    _calcPrecision(value) {
        const strVal = String(value);
        if (strVal.includes('.')) {
            return strVal.split('.')[1].length;
        }
        return 0;
    }
}
