/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module Notification
 */
import classnames from "classnames";
import * as React from "react";
import { UiEvent } from "@itwin/appui-abstract";
import { Rectangle } from "@itwin/core-react";
import { offsetAndContainInContainer, Tooltip } from "@itwin/appui-layout-react";
import { MessageDiv } from "../messages/MessageSpan";
/** ElementTooltip Changed Event class.
 * @public
 */
export class ElementTooltipChangedEvent extends UiEvent {
}
/** ElementTooltip React component.
 * @public
 */
export class ElementTooltip extends React.Component {
    constructor(props) {
        super(props);
        this._size = {
            height: 0,
            width: 0,
        };
        /** @internal */
        this.state = {
            message: "",
            isVisible: false,
            position: {
                x: 0,
                y: 0,
            },
        };
        this._handleElementTooltipChangedEvent = (args) => {
            this._element = args.el;
            this._position = args.pt;
            this.setState({
                isVisible: args.isTooltipVisible,
                message: args.message,
            });
            this.updatePosition();
        };
        // istanbul ignore next
        this._handleSizeChanged = (size) => {
            this._size = size;
            this.updatePosition();
        };
    }
    static get onElementTooltipChangedEvent() { return ElementTooltip._elementTooltipChangedEvent; }
    static get isTooltipVisible() { return ElementTooltip._isTooltipVisible; }
    static showTooltip(el, message, pt, options) {
        // istanbul ignore if
        if (ElementTooltip._isTooltipHalted)
            return;
        ElementTooltip._isTooltipVisible = true;
        ElementTooltip.onElementTooltipChangedEvent.emit({ isTooltipVisible: true, el, message, pt, options });
        el.ownerDocument.addEventListener("mousemove", ElementTooltip._handleMouseMove);
    }
    static hideTooltip() {
        ElementTooltip._isTooltipVisible = false;
        ElementTooltip.onElementTooltipChangedEvent.emit({ isTooltipVisible: false, message: "" });
    }
    // istanbul ignore next
    static get isTooltipHalted() { return ElementTooltip._isTooltipHalted; }
    // istanbul ignore next
    static set isTooltipHalted(halt) {
        ElementTooltip._isTooltipHalted = halt;
        if (halt && ElementTooltip._isTooltipVisible)
            ElementTooltip.hideTooltip();
    }
    render() {
        if (!this.state.isVisible)
            return null;
        const className = classnames("uifw-element-tooltip", this.props.className);
        const messageNode = React.createElement(MessageDiv, { message: this.state.message });
        return (React.createElement("div", { className: "uifw-element-tooltip-container" },
            React.createElement(Tooltip // eslint-disable-line deprecation/deprecation
            , { className: className, style: this.props.style, position: this.state.position, onSizeChanged: this._handleSizeChanged }, messageNode)));
    }
    componentDidMount() {
        ElementTooltip.onElementTooltipChangedEvent.addListener(this._handleElementTooltipChangedEvent);
    }
    componentWillUnmount() {
        ElementTooltip.onElementTooltipChangedEvent.removeListener(this._handleElementTooltipChangedEvent);
    }
    static _handleMouseMove(event) {
        const el = event.currentTarget;
        /* Only monitor mouse movement when an ElementTooltip is open. */
        if (el && ElementTooltip._isTooltipHalted || !ElementTooltip._isTooltipVisible) {
            el.removeEventListener("mousemove", ElementTooltip._handleMouseMove);
            return;
        }
        const hoveredElement = el ? el.elementFromPoint(event.clientX, event.clientY) : undefined;
        /* If the mouse has moved to an element that is not the view canvas, close the ElementTooltip. */
        // istanbul ignore next.
        if (hoveredElement && hoveredElement.localName !== "canvas") {
            ElementTooltip.onElementTooltipChangedEvent.emit({ isTooltipVisible: false, message: "" });
            el.removeEventListener("mousemove", ElementTooltip._handleMouseMove);
            return;
        }
    }
    updatePosition() {
        this.setState((prevState) => {
            if (!this._element)
                return null;
            // istanbul ignore next
            if (!this._position)
                return null;
            const containerBounds = Rectangle.create(this._element.getBoundingClientRect());
            const relativeBounds = Rectangle.createFromSize(this._size).offset(this._position);
            const adjustedPosition = offsetAndContainInContainer(relativeBounds, containerBounds.getSize(), { x: 8, y: 8 });
            const position = adjustedPosition.offset(containerBounds.topLeft());
            // istanbul ignore else
            if (position.equals(prevState.position))
                return null;
            // istanbul ignore next
            return {
                position,
            };
        });
    }
}
ElementTooltip._elementTooltipChangedEvent = new ElementTooltipChangedEvent();
//# sourceMappingURL=ElementTooltip.js.map