/**
 * @license
 * Copyright Tyler Technologies, Inc. 
 * License: Apache-2.0
 */
import { getShadowElement, toggleAttribute } from '@tylertech/forge-core';
import { tylIconKeyboardArrowLeft, tylIconKeyboardArrowRight, tylIconKeyboardArrowUp, tylIconKeyboardArrowDown } from '@tylertech/tyler-icons/standard';
import { BaseAdapter } from '../../core/base/base-adapter';
import { TAB_CONSTANTS } from '../tab/tab-constants';
import { TAB_BAR_CONSTANTS } from './tab-bar-constants';
export class TabBarAdapter extends BaseAdapter {
    constructor(component) {
        super(component);
        this._defaultSlotElement = getShadowElement(this._component, TAB_BAR_CONSTANTS.selectors.DEFAULT_SLOT);
        this._rootElement = getShadowElement(this._component, TAB_BAR_CONSTANTS.selectors.ROOT);
        this._scrollContainer = getShadowElement(this._component, TAB_BAR_CONSTANTS.selectors.SCROLL_CONTAINER);
    }
    initializeContainerSizeObserver(listener) {
        this._resizeObserver = new ResizeObserver(() => listener());
        this._resizeObserver.observe(this._component);
    }
    initializeScrollObserver(listener) {
        this._scrollContainer.addEventListener('scroll', listener, { passive: true });
    }
    destroyContainerSizeObserver() {
        var _a;
        (_a = this._resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
        this._resizeObserver = undefined;
    }
    destroyScrollObserver(listener) {
        this._scrollContainer.removeEventListener('scroll', listener, { passive: true });
    }
    setVertical(value) {
        toggleAttribute(this._scrollContainer, !!value, 'aria-orientation', 'vertical');
    }
    setScrollBackwardButtonListener(listener) {
        var _a;
        (_a = this._backwardScrollButton) === null || _a === void 0 ? void 0 : _a.addEventListener('click', listener);
    }
    setScrollForwardButtonListener(listener) {
        var _a;
        (_a = this._forwardScrollButton) === null || _a === void 0 ? void 0 : _a.addEventListener('click', listener);
    }
    addSlotListener(listener) {
        this._defaultSlotElement.addEventListener('slotchange', listener);
    }
    getTabs() {
        return Array.from(this._component.querySelectorAll(TAB_CONSTANTS.elementName));
    }
    async tryScrollTabIntoView(tab) {
        await new Promise(requestAnimationFrame);
        // Due to the async nature of this method, make sure we still need to scroll this tab into view...
        if (!tab.isConnected || (!tab.selected && !tab.matches(':focus'))) {
            return;
        }
        const isVertical = this._component.vertical;
        const scrollContainerOffset = isVertical ? this._scrollContainer.offsetTop : this._scrollContainer.offsetLeft;
        const offset = isVertical ? tab.offsetTop : tab.offsetLeft;
        const extent = isVertical ? tab.offsetHeight : tab.offsetWidth;
        const scroll = isVertical ? this._scrollContainer.scrollTop : this._scrollContainer.scrollLeft;
        const hostExtent = isVertical ? this._scrollContainer.offsetHeight : this._scrollContainer.offsetWidth;
        const min = offset - (TAB_BAR_CONSTANTS.numbers.SCROLL_MARGIN + scrollContainerOffset);
        const max = offset + extent - hostExtent + (TAB_BAR_CONSTANTS.numbers.SCROLL_MARGIN - scrollContainerOffset);
        const to = Math.min(min, Math.max(max, scroll));
        const behavior = tab.matches(':focus') ? 'smooth' : 'instant';
        this._scrollContainer.scrollTo({
            behavior,
            [isVertical ? 'left' : 'top']: 0,
            [isVertical ? 'top' : 'left']: to
        });
    }
    getScrollState() {
        const { scrollHeight, scrollWidth, scrollLeft, scrollTop, clientHeight, clientWidth } = this._scrollContainer;
        const scrollPosition = this._component.vertical ? clientHeight + scrollTop : clientWidth + scrollLeft;
        const scrollSize = this._component.vertical ? scrollHeight : scrollWidth;
        const isScrolledEnd = scrollPosition === scrollSize;
        const isScrolledStart = (this._component.vertical ? scrollPosition - clientHeight : scrollPosition - clientWidth) === 0;
        return { isScrolledStart, isScrolledEnd };
    }
    isScrollable() {
        const { scrollHeight, scrollWidth, clientHeight, clientWidth } = this._scrollContainer;
        return this._component.vertical ? scrollHeight > clientHeight : scrollWidth > clientWidth;
    }
    setScrollButtons(value) {
        var _a, _b;
        if (value) {
            this._backwardScrollButton = this._createScrollButton(this._component.vertical ? tylIconKeyboardArrowUp.name : tylIconKeyboardArrowLeft.name);
            this._rootElement.insertAdjacentElement('afterbegin', this._backwardScrollButton);
            this._forwardScrollButton = this._createScrollButton(this._component.vertical ? tylIconKeyboardArrowDown.name : tylIconKeyboardArrowRight.name);
            this._rootElement.insertAdjacentElement('beforeend', this._forwardScrollButton);
        }
        else {
            (_a = this._backwardScrollButton) === null || _a === void 0 ? void 0 : _a.remove();
            this._backwardScrollButton = undefined;
            (_b = this._forwardScrollButton) === null || _b === void 0 ? void 0 : _b.remove();
            this._forwardScrollButton = undefined;
        }
    }
    syncScrollButtons({ backwardEnabled, forwardEnabled }) {
        var _a, _b;
        if (this._backwardScrollButton) {
            const disabled = !backwardEnabled;
            if (disabled && this._backwardScrollButton.matches(':focus')) {
                (_a = this._forwardScrollButton) === null || _a === void 0 ? void 0 : _a.focus();
            }
            this._backwardScrollButton.disabled = disabled;
        }
        if (this._forwardScrollButton) {
            const disabled = !forwardEnabled;
            if (disabled && this._forwardScrollButton.matches(':focus')) {
                (_b = this._backwardScrollButton) === null || _b === void 0 ? void 0 : _b.focus();
            }
            this._forwardScrollButton.disabled = disabled;
        }
    }
    scroll(which) {
        const amount = this._component.vertical ? this._scrollContainer.offsetHeight : this._scrollContainer.offsetWidth;
        this._scrollContainer.scrollBy({
            behavior: 'smooth',
            [this._component.vertical ? 'top' : 'left']: amount * (which === 'forward' ? 1 : -1)
        });
    }
    updateScrollButtonIcons(vertical) {
        var _a, _b;
        const backButtonIcon = (_a = this._backwardScrollButton) === null || _a === void 0 ? void 0 : _a.querySelector('forge-icon');
        if (backButtonIcon) {
            backButtonIcon.name = vertical ? tylIconKeyboardArrowUp.name : tylIconKeyboardArrowLeft.name;
        }
        const nextButtonIcon = (_b = this._forwardScrollButton) === null || _b === void 0 ? void 0 : _b.querySelector('forge-icon');
        if (nextButtonIcon) {
            nextButtonIcon.name = vertical ? tylIconKeyboardArrowDown.name : tylIconKeyboardArrowRight.name;
        }
    }
    _createScrollButton(iconName) {
        const iconButton = document.createElement('forge-icon-button');
        iconButton.classList.add(TAB_BAR_CONSTANTS.classes.SCROLL_BUTTON);
        iconButton.shape = 'squared';
        iconButton.type = 'button';
        iconButton.tabIndex = -1;
        iconButton.setAttribute('aria-hidden', 'true');
        const icon = document.createElement('forge-icon');
        icon.name = iconName;
        iconButton.appendChild(icon);
        return iconButton;
    }
}
