/**
 * @license
 * Copyright 2023 Tyler Technologies, Inc. 
 * License: Apache-2.0
 */
import { matchesSelectors } from '@tylertech/forge-core';
import { LIST_ITEM_CONSTANTS } from './list-item-constants';
/**
 * The foundation class behind the `<forge-list-item>` component.
 */
export class ListItemFoundation {
    constructor(_adapter) {
        this._adapter = _adapter;
        this._ripple = true;
        this._static = false;
        this._twoLine = false;
        this._threeLine = false;
        this._active = false;
        this._selected = false;
        this._disabled = false;
        this._dense = false;
        this._propagateClick = true;
        this._indented = false;
        this._wrap = false;
        this._clickListener = (evt) => this._onClick(evt);
        this._keydownListener = (evt) => this._onKeydown(evt);
    }
    initialize() {
        this._adapter.initializeAccessibility();
        this._setRipple();
        this._adapter.setStatic(this._static);
        this._adapter.setDense(this._dense);
        this._adapter.setDisabled(this._disabled);
        this._adapter.setIndented(this._indented);
        this._adapter.setWrap(this._wrap);
        if (!this._static) {
            this._adapter.addListener('click', this._clickListener);
            this._adapter.addListener('keydown', this._keydownListener);
        }
        if (this._threeLine) {
            this._adapter.setThreeLine(this._threeLine);
        }
        else if (this.twoLine) {
            this._adapter.setTwoLine(this._twoLine);
        }
        const isSelected = this._adapter.trySelect(this._value);
        if (isSelected != null) {
            this._selected = isSelected;
        }
    }
    disconnect() {
        if (this._rippleInstance) {
            this._rippleInstance.destroy();
            this._rippleInstance = undefined;
        }
        if (typeof this._destroyUserInteractionListener === 'function') {
            this._destroyUserInteractionListener();
            this._destroyUserInteractionListener = undefined;
        }
    }
    deactivateRipple() {
        var _a;
        (_a = this._rippleInstance) === null || _a === void 0 ? void 0 : _a.deactivate();
    }
    _onKeydown(evt) {
        if (evt.key === 'Enter' || evt.key === ' ') {
            if (evt.key === ' ') {
                evt.preventDefault();
            }
            this._select(evt.target);
        }
    }
    /**
     * Handles clicking a list item.
     * @param evt
     */
    _onClick(evt) {
        this._select(evt.target);
    }
    _select(targetElement) {
        const ignoreElement = targetElement === null || targetElement === void 0 ? void 0 : targetElement.hasAttribute(LIST_ITEM_CONSTANTS.attributes.IGNORE);
        if (this._static || this._disabled || ignoreElement) {
            return;
        }
        if (!this._adapter.hasFocus() && this._propagateClick) {
            this.setFocus();
        }
        if (this._href) {
            if (this._target) {
                window.open(this._href, this._target);
            }
            else {
                document.location.href = this._href;
            }
            return;
        }
        // If the target was not a checkbox or radio button, attempt to find one and toggle its checked state
        if (!matchesSelectors(targetElement, LIST_ITEM_CONSTANTS.selectors.CHECKBOX_RADIO_SELECTOR)) {
            this._adapter.tryToggleCheckboxRadio();
        }
        const data = {
            value: this._value,
            listItem: this._adapter.getListItem()
        };
        this._adapter.emitHostEvent(LIST_ITEM_CONSTANTS.events.SELECT, data);
    }
    /** Gets/sets whether the list item has a ripple or not. */
    get ripple() {
        return this._ripple;
    }
    set ripple(value) {
        if (this._ripple !== value) {
            // We don't attach ripples to static items
            if (value && this._static) {
                return;
            }
            this._ripple = value;
            this._setRipple();
            this._adapter.setHostAttribute(LIST_ITEM_CONSTANTS.attributes.RIPPLE, String(this._ripple));
        }
    }
    /** Gets/sets whether the static state of this list item. */
    get static() {
        return this._static;
    }
    set static(value) {
        if (this._static !== value) {
            this._static = value;
            this._adapter.setStatic(this._static);
            // Ensure we either add or remove the ripple
            this._setRipple();
            // Toggle the click listener
            if (this._static) {
                this._adapter.removeListener('click', this._clickListener);
            }
            else {
                this._adapter.addListener('click', this._clickListener);
            }
            if (this._static) {
                this._adapter.setHostAttribute(LIST_ITEM_CONSTANTS.attributes.STATIC);
            }
            else {
                this._adapter.removeHostAttribute(LIST_ITEM_CONSTANTS.attributes.STATIC);
            }
        }
    }
    /** Gets/sets whether the list item displays two lines of text. */
    get twoLine() {
        return this._twoLine;
    }
    set twoLine(value) {
        if (this._twoLine !== value) {
            this._twoLine = value;
            this._adapter.setTwoLine(this._twoLine);
            if (this._twoLine) {
                this._adapter.setHostAttribute(LIST_ITEM_CONSTANTS.attributes.TWO_LINE);
            }
            else {
                this._adapter.removeHostAttribute(LIST_ITEM_CONSTANTS.attributes.TWO_LINE);
            }
        }
    }
    /** Gets/sets whether the list item displays two lines of text. */
    get threeLine() {
        return this._threeLine;
    }
    set threeLine(value) {
        if (this._threeLine !== value) {
            this._threeLine = value;
            if (this._threeLine) {
                this._adapter.setHostAttribute(LIST_ITEM_CONSTANTS.attributes.THREE_LINE);
            }
            else {
                this._adapter.removeHostAttribute(LIST_ITEM_CONSTANTS.attributes.THREE_LINE);
            }
            if (this._threeLine) {
                this._twoLine = false;
            }
            this._adapter.setTwoLine(this._twoLine);
            this._adapter.setThreeLine(this._threeLine);
        }
    }
    /** Gets/sets whether the list item is active or not. */
    get active() {
        return this._active;
    }
    set active(value) {
        if (this._active !== value) {
            this._active = value;
            this._adapter.setActive(this._active);
            if (this._active) {
                this._adapter.setHostAttribute(LIST_ITEM_CONSTANTS.attributes.ACTIVE);
            }
            else {
                this._adapter.removeHostAttribute(LIST_ITEM_CONSTANTS.attributes.ACTIVE);
            }
        }
    }
    /** Gets/sets whether the list item is selected or not. */
    get selected() {
        return this._selected;
    }
    set selected(value) {
        if (this._selected !== value) {
            this._selected = value;
            this._adapter.setSelected(this._selected);
            this._adapter.tryToggleCheckboxRadio(this._selected);
            this._adapter.toggleHostAttribute(LIST_ITEM_CONSTANTS.attributes.SELECTED, this._selected);
        }
    }
    /** Gets/sets the unique value for this list item. */
    get value() {
        return this._value;
    }
    set value(value) {
        this._value = value;
        const isSelected = this._adapter.trySelect(this._value);
        if (isSelected != null) {
            this._selected = isSelected;
        }
    }
    /** Gets/sets the href link that this list item will send the browser to when clicked. */
    get href() {
        return this._href;
    }
    set href(value) {
        if (this._href !== value) {
            this._href = value;
            if (this._href) {
                this._adapter.setRole(LIST_ITEM_CONSTANTS.roles.LINK);
            }
            else {
                this._adapter.setRole(LIST_ITEM_CONSTANTS.roles.LIST_ITEM);
            }
            this._adapter.setHostAttribute(LIST_ITEM_CONSTANTS.attributes.HREF, this._href);
        }
    }
    /** Gets/sets the href link target. */
    get target() {
        return this._target;
    }
    set target(value) {
        this._target = value;
    }
    /** Gets/sets the disabled state. */
    get disabled() {
        return this._disabled;
    }
    set disabled(value) {
        if (this._disabled !== value) {
            this._disabled = value;
            this._adapter.setDisabled(this._disabled);
            this._adapter.toggleHostAttribute(LIST_ITEM_CONSTANTS.attributes.DISABLED, this._disabled);
        }
    }
    /** Gets/sets the dense state. */
    get dense() {
        return this._dense;
    }
    set dense(value) {
        if (this._dense !== value) {
            this._dense = value;
            this._adapter.setDense(this._dense);
            this._adapter.toggleHostAttribute(LIST_ITEM_CONSTANTS.attributes.DENSE, this._dense);
        }
    }
    /** Gets/sets the dense state. */
    get propagateClick() {
        return this._propagateClick;
    }
    set propagateClick(value) {
        if (this._propagateClick !== value) {
            this._propagateClick = value;
            this._adapter.setHostAttribute(LIST_ITEM_CONSTANTS.attributes.PROPAGATE_CLICK, '' + !!this._propagateClick);
        }
    }
    get indented() {
        return this._indented;
    }
    set indented(value) {
        if (this._indented !== value) {
            this._indented = value;
            this._adapter.setIndented(this._indented);
            this._adapter.toggleHostAttribute(LIST_ITEM_CONSTANTS.attributes.INDENTED, this._indented);
        }
    }
    get wrap() {
        return this._wrap;
    }
    set wrap(value) {
        if (this._wrap !== value) {
            this._wrap = value;
            this._adapter.setWrap(this._wrap);
            this._adapter.toggleHostAttribute(LIST_ITEM_CONSTANTS.attributes.WRAP, this._wrap);
        }
    }
    async _setRipple() {
        if (this._ripple && !this._static && !this._rippleInstance) {
            const { userInteraction, destroy } = await this._adapter.createUserInteractionListener();
            this._destroyUserInteractionListener = destroy;
            const { type } = await userInteraction;
            this._destroyUserInteractionListener = undefined;
            if (!this._adapter.isConnected) {
                return;
            }
            if (this._ripple && !this._static && !this._rippleInstance) {
                this._rippleInstance = this._adapter.createRipple();
                if (type === 'focusin') {
                    this._rippleInstance.handleFocus();
                }
            }
        }
        else if ((!this._ripple || this._static) && this._rippleInstance) {
            this._rippleInstance.destroy();
            this._rippleInstance = undefined;
        }
    }
    /**
     * Sets focus to this list item.
     */
    setFocus() {
        this._adapter.setFocus();
    }
}
