/**
 * @license
 * Copyright 2023 Tyler Technologies, Inc. 
 * License: Apache-2.0
 */
import { isDefined } from '@tylertech/forge-core';
import { LIST_CONSTANTS } from './list-constants';
const ELEMENTS_KEY_ALLOWED_IN = ['input', 'button', 'textarea', 'select'];
/**
 * The foundation class behind the `<forge-list>` component.
 */
export class ListFoundation {
    constructor(_adapter) {
        this._adapter = _adapter;
        this._static = false;
        this._dense = false;
        this._propagateClick = true;
        this._indented = false;
        this._keydownListener = (evt) => this._onKeydown(evt);
    }
    initialize() {
        this._adapter.initializeAccessibility();
        if (!this._static) {
            this._adapter.addListener('keydown', this._keydownListener);
        }
        if (this._selectedValue) {
            this._adapter.setSelectedListItems(this._selectedValue);
        }
    }
    _onKeydown(evt) {
        const path = evt.composedPath();
        const composedBeforeUs = path.slice(0, path.indexOf(this._adapter.hostElement));
        const fromListDescendant = composedBeforeUs.some((el) => el.localName === LIST_CONSTANTS.elementName.toLowerCase());
        if (fromListDescendant) {
            return; // We ignore keydown events coming from sub-lists because they are already handling it themselves
        }
        const isArrowDown = evt.key === 'ArrowDown' || evt.keyCode === 40;
        const isArrowUp = evt.key === 'ArrowUp' || evt.keyCode === 38;
        const isHome = evt.key === 'Home' || evt.keyCode === 36;
        const isEnd = evt.key === 'End' || evt.keyCode === 35;
        const isTab = evt.key === 'Tab' || evt.keyCode === 9;
        // We don't capture modifier keys
        if (evt.altKey || evt.ctrlKey || evt.shiftKey || evt.metaKey) {
            return;
        }
        if (!isTab) {
            this._preventDefaultEvent(evt);
        }
        if (isHome) {
            this._adapter.focusFirstListItem();
        }
        else if (isEnd) {
            this._adapter.focusLastListItem();
        }
        else if (isArrowDown) {
            this._adapter.focusNextListItem();
        }
        else if (isArrowUp) {
            this._adapter.focusPreviousListItem();
        }
    }
    /**
     * Ensures that preventDefault is only called if the containing element doesn't
     * consume the event, and it will cause an unintended scroll.
     * @param {Event} evt
     */
    _preventDefaultEvent(evt) {
        const tagName = `${evt.target.tagName}`.toLowerCase();
        if (ELEMENTS_KEY_ALLOWED_IN.indexOf(tagName) === -1) {
            evt.preventDefault();
        }
    }
    _setSelectedValue(value) {
        let values = value instanceof Array ? value : [value];
        values = values.filter(v => isDefined(v));
        this._adapter.setSelectedListItems(values);
    }
    /** Gets/sets whether the list has all static items or not. */
    get static() {
        return this._static;
    }
    set static(value) {
        if (this._static !== value) {
            this._static = value;
            if (!this._static) {
                this._adapter.addListener('keydown', this._keydownListener);
            }
            else {
                this._adapter.removeListener('keydown', this._keydownListener);
            }
            this._adapter.updateListItems(li => li.static = this._static);
            if (this._static) {
                this._adapter.setHostAttribute(LIST_CONSTANTS.attributes.STATIC);
            }
            else {
                this._adapter.removeHostAttribute(LIST_CONSTANTS.attributes.STATIC);
            }
        }
    }
    /** Gets/sets whether the list has all dense items or not. */
    get dense() {
        return this._dense;
    }
    set dense(value) {
        if (this._dense !== value) {
            this._dense = value;
            this._adapter.updateListItems(li => li.dense = this._dense);
            if (this._dense) {
                this._adapter.setHostAttribute(LIST_CONSTANTS.attributes.DENSE);
            }
            else {
                this._adapter.removeHostAttribute(LIST_CONSTANTS.attributes.DENSE);
            }
        }
    }
    get propagateClick() {
        return this._propagateClick;
    }
    set propagateClick(value) {
        if (this._propagateClick !== value) {
            this._propagateClick = value;
            this._adapter.updateListItems(li => li.propagateClick = this._propagateClick);
            this._adapter.setHostAttribute(LIST_CONSTANTS.attributes.PROPAGATE_CLICK, '' + !!this._propagateClick);
        }
    }
    get indented() {
        return this._indented;
    }
    set indented(value) {
        if (this._indented !== value) {
            this._indented = value;
            this._adapter.updateListItems(li => li.indented = this._indented);
            if (this._indented) {
                this._adapter.setHostAttribute(LIST_CONSTANTS.attributes.INDENTED);
            }
            else {
                this._adapter.removeHostAttribute(LIST_CONSTANTS.attributes.INDENTED);
            }
        }
    }
    get selectedValue() {
        return this._selectedValue;
    }
    set selectedValue(value) {
        this._selectedValue = value;
        this._setSelectedValue(value);
    }
}
