/**
 * @license
 * Copyright 2023 Tyler Technologies, Inc. 
 * License: Apache-2.0
 */
import { deepQuerySelectorAll } from '@tylertech/forge-core';
import { BaseAdapter } from '../../core/base/base-adapter';
import { LIST_ITEM_CONSTANTS } from '../list-item';
import { LIST_CONSTANTS } from './list-constants';
/**
 * The DOM adapter for the `<forge-list>` component.
 */
export class ListAdapter extends BaseAdapter {
    constructor(component) {
        super(component);
    }
    initializeAccessibility() {
        if (!this._component.hasAttribute('role')) {
            this._component.setAttribute('role', 'list');
        }
    }
    /**
     * Adds an event listener to the `<forge-list>` host element.
     * @param {string} type The event type.
     * @param {Function} listener The event callback.
     */
    addListener(type, listener) {
        this._component.addEventListener(type, listener);
    }
    /**
     * Removes an event listener to the `<forge-list>` host element.
     * @param {string} type The event type.
     * @param {Function} listener The event callback.
     */
    removeListener(type, listener) {
        this._component.removeEventListener(type, listener);
    }
    /**
     * Sets focus to the next item in the list.
     */
    focusNextListItem() {
        const listItems = this._getOwnListItems();
        if (listItems.length > 0) {
            const focusedListItemIndex = listItems.findIndex(li => li.matches(':focus-within'));
            const nextIndex = focusedListItemIndex < listItems.length - 1 ? focusedListItemIndex + 1 : 0;
            if (nextIndex <= listItems.length - 1) {
                listItems[nextIndex].focus();
            }
        }
    }
    /**
     * Sets focus to the previous item in the list.
     */
    focusPreviousListItem() {
        const listItems = this._getOwnListItems();
        if (listItems.length > 0) {
            const focusedListItemIndex = listItems.findIndex(li => li.matches(':focus-within'));
            const nextIndex = focusedListItemIndex > 0 ? focusedListItemIndex - 1 : listItems.length - 1;
            if (nextIndex >= 0) {
                listItems[nextIndex].focus();
            }
        }
    }
    /**
     * Sets focus to the first item in the list.
     */
    focusFirstListItem() {
        const listItems = this._getOwnListItems();
        if (listItems.length > 0) {
            listItems[0].focus();
        }
    }
    /**
     * Sets focus to the last item in the list.
     */
    focusLastListItem() {
        const listItems = this._getOwnListItems();
        if (listItems.length > 0) {
            listItems[listItems.length - 1].focus();
        }
    }
    setSelectedListItems(values) {
        const listItems = Array.from(this._component.querySelectorAll(LIST_ITEM_CONSTANTS.elementName));
        if (listItems && listItems.length) {
            for (const item of listItems) {
                item.selected = values.includes(item.value);
            }
        }
    }
    updateListItems(cb) {
        this._getOwnListItems().forEach(li => cb(li));
    }
    _getOwnListItems() {
        // Find all deeply nested list items
        const allChildListItems = deepQuerySelectorAll(this._component, LIST_ITEM_CONSTANTS.elementName);
        // Get all list items that are scoped to this component only (not within sub-lists).
        const scopedListItems = [];
        const listener = evt => {
            const composedPath = evt.composedPath();
            const composedBeforeUs = composedPath.slice(0, composedPath.indexOf(this._component));
            if (!composedBeforeUs.some((el) => el.localName === LIST_CONSTANTS.elementName.toLowerCase())) {
                scopedListItems.push(evt.target);
            }
        };
        this._component.addEventListener(LIST_CONSTANTS.events.SCOPE_TEST, listener);
        allChildListItems.forEach(li => li.dispatchEvent(new CustomEvent(LIST_CONSTANTS.events.SCOPE_TEST, { bubbles: true, composed: true })));
        this._component.removeEventListener(LIST_CONSTANTS.events.SCOPE_TEST, listener);
        return scopedListItems;
    }
}
