/**
 * @license
 * Copyright 2023 Tyler Technologies, Inc. 
 * License: Apache-2.0
 */
import { getShadowElement, removeAllChildren, appendToAttribute, toggleAttribute, toggleOnAttribute } from '@tylertech/forge-core';
import { BaseAdapter } from '../core/base';
import { CALENDAR_CONSTANTS } from './calendar-constants';
import { splitIntoWeeks } from './calendar-utils';
import { getAccessibleHeader, getClearButton, getDateElement, getDateId, getDateRow, getDateSpacerElement, getDayElement, getEventElement, getEventWrapperElement, getEventWrapperId, getFooter, getHeader, getMonthButtonContent, getTodayButton, getTooltip, getYearButtonContent, setTabindexOnElement } from './calendar-dom-utils';
import { getLocalizedMonth, getLocalizedYear } from './calendar-locale-utils';
import { CALENDAR_MENU_CONSTANTS } from './calendar-menu';
export class CalendarAdapter extends BaseAdapter {
    constructor(component) {
        super(component);
        this._container = getShadowElement(component, CALENDAR_CONSTANTS.selectors.CALENDAR);
        this._dateView = getShadowElement(component, CALENDAR_CONSTANTS.selectors.DATE_VIEW);
        this._dayRow = getShadowElement(component, CALENDAR_CONSTANTS.selectors.DAY_ROW);
        this._dateGrid = getShadowElement(component, CALENDAR_CONSTANTS.selectors.DATE_GRID);
        this._menu = getShadowElement(component, CALENDAR_CONSTANTS.selectors.MENU);
    }
    toggleContainerAttribute(hasAttribute, name, value) {
        toggleAttribute(this._container, hasAttribute, name, value);
    }
    registerMonthButtonListener(listener) {
        const monthButton = this._container.querySelector(CALENDAR_CONSTANTS.selectors.MONTH_BUTTON);
        monthButton === null || monthButton === void 0 ? void 0 : monthButton.addEventListener('click', listener);
    }
    unregisterMonthButtonListener(listener) {
        const monthButton = this._container.querySelector(CALENDAR_CONSTANTS.selectors.MONTH_BUTTON);
        monthButton === null || monthButton === void 0 ? void 0 : monthButton.removeEventListener('click', listener);
    }
    registerYearButtonListener(listener) {
        const yearButton = this._container.querySelector(CALENDAR_CONSTANTS.selectors.YEAR_BUTTON);
        yearButton === null || yearButton === void 0 ? void 0 : yearButton.addEventListener('click', listener);
    }
    unregisterYearButtonListener(listener) {
        const yearButton = this._container.querySelector(CALENDAR_CONSTANTS.selectors.YEAR_BUTTON);
        yearButton === null || yearButton === void 0 ? void 0 : yearButton.removeEventListener('click', listener);
    }
    registerMenuListener(listener) {
        this._menu.addEventListener(CALENDAR_MENU_CONSTANTS.events.SELECT, listener);
    }
    unregisterMenuListener(listener) {
        this._menu.removeEventListener(CALENDAR_MENU_CONSTANTS.events.SELECT, listener);
    }
    registerMenuFocusChangeEventListener(listener) {
        this._menu.addEventListener(CALENDAR_MENU_CONSTANTS.events.FOCUS_CHANGE, listener);
    }
    unregisterMenuFocusChangeEventListener(listener) {
        this._menu.addEventListener(CALENDAR_MENU_CONSTANTS.events.FOCUS_CHANGE, listener);
    }
    registerNextButtonListener(listener) {
        const nextButton = this._container.querySelector(CALENDAR_CONSTANTS.selectors.NEXT_BUTTON);
        nextButton === null || nextButton === void 0 ? void 0 : nextButton.addEventListener('click', listener);
    }
    unregisterNextButtonListener(listener) {
        const nextButton = this._container.querySelector(CALENDAR_CONSTANTS.selectors.NEXT_BUTTON);
        nextButton === null || nextButton === void 0 ? void 0 : nextButton.removeEventListener('click', listener);
    }
    registerPreviousButtonListener(listener) {
        const previousButton = this._container.querySelector(CALENDAR_CONSTANTS.selectors.PREVIOUS_BUTTON);
        previousButton === null || previousButton === void 0 ? void 0 : previousButton.addEventListener('click', listener);
    }
    unregisterPreviousButtonListener(listener) {
        const previousButton = this._container.querySelector(CALENDAR_CONSTANTS.selectors.PREVIOUS_BUTTON);
        previousButton === null || previousButton === void 0 ? void 0 : previousButton.removeEventListener('click', listener);
    }
    registerClearButtonListener(listener) {
        const clearButton = this._container.querySelector(CALENDAR_CONSTANTS.selectors.CLEAR_BUTTON);
        clearButton === null || clearButton === void 0 ? void 0 : clearButton.addEventListener('click', listener);
    }
    unregisterClearButtonListener(listener) {
        const clearButton = this._container.querySelector(CALENDAR_CONSTANTS.selectors.CLEAR_BUTTON);
        clearButton === null || clearButton === void 0 ? void 0 : clearButton.removeEventListener('click', listener);
    }
    registerTodayButtonListener(listener) {
        const todayButton = this._container.querySelector(CALENDAR_CONSTANTS.selectors.TODAY_BUTTON);
        todayButton === null || todayButton === void 0 ? void 0 : todayButton.addEventListener('click', listener);
    }
    unregisterTodayButtonListener(listener) {
        const todayButton = this._container.querySelector(CALENDAR_CONSTANTS.selectors.TODAY_BUTTON);
        todayButton === null || todayButton === void 0 ? void 0 : todayButton.removeEventListener('click', listener);
    }
    registerDateClickListener(listener) {
        this._dateGrid.addEventListener('click', listener);
    }
    unregisterDateClickListener(listener) {
        this._dateGrid.removeEventListener('click', listener);
    }
    registerKeydownListener(listener) {
        this._container.addEventListener('keydown', listener);
    }
    registerHoverListener(listener) {
        this._dateGrid.addEventListener('mouseover', listener);
    }
    unregisterHoverListener(listener) {
        this._dateGrid.removeEventListener('mouseover', listener);
    }
    registerPreventFocusListener(listener) {
        this._container.addEventListener('mousedown', listener);
    }
    unregisterPreventFocusListener(listener) {
        this._container.removeEventListener('mousedown', listener);
    }
    setContainerClass(name, value) {
        this._container.classList.toggle(name, value);
    }
    setHeader() {
        const accessibleHeader = this._container.querySelector(CALENDAR_CONSTANTS.selectors.ACCESSIBLE_HEADER);
        accessibleHeader === null || accessibleHeader === void 0 ? void 0 : accessibleHeader.remove();
        const header = this._container.querySelector(CALENDAR_CONSTANTS.selectors.HEADER);
        if (header) {
            header.replaceWith(getHeader());
        }
        else {
            this._container.prepend(getHeader());
        }
    }
    removeHeader() {
        const header = this._container.querySelector(CALENDAR_CONSTANTS.selectors.HEADER);
        header === null || header === void 0 ? void 0 : header.remove();
        const accessibleHeader = this._container.querySelector(CALENDAR_CONSTANTS.selectors.ACCESSIBLE_HEADER);
        if (accessibleHeader) {
            accessibleHeader.replaceWith(getAccessibleHeader());
        }
        else {
            this._container.prepend(getAccessibleHeader());
        }
    }
    setNextButtonDisabled(value) {
        const nextButton = this._container.querySelector(CALENDAR_CONSTANTS.selectors.NEXT_BUTTON);
        nextButton === null || nextButton === void 0 ? void 0 : nextButton.toggleAttribute('disabled', value);
    }
    setPreviousButtonDisabled(value) {
        const previousButton = this._container.querySelector(CALENDAR_CONSTANTS.selectors.PREVIOUS_BUTTON);
        previousButton === null || previousButton === void 0 ? void 0 : previousButton.toggleAttribute('disabled', value);
    }
    setNextButtonLabel(label) {
        const nextButton = this._container.querySelector(CALENDAR_CONSTANTS.selectors.NEXT_BUTTON);
        nextButton === null || nextButton === void 0 ? void 0 : nextButton.setAttribute('aria-label', label);
        const nextTooltip = this._container.querySelector(CALENDAR_CONSTANTS.selectors.NEXT_BUTTON_TOOLTIP);
        if (nextTooltip) {
            nextTooltip.innerHTML = label;
        }
    }
    setPreviousButtonLabel(label) {
        const previousButton = this._container.querySelector(CALENDAR_CONSTANTS.selectors.PREVIOUS_BUTTON);
        previousButton === null || previousButton === void 0 ? void 0 : previousButton.setAttribute('aria-label', label);
        const previousTooltip = this._container.querySelector(CALENDAR_CONSTANTS.selectors.PREVIOUS_BUTTON_TOOLTIP);
        if (previousTooltip) {
            previousTooltip.innerHTML = label;
        }
    }
    setMonthButtonPressed(value) {
        const monthButton = this._container.querySelector(CALENDAR_CONSTANTS.selectors.MONTH_BUTTON);
        if (monthButton) {
            monthButton.setAttribute('aria-pressed', value.toString());
            this._container.classList.toggle(CALENDAR_CONSTANTS.classes.MONTH_MENU_OPEN, value);
        }
    }
    setYearButtonPressed(value) {
        const yearButton = this._container.querySelector(CALENDAR_CONSTANTS.selectors.YEAR_BUTTON);
        if (yearButton) {
            yearButton.setAttribute('aria-pressed', value.toString());
            this._container.classList.toggle(CALENDAR_CONSTANTS.classes.YEAR_MENU_OPEN, value);
        }
    }
    setMonth(month, locale) {
        const monthButton = this._container.querySelector(CALENDAR_CONSTANTS.selectors.MONTH_BUTTON);
        if (monthButton) {
            const content = getMonthButtonContent(month, locale);
            monthButton.replaceChildren(content[0], content[1]);
            return;
        }
        const accessibleMonth = this._container.querySelector(CALENDAR_CONSTANTS.selectors.ACCESSIBLE_MONTH);
        if (accessibleMonth) {
            accessibleMonth.textContent = getLocalizedMonth(month, 'long', locale);
        }
    }
    setYear(year, locale) {
        const yearButton = this._container.querySelector(CALENDAR_CONSTANTS.selectors.YEAR_BUTTON);
        if (yearButton) {
            const content = getYearButtonContent(year, locale);
            yearButton.replaceChildren(content[0], content[1]);
            return;
        }
        const accessibleYear = this._container.querySelector(CALENDAR_CONSTANTS.selectors.ACCESSIBLE_YEAR);
        if (accessibleYear) {
            accessibleYear.textContent = getLocalizedYear(year, 'numeric', locale);
        }
    }
    setFooter() {
        const footer = this._container.querySelector(CALENDAR_CONSTANTS.selectors.FOOTER);
        if (!footer) {
            this._container.appendChild(getFooter());
        }
    }
    removeFooter() {
        var _a;
        const footer = this._container.querySelector(CALENDAR_CONSTANTS.selectors.FOOTER);
        (_a = footer === null || footer === void 0 ? void 0 : footer.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(footer);
    }
    setClearButton() {
        const footer = this._container.querySelector(CALENDAR_CONSTANTS.selectors.FOOTER);
        if (!footer) {
            return;
        }
        const clearButton = footer.querySelector(CALENDAR_CONSTANTS.selectors.CLEAR_BUTTON);
        if (!clearButton) {
            footer.prepend(getClearButton());
        }
    }
    removeClearButton() {
        var _a;
        const clearButton = this._container.querySelector(CALENDAR_CONSTANTS.selectors.CLEAR_BUTTON);
        (_a = clearButton === null || clearButton === void 0 ? void 0 : clearButton.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(clearButton);
    }
    setTodayButton() {
        const footer = this._container.querySelector(CALENDAR_CONSTANTS.selectors.FOOTER);
        if (!footer) {
            return;
        }
        const todayButton = footer.querySelector(CALENDAR_CONSTANTS.selectors.TODAY_BUTTON);
        if (!todayButton) {
            footer.appendChild(getTodayButton());
        }
    }
    removeTodayButton() {
        var _a;
        const todayButton = this._container.querySelector(CALENDAR_CONSTANTS.selectors.TODAY_BUTTON);
        (_a = todayButton === null || todayButton === void 0 ? void 0 : todayButton.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(todayButton);
    }
    setDays(days, options) {
        removeAllChildren(this._dayRow);
        days.forEach(d => {
            let element = getDayElement(d, options === null || options === void 0 ? void 0 : options.locale);
            if (options === null || options === void 0 ? void 0 : options.builder) {
                element = options.builder(d, element);
            }
            this._dayRow.appendChild(element);
        });
    }
    setDates(dates, options) {
        removeAllChildren(this._dateGrid);
        splitIntoWeeks(dates).forEach((w, i) => {
            const dateRow = getDateRow(w, i, options);
            this._dateGrid.appendChild(dateRow);
        });
    }
    replaceDate(date, options) {
        const dateElement = this._dateGrid.querySelector(`#${getDateId(date.date)}`);
        if (dateElement) {
            const element = getDateElement(date, options === null || options === void 0 ? void 0 : options.locale);
            if (options === null || options === void 0 ? void 0 : options.builder) {
                dateElement.replaceWith(options.builder(date, element));
            }
            else {
                dateElement.replaceWith(element);
            }
        }
    }
    replaceDateWithSpacer(date) {
        const dateElement = this._dateGrid.querySelector(`#${getDateId(date)}`);
        dateElement === null || dateElement === void 0 ? void 0 : dateElement.replaceWith(getDateSpacerElement(date));
    }
    setDateDisabled(date, value) {
        const element = this._dateGrid.querySelector(`#${getDateId(date)}`);
        if (element) {
            element.toggleAttribute('disabled', value);
            element.setAttribute('aria-disabled', value.toString());
        }
    }
    setDateSelected(date, value) {
        const element = this._dateGrid.querySelector(`#${getDateId(date)}`);
        if (element) {
            element.classList.toggle(CALENDAR_CONSTANTS.classes.DATE_SELECTED, value);
            element.setAttribute('aria-selected', value.toString());
        }
    }
    setWeekend(date, value) {
        const element = this._dateGrid.querySelector(`#${getDateId(date)}`);
        const innerElement = element === null || element === void 0 ? void 0 : element.querySelector(CALENDAR_CONSTANTS.selectors.DATE_INNER);
        if (!innerElement) {
            return;
        }
        toggleOnAttribute(innerElement, 'part', CALENDAR_CONSTANTS.parts.WEEKEND, value);
    }
    appendDateAttribute(date, name, value) {
        const element = this._dateGrid.querySelector(`#${getDateId(date)}`);
        if (element) {
            appendToAttribute(element, name, value);
        }
    }
    setMultiple(value) {
        this._dateView.setAttribute('aria-multiselectable', value.toString());
    }
    setDateViewHidden(value) {
        toggleAttribute(this._dateView, value, 'aria-hidden', value.toString());
        this.setAllDatesUnfocusable();
    }
    // #endregion
    // #region Range
    setRange(dates) {
        const oldDateElements = this._dateGrid.querySelectorAll(CALENDAR_CONSTANTS.selectors.RANGE);
        oldDateElements.forEach(e => e.classList.remove(CALENDAR_CONSTANTS.classes.RANGE));
        if (!dates) {
            return;
        }
        dates.forEach(d => {
            const dateElement = this._dateGrid.querySelector(`#${getDateId(d)}`);
            dateElement === null || dateElement === void 0 ? void 0 : dateElement.classList.add(CALENDAR_CONSTANTS.classes.RANGE);
        });
    }
    setRangeStart(date) {
        const oldDateElement = this._dateGrid.querySelector(CALENDAR_CONSTANTS.selectors.RANGE_START);
        oldDateElement === null || oldDateElement === void 0 ? void 0 : oldDateElement.classList.remove(CALENDAR_CONSTANTS.classes.RANGE_START);
        if (!date) {
            return;
        }
        const newDateElement = this._dateGrid.querySelector(`#${getDateId(date)}`);
        newDateElement === null || newDateElement === void 0 ? void 0 : newDateElement.classList.add(CALENDAR_CONSTANTS.classes.RANGE_START);
    }
    setRangeEnd(date) {
        const oldDateElement = this._dateGrid.querySelector(CALENDAR_CONSTANTS.selectors.RANGE_END);
        oldDateElement === null || oldDateElement === void 0 ? void 0 : oldDateElement.classList.remove(CALENDAR_CONSTANTS.classes.RANGE_END);
        if (!date) {
            return;
        }
        const newDateElement = this._dateGrid.querySelector(`#${getDateId(date)}`);
        newDateElement === null || newDateElement === void 0 ? void 0 : newDateElement.classList.add(CALENDAR_CONSTANTS.classes.RANGE_END);
    }
    setActiveDate(date, setFocus, preventFocus) {
        const dateString = date.toDateString();
        const elements = this._dateGrid.querySelectorAll(CALENDAR_CONSTANTS.selectors.DATE);
        elements.forEach(e => {
            const shouldFocus = e.getAttribute(CALENDAR_CONSTANTS.attributes.DATA_DATE) === dateString;
            setTabindexOnElement(e, shouldFocus ? 0 : -1, setFocus, preventFocus);
        });
    }
    setAllDatesUnfocusable() {
        const elements = this._dateGrid.querySelectorAll(CALENDAR_CONSTANTS.selectors.DATE);
        elements.forEach(e => setTabindexOnElement(e, -1, false, true));
    }
    setDateDescription(date, value) {
        const dateElement = this._dateGrid.querySelector(`#${getDateId(date)}`);
        if (!dateElement) {
            return;
        }
        toggleAttribute(dateElement, !!value, value);
    }
    setDateTooltip(date, value) {
        const dateElement = this._dateGrid.querySelector(`#${getDateId(date)}`);
        if (!dateElement) {
            return;
        }
        const tooltip = dateElement.querySelector(CALENDAR_CONSTANTS.selectors.TOOLTIP);
        if (tooltip) {
            if (value === null || value === void 0 ? void 0 : value.length) {
                tooltip.textContent = value;
            }
            else {
                tooltip.remove();
            }
        }
        else if (value === null || value === void 0 ? void 0 : value.length) {
            dateElement.prepend(getTooltip(value));
        }
    }
    setEventWrapperOnDate(date, value) {
        const dateElement = this._dateGrid.querySelector(`#${getDateId(date)}`);
        if (!dateElement) {
            return;
        }
        const eventWrapper = dateElement.querySelector(CALENDAR_CONSTANTS.selectors.EVENT_WRAPPER);
        if (eventWrapper) {
            if (value) {
                removeAllChildren(eventWrapper);
            }
            else {
                eventWrapper.remove();
            }
        }
        else if (value) {
            dateElement.appendChild(getEventWrapperElement(date));
        }
    }
    setEvent(event, overflow) {
        const eventWrapper = this._dateGrid.querySelector(`#${getEventWrapperId(event.date)}`);
        eventWrapper === null || eventWrapper === void 0 ? void 0 : eventWrapper.appendChild(getEventElement(event, overflow));
    }
    openMenuAsGrid(options, setFocus) {
        this._menu.openAsGrid(options, setFocus);
    }
    openMenuAsList(options, setFocus) {
        this._menu.openAsList(options, setFocus);
    }
    closeMenu() {
        this._menu.close();
    }
    setMenuAnimation(value) {
        this._menu.animationType = value;
    }
    animateIntoSelectionMenu(options, direction, setFocus) {
        this._menu.animateIn(options, direction, setFocus);
    }
    moveMenuFocusDown() {
        this._menu.moveFocusDown();
    }
    moveMenuFocusBackward() {
        return this._menu.moveFocusBackward();
    }
    moveMenuFocusForward() {
        return this._menu.moveFocusForward();
    }
    moveMenuFocusUp() {
        this._menu.moveFocusUp();
    }
    selectFocusedMenuItem() {
        this._menu.selectFocusedItem();
    }
    setPreventFocusOnMenu(value) {
        this._menu.preventFocus = value;
    }
}
