/*!
 * KoliBri - The accessible HTML-Standard
 */
import { autoUpdate } from "@floating-ui/dom";
import { getDocument } from "../../../schema";
import { alignFloatingElements } from "../../../utils/align-floating-elements";
import { hideOverlay, showOverlay } from "../../../utils/overlay";
import { tooltipClosed, tooltipOpened } from "../../../utils/tooltip-open-tracking";
import { alignProp, badgeTextProp, idProp, labelProp } from "../../props";
import { BaseController } from "../base-controller";
import { tooltipPropsConfig } from "./api";
export class TooltipController extends BaseController {
    constructor(stateAccess) {
        super(stateAccess, tooltipPropsConfig);
        this.hasFocusIn = false;
        this.hasMouseIn = false;
        this.isHiddenForCurrentVisit = false;
        this.setTooltipElementRef = (el) => {
            this.tooltipElement = el;
            if (this.tooltipElement) {
                this.addListeners(this.tooltipElement);
            }
        };
        this.hideTooltipByEscape = (event) => {
            if (event.key === 'Escape') {
                this.hideTooltip();
            }
        };
        this.handleMouseEnter = () => {
            const isNewVisit = this.isNewVisit();
            this.hasMouseIn = true;
            if (isNewVisit) {
                this.isHiddenForCurrentVisit = false;
            }
            this.showOrHideTooltip();
        };
        this.handleMouseLeave = () => {
            this.hasMouseIn = false;
            this.resetHideFlag();
            this.showOrHideTooltip();
        };
        this.handleFocusIn = () => {
            const isNewVisit = this.isNewVisit();
            this.hasFocusIn = true;
            if (isNewVisit) {
                this.isHiddenForCurrentVisit = false;
            }
            this.showOrHideTooltip();
        };
        this.handleFocusOut = () => {
            this.hasFocusIn = false;
            this.resetHideFlag();
            this.showOrHideTooltip();
        };
    }
    componentWillLoad(props) {
        this.watchLabel(props.label);
        this.watchAlign(props.align);
        this.watchBadgeText(props.badgeText);
        this.watchId(props.id);
    }
    watchLabel(value) {
        labelProp.apply(value, (v) => {
            this.setRenderProp('label', v);
        });
    }
    watchAlign(value) {
        alignProp.apply(value, (v) => {
            this.setRenderProp('align', v);
        });
    }
    watchBadgeText(value) {
        badgeTextProp.apply(value, (v) => {
            this.setRenderProp('badgeText', v);
        });
    }
    watchId(value) {
        idProp.apply(value, (v) => {
            this.setRenderProp('id', v);
        });
    }
    initContext(previousSibling) {
        this.previousSibling = previousSibling;
    }
    syncListeners(last, next, replacePreviousSibling = false) {
        if (last) {
            this.removeListeners(last);
        }
        if (next) {
            if (replacePreviousSibling) {
                this.previousSibling = next;
            }
            this.addListeners(next);
        }
    }
    handleEventListeners(host) {
        const nextSibling = host.previousElementSibling;
        this.syncListeners(this.previousSibling, nextSibling, true);
    }
    hideTooltip() {
        this.isHiddenForCurrentVisit = true;
        if (this.tooltipElement) {
            hideOverlay(this.tooltipElement);
            tooltipClosed();
            this.tooltipElement.classList.remove('show');
            this.tooltipElement.classList.add('hide');
            if (this.cleanupAutoPositioning) {
                this.cleanupAutoPositioning();
                this.cleanupAutoPositioning = undefined;
            }
        }
        getDocument().removeEventListener('keyup', this.hideTooltipByEscape);
    }
    destroy() {
        clearTimeout(this.overFocusTimeout);
        if (this.previousSibling) {
            this.removeListeners(this.previousSibling);
            this.previousSibling = undefined;
        }
        if (this.tooltipElement) {
            this.removeListeners(this.tooltipElement);
        }
        if (this.cleanupAutoPositioning) {
            this.cleanupAutoPositioning();
            this.cleanupAutoPositioning = undefined;
        }
        getDocument().removeEventListener('keyup', this.hideTooltipByEscape);
    }
    isNewVisit() {
        return !this.hasMouseIn && !this.hasFocusIn;
    }
    resetHideFlag() {
        if (this.isNewVisit()) {
            this.isHiddenForCurrentVisit = false;
        }
    }
    async alignTooltip() {
        if (this.tooltipElement && this.previousSibling) {
            await alignFloatingElements({
                align: this.getRenderProp('align'),
                arrowElement: this.tooltipElement.querySelector('.kol-tooltip__arrow'),
                floatingElement: this.tooltipElement,
                referenceElement: this.previousSibling,
            });
        }
    }
    showTooltip() {
        if (this.isHiddenForCurrentVisit) {
            return;
        }
        if (this.previousSibling && this.tooltipElement) {
            showOverlay(this.tooltipElement);
            tooltipOpened();
            this.tooltipElement.classList.remove('hide');
            this.tooltipElement.classList.add('show');
            this.tooltipElement.style.setProperty('display', 'block');
            getDocument().addEventListener('keyup', this.hideTooltipByEscape, { once: true });
            const target = this.previousSibling;
            const tooltipEl = this.tooltipElement;
            this.cleanupAutoPositioning = autoUpdate(target, tooltipEl, () => {
                void this.alignTooltip();
            });
        }
    }
    showOrHideTooltip() {
        clearTimeout(this.overFocusTimeout);
        this.overFocusTimeout = setTimeout(() => {
            if (this.hasMouseIn || this.hasFocusIn) {
                this.showTooltip();
            }
            else {
                this.hideTooltip();
            }
        }, 300);
    }
    addListeners(el) {
        el.addEventListener('mouseover', this.handleMouseEnter);
        el.addEventListener('mouseout', this.handleMouseLeave);
        el.addEventListener('focusin', this.handleFocusIn);
        el.addEventListener('focusout', this.handleFocusOut);
    }
    removeListeners(el) {
        el.removeEventListener('mouseover', this.handleMouseEnter);
        el.removeEventListener('mouseout', this.handleMouseLeave);
        el.removeEventListener('focusin', this.handleFocusIn);
        el.removeEventListener('focusout', this.handleFocusOut);
    }
}
//# sourceMappingURL=controller.js.map
