"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 Popup
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.PopupRenderer = exports.PopupManager = exports.isReactContent = exports.PopupsChangedEvent = void 0;
const React = require("react");
const core_bentley_1 = require("@itwin/core-bentley");
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 UiFramework_1 = require("../UiFramework");
const CardPopup_1 = require("./CardPopup");
const HTMLElementPopup_1 = require("./HTMLElementPopup");
const InputEditorPopup_1 = require("./InputEditorPopup");
const KeyinPalettePopup_1 = require("./KeyinPalettePopup");
const ToolbarPopup_1 = require("./ToolbarPopup");
const ToolSettingsPopup_1 = require("./ToolSettingsPopup");
/** Popups Changed Event class.
 * @public
 */
class PopupsChangedEvent extends appui_abstract_1.UiEvent {
}
exports.PopupsChangedEvent = PopupsChangedEvent;
/** ReactContent type guard.
 * @internal
 */
const isReactContent = (content) => {
    return content.reactNode !== undefined;
};
exports.isReactContent = isReactContent;
/** Popup Manager class
 * @public
 */
class PopupManager {
    static get popupCount() {
        return this._popups.length;
    }
    static get popups() {
        return this._popups;
    }
    static set popups(popups) {
        // istanbul ignore if
        if (this._popups === popups)
            return;
        this._popups = popups;
        this.onPopupsChangedEvent.emit({ popups });
    }
    /** @internal */
    static clearPopups() {
        this.popups = [];
    }
    static addPopup(popupInfo) {
        const popups = [...PopupManager._popups, popupInfo];
        this.popups = popups;
    }
    static updatePopup(popupInfo, itemIndex) {
        // istanbul ignore if
        if (itemIndex < 0)
            return;
        const popups = [
            ...PopupManager._popups.slice(0, itemIndex),
            popupInfo,
            ...PopupManager._popups.slice(itemIndex + 1),
        ];
        this.popups = popups;
    }
    static addOrUpdatePopup(popupInfo) {
        const itemIndex = PopupManager._popups.findIndex((info) => info.id === popupInfo.id);
        if (itemIndex >= 0)
            PopupManager.updatePopup(popupInfo, itemIndex);
        else
            PopupManager.addPopup(popupInfo);
    }
    static removePopup(id) {
        const index = PopupManager._popups.findIndex((info) => id === info.id);
        let result = true;
        if (index >= 0) {
            const popups = PopupManager._popups.filter((info) => {
                return info.id !== id;
            });
            this.popups = popups;
        }
        else {
            core_bentley_1.Logger.logError(UiFramework_1.UiFramework.loggerCategory(this), `removePopup: Could not find popup with id of '${id}'`);
            result = false;
        }
        return result;
    }
    static get defaultOffset() {
        return PopupManager._defaultOffset;
    }
    static set defaultOffset(offset) {
        PopupManager._defaultOffset = offset;
    }
    static showInputEditor(el, pt, value, propertyDescription, onCommit, onCancel) {
        const primitiveValue = {
            value,
            valueFormat: appui_abstract_1.PropertyValueFormat.Primitive,
        };
        const record = new appui_abstract_1.PropertyRecord(primitiveValue, propertyDescription);
        const commitHandler = new InputEditorPopup_1.InputEditorCommitHandler(onCommit);
        const id = PopupManager._editorId;
        const component = (React.createElement(InputEditorPopup_1.InputEditorPopup, { id: id, el: el, pt: pt, offset: PopupManager.defaultOffset, record: record, onCancel: onCancel, commitHandler: commitHandler }));
        const popupInfo = {
            id,
            pt,
            component,
            parentDocument: el.ownerDocument,
        };
        PopupManager.addOrUpdatePopup(popupInfo);
        return true;
    }
    static hideInputEditor() {
        return PopupManager.removePopup(PopupManager._editorId);
    }
    static showKeyinPalette(keyins, el, onItemExecuted, onCancel) {
        const id = PopupManager._keyPalettePopupId;
        const component = (React.createElement(KeyinPalettePopup_1.KeyinPalettePopup, { keyins: keyins, id: id, el: el, onCancel: onCancel, onItemExecuted: onItemExecuted }));
        // since the command palette popup is always at top center of specified HTML element and it does not need to move like
        // cursor popups just set pt to 0,0.
        const pt = { x: 0, y: 0 };
        const popupInfo = {
            id,
            pt,
            component,
            parentDocument: el.ownerDocument,
        };
        PopupManager.addOrUpdatePopup(popupInfo);
        return true;
    }
    static hideKeyinPalette() {
        return PopupManager.removePopup(PopupManager._keyPalettePopupId);
    }
    static showToolbar(toolbarProps, el, pt, offset, onItemExecuted, onCancel, relativePosition) {
        const id = PopupManager._toolbarId;
        const component = (React.createElement(ToolbarPopup_1.ToolbarPopup, { id: id, el: el, pt: pt, offset: offset, items: toolbarProps.items, relativePosition: relativePosition, orientation: core_react_1.Orientation.Horizontal, onCancel: onCancel, onItemExecuted: onItemExecuted }));
        const popupInfo = {
            id,
            pt,
            component,
            parentDocument: el.ownerDocument,
        };
        PopupManager.addOrUpdatePopup(popupInfo);
        return true;
    }
    static hideToolbar() {
        return PopupManager.removePopup(PopupManager._toolbarId);
    }
    static showHTMLElement(displayElement, el, pt, offset, onCancel, relativePosition) {
        const id = PopupManager._htmlElementId;
        const component = (React.createElement(HTMLElementPopup_1.HTMLElementPopup, { id: id, el: el, pt: pt, offset: offset, element: displayElement, relativePosition: relativePosition, orientation: core_react_1.Orientation.Horizontal, onCancel: onCancel }));
        const popupInfo = {
            id,
            pt,
            component,
            parentDocument: el.ownerDocument,
        };
        PopupManager.addOrUpdatePopup(popupInfo);
        return true;
    }
    static hideHTMLElement() {
        return PopupManager.removePopup(PopupManager._htmlElementId);
    }
    static showCard(content, title, toolbarProps, el, pt, offset, onItemExecuted, onCancel, relativePosition) {
        const id = PopupManager._cardId;
        const component = (React.createElement(CardPopup_1.CardPopup, { id: id, el: el, pt: pt, offset: offset, content: content, title: title, items: toolbarProps
                ? toolbarProps.items
                : /* istanbul ignore next */ undefined, relativePosition: relativePosition, orientation: core_react_1.Orientation.Horizontal, onCancel: onCancel, onItemExecuted: onItemExecuted }));
        const popupInfo = {
            id,
            pt,
            component,
            parentDocument: el.ownerDocument,
        };
        PopupManager.addOrUpdatePopup(popupInfo);
        return true;
    }
    static hideCard() {
        const index = PopupManager._popups.findIndex((info) => PopupManager._cardId === info.id);
        if (index >= 0)
            return PopupManager.removePopup(PopupManager._cardId);
        return false;
    }
    static openToolSettings(dataProvider, el, pt, offset, onCancel, relativePosition) {
        const id = PopupManager._toolSettingsId;
        const component = (React.createElement(ToolSettingsPopup_1.ToolSettingsPopup, { id: id, el: el, pt: pt, offset: offset, dataProvider: dataProvider, relativePosition: relativePosition, orientation: core_react_1.Orientation.Horizontal, onCancel: onCancel }));
        const popupInfo = {
            id,
            pt,
            component,
            parentDocument: el.ownerDocument,
        };
        PopupManager.addOrUpdatePopup(popupInfo);
        return true;
    }
    static closeToolSettings() {
        return PopupManager.removePopup(PopupManager._toolSettingsId);
    }
    static getPopupPosition(el, pt, offset, size) {
        const containerBounds = core_react_1.Rectangle.create(el.getBoundingClientRect());
        const relativeBounds = core_react_1.Rectangle.createFromSize(size).offset(pt);
        const adjustedPosition = (0, appui_layout_react_1.offsetAndContainInContainer)(relativeBounds, containerBounds.getSize(), offset);
        const position = adjustedPosition.offset(containerBounds.topLeft());
        return position;
    }
}
PopupManager._popups = [];
PopupManager._editorId = "InputEditor";
PopupManager._toolbarId = "Toolbar";
PopupManager._htmlElementId = "HTMLElement";
PopupManager._cardId = "Card";
PopupManager._toolSettingsId = "ToolSettings";
PopupManager._keyPalettePopupId = "KeyinPalette";
PopupManager._defaultOffset = { x: 8, y: 8 };
PopupManager.onPopupsChangedEvent = new PopupsChangedEvent();
exports.PopupManager = PopupManager;
/**  Popup Renderer
 * @public
 */
