/**
 * @license
 * Copyright Tyler Technologies, Inc. 
 * License: Apache-2.0
 */
import { LIST_ITEM_CONSTANTS } from './list-item-constants';
export class ListItemCore {
    constructor(_adapter) {
        this._adapter = _adapter;
        this._selected = false;
        this._active = false;
        this._dense = false;
        this._indented = false;
        this._twoLine = false;
        this._threeLine = false;
        this._wrap = false;
        this._noninteractive = false;
        this._interactiveStateChangeListener = this._onInteractiveStateChange.bind(this);
        this._mousedownListener = this._onMousedown.bind(this);
        this._clickListener = this._onClick.bind(this);
        this._keydownListener = this._onKeydown.bind(this);
    }
    initialize() {
        this._adapter.initialize();
        if (this._noninteractive) {
            this._adapter.destroyInteractiveObserver();
        }
        else {
            this._adapter.initializeInteractiveObserver(this._interactiveStateChangeListener);
        }
    }
    destroy() {
        this._adapter.destroy();
    }
    _onMousedown(evt) {
        const composedElements = evt.composedPath().filter((el) => el.nodeType === Node.ELEMENT_NODE);
        const fromInteractiveElement = composedElements.some(el => el === this._adapter.interactiveElement);
        if (!fromInteractiveElement) {
            evt.preventDefault();
        }
    }
    _onKeydown(evt) {
        const composedElements = evt.composedPath().filter((el) => el.nodeType === Node.ELEMENT_NODE);
        const isFromStartEndSlot = composedElements.some((el) => el.matches(LIST_ITEM_CONSTANTS.selectors.SLOTTED_START_END));
        if (evt.key === 'Enter' || evt.key === ' ') {
            evt.stopPropagation();
        }
        if (isFromStartEndSlot) {
            if (evt.key === 'Enter' || evt.key === ' ') {
                this._adapter.animateStateLayer();
            }
            if (evt.key === 'Enter') {
                this._adapter.interactiveElement?.click();
            }
            return;
        }
        if (evt.key === ' ') {
            evt.preventDefault();
            this._adapter.interactiveElement?.click();
        }
    }
    _onClick(evt) {
        const composedElements = evt.composedPath().filter((el) => el.nodeType === Node.ELEMENT_NODE);
        // Ignore clicks from elements that should not trigger selection
        const fromIgnoredElement = composedElements.some(el => el.matches(LIST_ITEM_CONSTANTS.selectors.IGNORE));
        if (fromIgnoredElement) {
            return;
        }
        // Ignore clicks from <label> elements that have a for attribute that matches our interactive elements' id
        const labelElementWithFor = (el) => el.matches('label[for]');
        const fromLabelFor = composedElements.filter(labelElementWithFor).some(el => el.htmlFor === this._adapter.interactiveElement?.id);
        if (fromLabelFor) {
            evt.stopPropagation();
            return;
        }
        // Check if our internal anchor was clicked and forward the click to the slotted interactive element
        const isInternalAnchor = (el) => el.tagName === 'A' && el.id === LIST_ITEM_CONSTANTS.ids.INTERNAL_ANCHOR;
        const fromInternalAnchor = composedElements.some(isInternalAnchor);
        if (fromInternalAnchor) {
            const isCtrlClick = evt.ctrlKey || evt.metaKey;
            const hasTarget = this._adapter.interactiveElement?.hasAttribute('target');
            evt.preventDefault();
            evt.stopImmediatePropagation();
            // Workaround to temporarily set the target attribute to '_blank' if the user is holding the ctrl key and remove it after the click
            const forceTempAnchorTarget = isCtrlClick && !hasTarget;
            /* c8 ignore next 3 */
            if (forceTempAnchorTarget) {
                this._adapter.interactiveElement?.setAttribute('target', '_blank');
            }
            this._clickInteractiveElement();
            /* c8 ignore next 3 */
            if (forceTempAnchorTarget) {
                this._adapter.interactiveElement?.removeAttribute('target');
            }
            return;
        }
        // If the click did not originate from the interactive element, forward the click to it
        const fromInteractiveElement = composedElements.some(el => el === this._adapter.interactiveElement);
        if (!fromInteractiveElement) {
            evt.stopImmediatePropagation();
            this._clickInteractiveElement();
            return;
        }
        this._dispatchSelectEvent();
    }
    _clickInteractiveElement() {
        this._adapter.interactiveElement?.focus();
        this._adapter.tempDeactivateFocusIndicator(); // Workaround until we can call `focus({ focusVisible: false })` to prevent focus ring from showing
        this._adapter.interactiveElement?.click();
    }
    _onInteractiveStateChange(value) {
        if (value && !this._noninteractive) {
            this._adapter.addRootListener('mousedown', this._mousedownListener, { capture: true });
            this._adapter.addHostListener('click', this._clickListener, { capture: true });
            this._adapter.addHostListener('keydown', this._keydownListener);
        }
        else {
            this._adapter.removeRootListener('mousedown', this._mousedownListener, { capture: true });
            this._adapter.removeHostListener('click', this._clickListener, { capture: true });
            this._adapter.removeHostListener('keydown', this._keydownListener);
        }
    }
    _dispatchSelectEvent() {
        const detail = { value: this._value };
        const event = new CustomEvent(LIST_ITEM_CONSTANTS.events.SELECT, {
            bubbles: true,
            detail
        });
        this._adapter.dispatchHostEvent(event);
    }
    get selected() {
        return this._selected;
    }
    set selected(value) {
        value = Boolean(value);
        if (this._selected !== value) {
            this._selected = value;
            this._adapter.toggleHostAttribute(LIST_ITEM_CONSTANTS.attributes.SELECTED, this._selected);
        }
    }
    get active() {
        return this._active;
    }
    set active(value) {
        value = Boolean(value);
        if (this._active !== value) {
            this._active = value;
            this._adapter.setActive(this._active);
            this._adapter.toggleHostAttribute(LIST_ITEM_CONSTANTS.attributes.ACTIVE, this._active);
        }
    }
    get value() {
        return this._value;
    }
    set value(value) {
        this._value = value;
        const isSelected = this._adapter.trySelect(this._value);
        if (isSelected !== null && isSelected !== this._selected) {
            this.selected = isSelected;
        }
    }
    get dense() {
        return this._dense;
    }
    set dense(value) {
        value = Boolean(value);
        if (this._dense !== value) {
            this._dense = value;
            this._adapter.toggleHostAttribute(LIST_ITEM_CONSTANTS.attributes.DENSE, this._dense);
        }
    }
    get indented() {
        return this._indented;
    }
    set indented(value) {
        value = Boolean(value);
        if (this._indented !== value) {
            this._indented = value;
            this._adapter.toggleHostAttribute(LIST_ITEM_CONSTANTS.attributes.INDENTED, this._indented);
        }
    }
    get twoLine() {
        return this._twoLine;
    }
    set twoLine(value) {
        value = Boolean(value);
        if (this._twoLine !== value) {
            this._twoLine = value;
            this._adapter.toggleHostAttribute(LIST_ITEM_CONSTANTS.attributes.TWO_LINE, this._twoLine);
        }
    }
    get threeLine() {
        return this._threeLine;
    }
    set threeLine(value) {
        value = Boolean(value);
        if (this._threeLine !== value) {
            this._threeLine = value;
            this._adapter.toggleHostAttribute(LIST_ITEM_CONSTANTS.attributes.THREE_LINE, this._threeLine);
        }
    }
    get wrap() {
        return this._wrap;
    }
    set wrap(value) {
        value = Boolean(value);
        if (this._wrap !== value) {
            this._wrap = value;
            this._adapter.toggleHostAttribute(LIST_ITEM_CONSTANTS.attributes.WRAP, this._wrap);
        }
    }
    get noninteractive() {
        return this._noninteractive;
    }
    set noninteractive(value) {
        value = Boolean(value);
        if (this._noninteractive !== value) {
            this._noninteractive = value;
            if (this._adapter.isConnected) {
                if (this._noninteractive) {
                    this._adapter.destroyInteractiveObserver();
                }
                else {
                    this._adapter.initializeInteractiveObserver(this._interactiveStateChangeListener);
                }
            }
            this._adapter.toggleHostAttribute(LIST_ITEM_CONSTANTS.attributes.NONINTERACTIVE, this._noninteractive);
        }
    }
}
