/**
 * @license
 * Copyright 2023 Tyler Technologies, Inc. 
 * License: Apache-2.0
 */
import { addClass, getShadowElement, removeElement, replaceElement, getActiveElement, toggleAttribute, toggleClass } from '@tylertech/forge-core';
import { BACKDROP_CONSTANTS } from '../backdrop';
import { BaseAdapter } from '../core/base/base-adapter';
import { BUSY_INDICATOR_CONSTANTS } from './busy-indicator-constants';
/**
 * Provides facilities for interacting with the internal DOM of `BusyIndicatorComponent`.
 */
export class BusyIndicatorAdapter extends BaseAdapter {
    constructor(component) {
        super(component);
        this._parentElement = null;
        this._surfaceElement = getShadowElement(component, BUSY_INDICATOR_CONSTANTS.selectors.SURFACE);
        this._titleElement = getShadowElement(component, BUSY_INDICATOR_CONSTANTS.selectors.TITLE);
        this._messageElement = getShadowElement(component, BUSY_INDICATOR_CONSTANTS.selectors.MESSAGE);
        this._cancelButtonElement = getShadowElement(component, BUSY_INDICATOR_CONSTANTS.selectors.CANCEL);
        this._spinnerElement = getShadowElement(component, BUSY_INDICATOR_CONSTANTS.selectors.SPINNER);
        this._progressBarContainerElement = getShadowElement(component, BUSY_INDICATOR_CONSTANTS.selectors.PROGRESS_BAR_CONTAINER);
        this._progressBarElement = getShadowElement(component, BUSY_INDICATOR_CONSTANTS.selectors.PROGRESS_BAR);
        this._backdropElement = getShadowElement(component, BUSY_INDICATOR_CONSTANTS.selectors.BACKDROP);
    }
    /**
     * Sets the opacity of the content element.
     * @param opacity The opacity value.
     */
    setSurfaceOpacity(opacity) {
        this._surfaceElement.style.opacity = opacity.toString();
    }
    setFixed(value) {
        toggleAttribute(this._backdropElement, value, BACKDROP_CONSTANTS.attributes.FIXED);
        toggleClass(this._surfaceElement, value, BUSY_INDICATOR_CONSTANTS.classes.SURFACE_FIXED);
    }
    /**
     * Sets the content of the title element.
     * @param title The title text.
     */
    setTitle(title) {
        this._titleElement.innerText = title;
    }
    /**
     * Sets the content of the message element.
     * @param message The message text.
     */
    setMessage(message) {
        this._messageElement.innerText = message;
    }
    /**
     * Sets the visibility of the title element by adding or removing it from the DOM.
     * @param visible Whether the title is visible or not.
     */
    setTitleVisibility(visible) {
        this._titlePlaceholderElement = this._toggleElement(visible, BUSY_INDICATOR_CONSTANTS.selectors.TITLE, this._titleElement, this._titlePlaceholderElement);
    }
    /**
     * Adds or removes the cancel button from the DOM.
     * @param visible The visibility value.
     */
    setCancelButtonVisibility(visible) {
        this._cancelButtonPlaceholderElement = this._toggleElement(visible, BUSY_INDICATOR_CONSTANTS.selectors.CANCEL, this._cancelButtonElement, this._cancelButtonPlaceholderElement);
    }
    /**
     * Adds or removes the message element from the DOM.
     * @param visible The visibility value.
     */
    setMessageVisibility(visible) {
        this._messagePlaceholderElement = this._toggleElement(visible, BUSY_INDICATOR_CONSTANTS.selectors.MESSAGE, this._messageElement, this._messagePlaceholderElement);
    }
    /**
     * Adds or removes the spinner element from the DOM.
     * @param visible The visibility value.
     */
    setSpinnerVisibility(visible) {
        this._spinnerPlaceholderElement = this._toggleElement(visible, BUSY_INDICATOR_CONSTANTS.selectors.SPINNER, this._spinnerElement, this._spinnerPlaceholderElement);
    }
    /**
     * Adds or removes the progress bar element from the DOM.
     * @param visible The visibility value.
     */
    setProgressBarVisibility(visible) {
        this._progressBarContainerPlaceholderElement = this._toggleElement(visible, BUSY_INDICATOR_CONSTANTS.selectors.PROGRESS_BAR_CONTAINER, this._progressBarContainerElement, this._progressBarContainerPlaceholderElement);
    }
    /**
     * Sets the determinate state of the progress bar component.
     * @param {boolean} determinate The determinate value.
     */
    setProgressBarDeterminate(determinate) {
        this._progressBarElement.determinate = determinate;
    }
    /**
     * Sets the progress percent for the progress bar component.
     * @param value The progress percent.
     */
    setProgressBarProgress(value) {
        this._progressBarElement.progress = value;
    }
    /**
     * Sets the progress bar component buffer percent.
     * @param value The buffer percent.
     */
    setProgressBarBuffer(value) {
        this._progressBarElement.buffer = value;
    }
    /**
     * Adds an event listener to the cancel button.
     * @param type The event type.
     * @param listener The event listener.
     */
    addCancelButtonEventListener(type, listener) {
        this._cancelButtonElement.addEventListener(type, listener);
    }
    /**
     * Removes an event listener from the cancel button.
     * @param type The event type.
     * @param listener The event listener.
     */
    removeCancelButtonEventListener(type, listener) {
        this._cancelButtonElement.removeEventListener(type, listener);
    }
    /**
     * Sets an attribute on the cancel button.
     * @param name The attribute name.
     * @param value The attribute value.
     */
    setCancelButtonAttribute(name, value) {
        this._cancelButtonElement.setAttribute(name, value);
    }
    /**
     * Sets the text displayed in the cancel button element.
     * @param text The text value.
     */
    setCancelButtonText(text) {
        this._cancelButtonElement.innerText = text;
    }
    /**
     * Sets the width of the surface element.
     * @param value The CSS width.
     */
    setSurfaceWidth(value) {
        this._surfaceElement.style.width = value.toString();
    }
    /**
     * Sets focus to the busy indicator component element.
     */
    captureFocus() {
        this._surfaceElement.focus();
    }
    /**
     * Removes the busy indicator component from its parent.
     */
    remove() {
        removeElement(this._component);
    }
    /**
     * Hides the backdrop by fading it out.
     */
    hideBackdrop() {
        this._backdropElement.fadeOut();
    }
    _toggleElement(isVisible, selector, element, placeholder) {
        const exists = !!getShadowElement(this._component, selector);
        if (!placeholder) {
            placeholder = document.createComment(`(${BUSY_INDICATOR_CONSTANTS.elementName}) ${selector}`);
        }
        if (isVisible && !exists) {
            replaceElement(element, placeholder);
        }
        else if (!isVisible && exists) {
            replaceElement(placeholder, element);
        }
        return placeholder;
    }
    setContainerInvisible() {
        addClass(BUSY_INDICATOR_CONSTANTS.classes.SURFACE_INVISIBLE, this._surfaceElement);
    }
    setBackdropAppearance(appearance) {
        this._backdropElement.setAttribute(BACKDROP_CONSTANTS.attributes.APPEARANCE, String(appearance));
    }
    setParentAttribute(name, value) {
        this._parentElement = this._component.parentElement;
        if (this._parentElement) {
            this._parentElement.setAttribute(name, value);
        }
    }
    removeParentAttribute(name) {
        if (this._parentElement) {
            this._parentElement.removeAttribute(name);
            this._parentElement = null;
        }
    }
    getFocusedElement() {
        return getActiveElement(this._component.ownerDocument);
    }
    hasFocus() {
        const activeElement = this.getFocusedElement();
        return this._component === activeElement || this._surfaceElement === activeElement || this._surfaceElement.contains(activeElement);
    }
}
