/**
 * @license
 * Copyright Tyler Technologies, Inc. 
 * License: Apache-2.0
 */
import { getShadowElement, listenOwnProperty, randomChars, toggleAttribute } from '@tylertech/forge-core';
import { CHIP_FIELD_CONSTANTS } from './chip-field-constants';
import { BaseFieldAdapter } from '../field/base/base-field-adapter';
import { FIELD_CONSTANTS } from '../field/field-constants';
import { LABEL_CONSTANTS } from '../label';
export class ChipFieldAdapter extends BaseFieldAdapter {
    get hasValue() {
        const hasMembers = !!this._component.querySelector(CHIP_FIELD_CONSTANTS.selectors.MEMBER);
        return hasMembers || this.hasInputValue;
    }
    get hasPlaceholder() {
        var _a;
        return !!((_a = this._inputElement) === null || _a === void 0 ? void 0 : _a.placeholder);
    }
    get hasInputValue() {
        var _a;
        return !!((_a = this._inputElement) === null || _a === void 0 ? void 0 : _a.value);
    }
    get inputHasFocus() {
        var _a;
        return !!((_a = this._inputElement) === null || _a === void 0 ? void 0 : _a.matches(':focus'));
    }
    get popoverTargetElement() {
        if (!this._popoverTargetElement) {
            this._popoverTargetElement = getShadowElement(this._fieldElement, FIELD_CONSTANTS.selectors.POPOVER_TARGET);
        }
        return this._popoverTargetElement;
    }
    constructor(component) {
        super(component);
        this._fieldElement = getShadowElement(component, FIELD_CONSTANTS.elementName);
        this._containerElement = getShadowElement(component, CHIP_FIELD_CONSTANTS.selectors.CONTAINER);
        this._memberSlot = getShadowElement(component, CHIP_FIELD_CONSTANTS.selectors.MEMBER_SLOT);
        this._fieldElement.setAttribute('exportparts', Object.values(FIELD_CONSTANTS.parts).join(', '));
    }
    initialize() {
        this._inputElement = this._component.querySelector('input:not([type=checkbox]):not([type=radio])');
    }
    addRootListener(type, listener, options) {
        this._fieldElement.addEventListener(type, listener, options);
    }
    removeRootListener(type, listener, options) {
        this._fieldElement.removeEventListener(type, listener, options);
    }
    addInputListener(type, listener) {
        var _a;
        (_a = this._inputElement) === null || _a === void 0 ? void 0 : _a.addEventListener(type, listener);
    }
    removeInputListener(type, listener) {
        var _a;
        (_a = this._inputElement) === null || _a === void 0 ? void 0 : _a.removeEventListener(type, listener);
    }
    clickInput() {
        var _a;
        (_a = this._inputElement) === null || _a === void 0 ? void 0 : _a.click();
    }
    tryAddValueChangeListener(context, listener) {
        var _a;
        (_a = this._destroyValueChangerListener) === null || _a === void 0 ? void 0 : _a.call(this);
        if (this._inputElement) {
            this._destroyValueChangerListener = listenOwnProperty(context, this._inputElement, 'value', listener);
        }
    }
    removeValueChangeListener() {
        var _a;
        (_a = this._destroyValueChangerListener) === null || _a === void 0 ? void 0 : _a.call(this);
    }
    focusInput() {
        var _a;
        (_a = this._inputElement) === null || _a === void 0 ? void 0 : _a.focus();
    }
    getSlottedMemberElements() {
        return this._memberSlot.assignedElements();
    }
    click() {
        this.focusInput();
    }
    applyLabel(value) {
        /* c8 ignore next 3 */
        if (!this._inputElement) {
            return;
        }
        toggleAttribute(this._inputElement, !!value, 'aria-label', value !== null && value !== void 0 ? value : '');
    }
    tryFloatLabel(force) {
        if (force !== undefined) {
            this._component.floatLabel = force;
            return;
        }
        this._component.floatLabel = this.hasValue || this.hasPlaceholder;
    }
    handleDefaultSlotChange(slot, listener) {
        var _a, _b;
        (_a = this._inputMutationObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
        const assignedElements = slot.assignedElements();
        this._inputElement = assignedElements.find(el => el.matches(CHIP_FIELD_CONSTANTS.selectors.INPUT));
        if (this._inputElement) {
            if (this._component.disabled) {
                this._inputElement.disabled = true;
            }
            this._inputMutationObserver = new MutationObserver(mutations => {
                mutations.forEach(mutation => {
                    if (mutation.attributeName) {
                        const element = mutation.target;
                        const attribute = element.getAttribute(mutation.attributeName);
                        const attributeName = mutation.attributeName;
                        listener(attributeName, attribute);
                    }
                });
            });
            (_b = this._inputMutationObserver) === null || _b === void 0 ? void 0 : _b.observe(this._inputElement, { attributes: true, attributeFilter: [...CHIP_FIELD_CONSTANTS.observedInputAttributes] });
            // Call the listener with each observed attribute to capture the initial state
            Object.values(CHIP_FIELD_CONSTANTS.observedInputAttributes).forEach(value => {
                const attributeName = value;
                if (this._inputElement) {
                    listener(attributeName, this._inputElement.getAttribute(attributeName));
                }
            });
        }
    }
    tryConnectSlottedLabel(slot) {
        /* c8 ignore next 3 */
        if (!this._inputElement) {
            return;
        }
        const elements = slot.assignedElements({ flatten: true });
        // Attempt to find and connect a `<forge-label>` element
        const forgeLabel = elements.find(el => el.matches(LABEL_CONSTANTS.elementName));
        if (forgeLabel) {
            forgeLabel.forElement = this._component;
            forgeLabel.clickTarget = this._inputElement;
            return;
        }
        // Attempt to find and connect a `<label>` element
        const label = elements.find(el => el.tagName === CHIP_FIELD_CONSTANTS.tagNames.LABEL);
        if (!label || label.control) {
            return;
        }
        const id = this._inputElement.id || `forge-input-${randomChars()}`;
        this._inputElement.id = id;
        label.htmlFor = id;
    }
    toggleContainerClass(className, force) {
        this._containerElement.classList.toggle(className, force);
    }
    setDisabled(value) {
        if (this._inputElement) {
            this._inputElement.disabled = value;
        }
    }
}
