"use strict";
/*---------------------------------------------------------------------------------------------
 * 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
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.PointerMessage = exports.PointerMessageChangedEvent = void 0;
require("./Pointer.scss");
const classnames_1 = require("classnames");
const React = require("react");
const core_frontend_1 = require("@itwin/core-frontend");
const appui_abstract_1 = require("@itwin/appui-abstract");
const core_react_1 = require("@itwin/core-react");
const appui_layout_react_1 = require("@itwin/appui-layout-react");
const MessageManager_1 = require("./MessageManager");
const MessageSpan_1 = require("./MessageSpan");
/** Pointer Message Changed Event emitted by the [[PointerMessage]] component
 * @public
 */
class PointerMessageChangedEvent extends appui_abstract_1.UiEvent {
}
exports.PointerMessageChangedEvent = PointerMessageChangedEvent;
/** Pointer Message Position Changed Event emitted by the [[PointerMessage]] component
 * @internal
 */
class PointerMessagePositionChangedEvent extends appui_abstract_1.UiEvent {
}
/** Pointer message pops up near pointer when attempting an invalid interaction.
 * @public
 */
class PointerMessage extends React.Component {
    constructor() {
        super(...arguments);
        this.state = {
            message: "",
            isVisible: false,
            position: {
                x: 0,
                y: 0,
            },
        };
        this._size = {
            height: 0,
            width: 0,
        };
        // istanbul ignore next
        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();
        };
    }
    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: core_frontend_1.OutputMessagePriority.None,
            message: "",
        });
    }
    render() {
        if (!this.state.isVisible)
            return null;
        const className = (0, classnames_1.default)("uifw-pointer-message", this.props.className);
        const severity = MessageManager_1.MessageManager.getSeverity(this.state.messageDetails);
        return (React.createElement(appui_layout_react_1.Tooltip, { className: className, onSizeChanged: this._handleSizeChanged, position: this.state.position, style: this.props.style },
            React.createElement("div", { className: "uifw-pointer-message-content" },
                severity !== appui_abstract_1.MessageSeverity.None && (React.createElement("span", { className: "uifw-pointer-message-icon" },
                    React.createElement(core_react_1.Icon, { className: `icon ${core_react_1.MessageContainer.getIconClassName(severity)}`, iconSpec: `${core_react_1.MessageContainer.getIcon(severity, false)}` }))),
                React.createElement("span", { className: "uifw-pointer-message-text" },
                    React.createElement(MessageSpan_1.MessageSpan, { className: "uifw-pointer-message-brief", message: this.state.message }),
                    this.state.detailedMessage && (React.createElement(MessageSpan_1.MessageDiv, { 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 appui_abstract_1.RelativePosition.Top:
                offset = { x: 0, y: -adjustmentOffset };
                break;
            case appui_abstract_1.RelativePosition.TopRight:
                offset = { x: adjustmentOffset, y: -adjustmentOffset };
                break;
            case appui_abstract_1.RelativePosition.Right:
                offset = { x: adjustmentOffset, y: 0 };
                break;
            case appui_abstract_1.RelativePosition.BottomRight:
                offset = { x: adjustmentOffset, y: adjustmentOffset };
                break;
            case appui_abstract_1.RelativePosition.Bottom:
                offset = { x: 0, y: adjustmentOffset };
                break;
            case appui_abstract_1.RelativePosition.BottomLeft:
                offset = { x: -adjustmentOffset, y: adjustmentOffset };
                break;
            case appui_abstract_1.RelativePosition.Left:
                offset = { x: -adjustmentOffset, y: 0 };
                break;
            case appui_abstract_1.RelativePosition.TopLeft:
                offset = { x: -adjustmentOffset, y: -adjustmentOffset };
                break;
        }
        this.setState((prevState) => {
            if (!this._viewport)
                return null;
            // istanbul ignore if
            if (!this._position)
                return null;
            const containerBounds = core_react_1.Rectangle.create(this._viewport.getBoundingClientRect());
            const relativeBounds = core_react_1.Rectangle.createFromSize(this._size).offset(this._position);
            const viewportOffset = new core_react_1.Point().getOffsetTo(containerBounds.topLeft());
            const adjustedPosition = (0, appui_layout_react_1.offsetAndContainInContainer)(relativeBounds, containerBounds.getSize(), offset);
            const position = adjustedPosition.offset(viewportOffset);
            // istanbul ignore else
            if (position.equals(prevState.position))
                return null;
            // istanbul ignore next
            return {
                position,
            };
        });
    }
}
PointerMessage._pointerMessageChangedEvent = new PointerMessageChangedEvent();
PointerMessage._onPointerMessagePositionChangedEvent = new PointerMessagePositionChangedEvent();
exports.PointerMessage = PointerMessage;
//# sourceMappingURL=Pointer.js.map