/*---------------------------------------------------------------------------------------------
 * 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 "./Pointer.scss";
import classnames from "classnames";
import * as React from "react";
import { MessageSeverity, RelativePosition, UiEvent, } from "@itwin/appui-abstract";
import { OutputMessagePriority } from "@itwin/core-frontend";
import { Icon, MessageContainer, MessageRenderer } from "@itwin/core-react";
import { Point, Rectangle } from "@itwin/core-react/internal";
import { offsetAndContainInContainer, Tooltip, } from "../layout/popup/Tooltip.js";
import { MessageManager } from "./MessageManager.js";
import { BeUiEvent } from "@itwin/core-bentley";
/** Pointer Message Changed Event emitted by the [[PointerMessage]] component
 * @public
 * @deprecated in 4.13.0. This class should not be used by applications to instantiate objects.
 */
// eslint-disable-next-line @typescript-eslint/no-deprecated
export class PointerMessageChangedEvent extends UiEvent {
}
/** Pointer message pops up near pointer when attempting an invalid interaction.
 * @public
 */
export class PointerMessage extends React.Component {
    constructor() {
        super(...arguments);
        this.state = {
            message: "",
            isVisible: false,
            position: {
                x: 0,
                y: 0,
            },
        };
        this._size = {
            height: 0,
            width: 0,
        };
        this._handleSizeChanged = (size) => {
            this._size = size;
            this.updatePosition();
        };
        this._handlePointerMessageChangedEvent = (args) => {
            this._relativePosition = args.relativePosition;
            this._viewport = args.viewport;
            this._position = args.pt;
            this.setState(() => ({
                isVisible: args.isVisible,
                message: args.message,
                detailedMessage: args.detailedMessage,
                messageDetails: args.messageDetails,
            }));
            this.updatePosition();
        };
        this._handlePointerMessagePositionChangedEvent = (args) => {
            this._relativePosition = args.relativePosition;
            this._position = args.pt;
            this.updatePosition();
        };
    }
    // eslint-disable-next-line @typescript-eslint/no-deprecated
    static get onPointerMessageChangedEvent() {
        return PointerMessage._pointerMessageChangedEvent;
    }
    static showMessage(message) {
        PointerMessage.onPointerMessageChangedEvent.emit({
            isVisible: true,
            priority: message.priority,
            message: message.briefMessage,
            detailedMessage: message.detailedMessage,
            relativePosition: message.relativePosition,
            viewport: message.viewport,
            pt: message.displayPoint,
            messageDetails: message,
        });
    }
    static updateMessage(displayPoint, relativePosition) {
        PointerMessage._onPointerMessagePositionChangedEvent.emit({
            pt: displayPoint,
            relativePosition,
        });
    }
    static hideMessage() {
        PointerMessage.onPointerMessageChangedEvent.emit({
            isVisible: false,
            priority: OutputMessagePriority.None,
            message: "",
        });
    }
    render() {
        if (!this.state.isVisible)
            return null;
        const className = classnames("uifw-pointer-message", this.props.className);
        const severity = MessageManager.getSeverity(this.state.messageDetails);
        return (React.createElement(Tooltip, { className: className, onSizeChanged: this._handleSizeChanged, position: this.state.position, style: this.props.style },
            React.createElement("div", { className: "uifw-pointer-message-content" },
                severity !== MessageSeverity.None && (React.createElement("span", { className: "uifw-pointer-message-icon" },
                    React.createElement(Icon
                    // eslint-disable-next-line @typescript-eslint/no-deprecated
                    , { 
                        // eslint-disable-next-line @typescript-eslint/no-deprecated
                        className: `icon ${MessageContainer.getIconClassName(severity)}`, 
                        // eslint-disable-next-line @typescript-eslint/no-deprecated, @typescript-eslint/no-base-to-string, @typescript-eslint/restrict-template-expressions
                        iconSpec: `${MessageContainer.getIcon(severity, false)}` }))),
                React.createElement("span", { className: "uifw-pointer-message-text" },
                    React.createElement(MessageRenderer, { className: "uifw-pointer-message-brief", message: this.state.message, useSpan: true }),
                    this.state.detailedMessage && (
                    // eslint-disable-next-line @typescript-eslint/no-deprecated
                    React.createElement(MessageRenderer, { className: "uifw-pointer-message-detailed", message: this.state.detailedMessage }))))));
    }
    componentDidMount() {
        PointerMessage.onPointerMessageChangedEvent.addListener(this._handlePointerMessageChangedEvent);
        PointerMessage._onPointerMessagePositionChangedEvent.addListener(this._handlePointerMessagePositionChangedEvent);
    }
    componentWillUnmount() {
        PointerMessage.onPointerMessageChangedEvent.removeListener(this._handlePointerMessageChangedEvent);
        PointerMessage._onPointerMessagePositionChangedEvent.removeListener(this._handlePointerMessagePositionChangedEvent);
    }
    updatePosition() {
        const adjustmentOffset = 20;
        let offset;
        switch (this._relativePosition) {
            case RelativePosition.Top:
                offset = { x: 0, y: -adjustmentOffset };
                break;
            case RelativePosition.TopRight:
                offset = { x: adjustmentOffset, y: -adjustmentOffset };
                break;
            case RelativePosition.Right:
                offset = { x: adjustmentOffset, y: 0 };
                break;
            case RelativePosition.BottomRight:
                offset = { x: adjustmentOffset, y: adjustmentOffset };
                break;
            case RelativePosition.Bottom:
                offset = { x: 0, y: adjustmentOffset };
                break;
            case RelativePosition.BottomLeft:
                offset = { x: -adjustmentOffset, y: adjustmentOffset };
                break;
            case RelativePosition.Left:
                offset = { x: -adjustmentOffset, y: 0 };
                break;
            case RelativePosition.TopLeft:
                offset = { x: -adjustmentOffset, y: -adjustmentOffset };
                break;
        }
        this.setState((prevState) => {
            if (!this._viewport)
                return null;
            if (!this._position)
                return null;
            const containerBounds = Rectangle.create(this._viewport.getBoundingClientRect());
            const relativeBounds = Rectangle.createFromSize(this._size).offset(this._position);
            const viewportOffset = new Point().getOffsetTo(containerBounds.topLeft());
            const adjustedPosition = offsetAndContainInContainer(relativeBounds, containerBounds.getSize(), offset);
            const position = adjustedPosition.offset(viewportOffset);
            if (position.equals(prevState.position))
                return null;
            return {
                position,
            };
        });
    }
}
PointerMessage._pointerMessageChangedEvent = new BeUiEvent(); // eslint-disable-line @typescript-eslint/no-deprecated
PointerMessage._onPointerMessagePositionChangedEvent = new BeUiEvent();
//# sourceMappingURL=Pointer.js.map