class PopupRenderer extends React.Component {
    constructor() {
        super(...arguments);
        /** @internal */
        this.state = {
            parentDocument: null,
            popups: PopupManager.popups,
        };
        this._handleRefSet = (popupDiv) => {
            this.setState({ parentDocument: popupDiv?.ownerDocument ?? null });
        };
        this._handlePopupsChangedEvent = (args) => {
            this.setState({ popups: args.popups });
        };
    }
    componentDidMount() {
        core_bentley_1.Logger.logInfo("PopupManager", `mounting PopupManager`);
        PopupManager.onPopupsChangedEvent.addListener(this._handlePopupsChangedEvent);
    }
    componentWillUnmount() {
        core_bentley_1.Logger.logInfo("PopupManager", `un-mounting PopupManager`);
        PopupManager.onPopupsChangedEvent.removeListener(this._handlePopupsChangedEvent);
    }
    render() {
        if (PopupManager.popupCount <= 0)
            return null;
        return (React.createElement("div", { className: "appui-react-popup-render-container", ref: this._handleRefSet }, this.state.parentDocument &&
            this.state.popups
                .filter((info) => info.parentDocument === this.state.parentDocument)
                .map((popupInfo) => {
                return (React.createElement(React.Fragment, { key: popupInfo.id }, popupInfo.component));
            })));
    }
}
exports.PopupRenderer = PopupRenderer;
//# sourceMappingURL=PopupManager.js.map