"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.ToolAssistanceField = void 0;
const core_bentley_1 = require("@itwin/core-bentley");
const core_frontend_1 = require("@itwin/core-frontend");
const core_react_1 = require("@itwin/core-react");
const itwinui_react_1 = require("@itwin/itwinui-react");
const classnames_1 = require("classnames");
const React = require("react");
const UiFramework_1 = require("../../UiFramework");
const CursorPrompt_1 = require("../../cursor/cursorprompt/CursorPrompt");
const MessageManager_1 = require("../../messages/MessageManager");
const useUiStateStorage_1 = require("../../uistate/useUiStateStorage");
require("./ToolAssistanceField.scss");
const itwinui_icons_react_1 = require("@itwin/itwinui-icons-react");
const Dialog_1 = require("../../layout/footer/tool-assistance/Dialog");
const Instruction_1 = require("../../layout/footer/tool-assistance/Instruction");
const Item_1 = require("../../layout/footer/tool-assistance/Item");
const Separator_1 = require("../../layout/footer/tool-assistance/Separator");
const Dialog_2 = require("../../statusbar/dialog/Dialog");
const accept_point_svg_1 = require("./accept-point.svg");
const cursor_click_svg_1 = require("./cursor-click.svg");
const gesture_one_finger_drag_svg_1 = require("./gesture-one-finger-drag.svg");
const gesture_one_finger_tap_double_svg_1 = require("./gesture-one-finger-tap-double.svg");
const gesture_one_finger_tap_svg_1 = require("./gesture-one-finger-tap.svg");
const gesture_pinch_svg_1 = require("./gesture-pinch.svg");
const gesture_two_finger_drag_svg_1 = require("./gesture-two-finger-drag.svg");
const gesture_two_finger_tap_svg_1 = require("./gesture-two-finger-tap.svg");
const mouse_click_left_drag_svg_1 = require("./mouse-click-left-drag.svg");
const mouse_click_left_svg_1 = require("./mouse-click-left.svg");
const mouse_click_right_drag_svg_1 = require("./mouse-click-right-drag.svg");
const mouse_click_right_svg_1 = require("./mouse-click-right.svg");
const mouse_click_wheel_drag_svg_1 = require("./mouse-click-wheel-drag.svg");
const mouse_click_wheel_svg_1 = require("./mouse-click-wheel.svg");
const touch_cursor_pan_svg_1 = require("./touch-cursor-pan.svg");
const touch_cursor_point_svg_1 = require("./touch-cursor-point.svg");
const StatusBarPopover_1 = require("../../statusbar/popup/StatusBarPopover");
/** Tool Assistance Field React component.
 * @public
 * @note Tool assistance field will only display 30 characters in the status bar. Any additional text will be hidden. The full text will always be shown in the opened popover.
 */
class ToolAssistanceField extends React.Component {
    /** @internal */
    constructor(p) {
        super(p);
        this._indicator = React.createRef();
        this._isMounted = false;
        this._handleToolAssistanceChangedEvent = (args // eslint-disable-line deprecation/deprecation
        ) => {
            let showMouseTouchTabs = false;
            let showMouseInstructions = false;
            let showTouchInstructions = false;
            if (args.instructions && args.instructions.sections) {
                const hasMouseInstructions = args.instructions.sections.some((section) => {
                    return section.instructions.some((instruction) => this._isMouseInstruction(instruction));
                });
                const hasTouchInstructions = args.instructions.sections.some((section) => {
                    return section.instructions.some((instruction) => this._isTouchInstruction(instruction));
                });
                if (this.state.includeMouseInstructions &&
                    this.state.includeTouchInstructions &&
                    hasMouseInstructions &&
                    hasTouchInstructions) {
                    showMouseTouchTabs = true;
                    showMouseInstructions = this.state.mouseTouchTabIndex === 0;
                    showTouchInstructions = this.state.mouseTouchTabIndex === 1;
                }
                else {
                    if (this.state.includeMouseInstructions && hasMouseInstructions)
                        showMouseInstructions = true;
                    else if (this.state.includeTouchInstructions && hasTouchInstructions)
                        showTouchInstructions = true;
                }
            }
            if (this._isMounted)
                this.setState({
                    instructions: args.instructions,
                    showMouseTouchTabs,
                    showMouseInstructions,
                    showTouchInstructions,
                }, () => {
                    this._showCursorPrompt();
                });
        };
        this._isBothInstruction = (instruction) => {
            return (instruction.inputMethod === undefined ||
                instruction.inputMethod === core_frontend_1.ToolAssistanceInputMethod.Both);
        };
        this._isMouseInstruction = (instruction) => instruction.inputMethod === core_frontend_1.ToolAssistanceInputMethod.Mouse;
        this._isTouchInstruction = (instruction) => instruction.inputMethod === core_frontend_1.ToolAssistanceInputMethod.Touch;
        this._handleToolIconChangedEvent = (args // eslint-disable-line deprecation/deprecation
        ) => {
            if (this._isMounted)
                this.setState({ toolIconSpec: args.iconSpec }, () => {
                    this._showCursorPrompt();
                });
        };
        this._handleMouseTouchTab = async (index) => {
            const showMouseInstructions = index === 0;
            const showTouchInstructions = index === 1;
            if (this._isMounted)
                this.setState({
                    mouseTouchTabIndex: index,
                    showMouseInstructions,
                    showTouchInstructions,
                }, async () => {
                    await this._mouseTouchTabIndexSetting.saveSetting(this._uiSettingsStorage);
                });
        };
        this._onPromptAtCursorChange = async (e) => {
            if (this._isMounted)
                this.setState({
                    showPromptAtCursor: e.target.checked,
                }, async () => {
                    await this._showPromptAtCursorSetting.saveSetting(this._uiSettingsStorage);
                });
        };
        this._handlePinButtonClick = () => {
            if (this._isMounted)
                this.setState({ isPinned: true });
        };
        this._handleCloseButtonClick = () => {
            this.setIsOpen(false);
        };
        const mobile = core_bentley_1.ProcessDetector.isMobileBrowser;
        this.state = {
            instructions: undefined,
            toolIconSpec: "",
            showPromptAtCursor: p.defaultPromptAtCursor,
            includeMouseInstructions: !mobile,
            includeTouchInstructions: true,
            showMouseTouchTabs: false,
            showMouseInstructions: false,
            showTouchInstructions: false,
            mouseTouchTabIndex: 0,
            isPinned: false,
            isOpen: false,
        };
        this._uiSettingsStorage = new core_react_1.LocalStateStorage();
        this._cursorPrompt = new CursorPrompt_1.CursorPrompt(this.props.cursorPromptTimeout, this.props.fadeOutCursorPrompt);
        this._showPromptAtCursorSetting = new core_react_1.UiStateEntry(ToolAssistanceField._toolAssistanceKey, ToolAssistanceField._showPromptAtCursorKey, () => this.state.showPromptAtCursor);
        this._mouseTouchTabIndexSetting = new core_react_1.UiStateEntry(ToolAssistanceField._toolAssistanceKey, ToolAssistanceField._mouseTouchTabIndexKey, () => this.state.mouseTouchTabIndex);
    }
    /** @internal */
    async componentDidMount() {
        this._isMounted = true;
        MessageManager_1.MessageManager.onToolAssistanceChangedEvent.addListener(this._handleToolAssistanceChangedEvent);
        UiFramework_1.UiFramework.frontstages.onToolIconChangedEvent.addListener(this._handleToolIconChangedEvent);
        if (this.props.uiStateStorage)
            this._uiSettingsStorage = this.props.uiStateStorage;
        else if (this.context)
            this._uiSettingsStorage = this.context;
        await this.restoreSettings();
    }
    /** @internal */
    componentWillUnmount() {
        this._isMounted = false;
        MessageManager_1.MessageManager.onToolAssistanceChangedEvent.removeListener(this._handleToolAssistanceChangedEvent);
        UiFramework_1.UiFramework.frontstages.onToolIconChangedEvent.removeListener(this._handleToolIconChangedEvent);
    }
    async restoreSettings() {
        let getShowPromptAtCursor;
        if (this.props.includePromptAtCursor) {
            getShowPromptAtCursor = this._showPromptAtCursorSetting.getSetting(this._uiSettingsStorage);
        }
        const getMouseTouchTabIndex = this._mouseTouchTabIndexSetting.getSetting(this._uiSettingsStorage);
        const [showPromptAtCursorResult, mouseTouchTabIndexResult] = await Promise.all([getShowPromptAtCursor, getMouseTouchTabIndex]);
        if (showPromptAtCursorResult !== undefined &&
            showPromptAtCursorResult.status === core_react_1.UiStateStorageStatus.Success) {
            if (this._isMounted)
                this.setState({ showPromptAtCursor: showPromptAtCursorResult.setting });
        }
        if (mouseTouchTabIndexResult.status === core_react_1.UiStateStorageStatus.Success) {
            if (this._isMounted)
                this.setState({ mouseTouchTabIndex: mouseTouchTabIndexResult.setting });
        }
    }
    _showCursorPrompt() {
        if (this.state.showPromptAtCursor && this.state.instructions)
            this._cursorPrompt.display(this.state.toolIconSpec, this.state.instructions.mainInstruction);
    }
    _sectionHasDisplayableInstructions(section) {
        const displayableInstructions = this._getDisplayableInstructions(section);
        return displayableInstructions.length > 0;
    }
    _getDisplayableInstructions(section) {
        const displayableInstructions = section.instructions.filter((instruction) => {
            return (this._isBothInstruction(instruction) ||
                (this.state.showMouseInstructions &&
                    this._isMouseInstruction(instruction)) ||
                (this.state.showTouchInstructions &&
                    this._isTouchInstruction(instruction)));
        });
        return displayableInstructions;
    }
    /** @internal */
    render() {
        const { instructions } = this.state;
        const dialogTitle = core_frontend_1.IModelApp.toolAdmin.activeTool
            ? core_frontend_1.IModelApp.toolAdmin.activeTool.flyover
            : UiFramework_1.UiFramework.translate("toolAssistance.title");
        const mouseLabel = UiFramework_1.UiFramework.translate("toolAssistance.mouse");
        const touchLabel = UiFramework_1.UiFramework.translate("toolAssistance.touch");
        let prompt = "";
        let tooltip = "";
        let toolIcon;
        let dialogContent;
        if (instructions) {
            prompt = instructions.mainInstruction.text;
            toolIcon = React.createElement(core_react_1.Icon, { iconSpec: this.state.toolIconSpec });
            let displayableSections;
            if (instructions.sections) {
                displayableSections = instructions.sections.filter((section) => this._sectionHasDisplayableInstructions(section));
            }
            dialogContent = (React.createElement("div", null,
                this.state.showMouseTouchTabs && (React.createElement(itwinui_react_1.Tabs.Wrapper, { type: "pill", value: String(this.state.mouseTouchTabIndex) },
                    React.createElement(itwinui_react_1.Tabs.TabList, { className: "uifw-toolAssistance-tabs" }, [mouseLabel, touchLabel].map((label, index) => (React.createElement(itwinui_react_1.Tabs.Tab, { key: index, className: "uifw-tab", value: String(index), label: label, onClick: async () => this._handleMouseTouchTab(index) })))))),
                React.createElement("div", { className: "uifw-toolAssistance-content" },
                    React.createElement(Instruction_1.ToolAssistanceInstruction, { key: "main", image: ToolAssistanceField.getInstructionImage(instructions.mainInstruction), text: instructions.mainInstruction.text, isNew: instructions.mainInstruction.isNew }),
                    displayableSections &&
                        displayableSections.map((section, index1) => {
                            return (React.createElement(React.Fragment, { key: index1.toString() },
                                React.createElement(Separator_1.ToolAssistanceSeparator, { key: index1.toString() }, section.label),
                                this._getDisplayableInstructions(section).map((instruction, index2) => {
                                    return (React.createElement(Instruction_1.ToolAssistanceInstruction, { key: `${index1.toString()}-${index2.toString()}`, image: ToolAssistanceField.getInstructionImage(instruction), text: instruction.text, isNew: instruction.isNew }));
                                })));
                        }),
                    this.props.includePromptAtCursor && (React.createElement(React.Fragment, null,
                        React.createElement(Separator_1.ToolAssistanceSeparator, { key: "prompt-sep" }),
                        React.createElement(Item_1.ToolAssistanceItem, { key: "prompt-item" },
                            React.createElement(itwinui_react_1.ToggleSwitch, { label: UiFramework_1.UiFramework.translate("toolAssistance.promptAtCursor"), labelPosition: "right", checked: this.state.showPromptAtCursor, onChange: this._onPromptAtCursorChange })))))));
        }
        if (prompt)
            tooltip = prompt;
        if (core_frontend_1.IModelApp.toolAdmin.activeTool)
            tooltip = `${core_frontend_1.IModelApp.toolAdmin.activeTool.flyover} > ${tooltip}  `;
        if (tooltip) {
            const lineBreak = "\u000d\u000a";
            tooltip = tooltip + lineBreak;
        }
        tooltip += UiFramework_1.UiFramework.translate("toolAssistance.moreInfo");
        return (React.createElement(StatusBarPopover_1.StatusBarPopover, { visible: this.state.isOpen, onVisibleChange: (visible) => {
                this.setIsOpen(visible);
            }, closeOnOutsideClick: !this.state.isPinned, content: React.createElement(Dialog_1.ToolAssistanceDialog, { buttons: React.createElement(React.Fragment, null,
                    !this.state.isPinned && (React.createElement(Dialog_2.StatusBarDialog.TitleBarButton, { onClick: this._handlePinButtonClick, title: UiFramework_1.UiFramework.translate("toolAssistance.pin") },
                        React.createElement(itwinui_icons_react_1.SvgPin, null))),
                    this.state.isPinned && (React.createElement(Dialog_2.StatusBarDialog.TitleBarButton, { onClick: this._handleCloseButtonClick, title: UiFramework_1.UiFramework.translate("dialog.close") },
                        React.createElement(itwinui_icons_react_1.SvgClose, null)))), title: dialogTitle }, dialogContent) },
            React.createElement(itwinui_react_1.Button, { styleType: "borderless", startIcon: React.createElement(React.Fragment, null, toolIcon), className: (0, classnames_1.default)("uifw-statusFields-toolAssistance-toolAssistanceField", this.props.className), title: tooltip, style: this.props.style, ref: this._indicator, labelProps: { className: "prompt" } },
                prompt,
                React.createElement(StatusBarPopover_1.StatusBarPopover.ExpandIndicator, null))));
    }
    setIsOpen(isOpen) {
        let newState = {
            isOpen,
        };
        if (!isOpen && this.state.isPinned && this._isMounted) {
            newState = { ...newState, ...{ isPinned: false } };
        }
        this.setState(newState);
    }
    /** @internal */
    static getInstructionImage(instruction) {
        let image;
        if ((typeof instruction.image === "string" ||
            instruction.image !== core_frontend_1.ToolAssistanceImage.Keyboard) &&
            instruction.keyboardInfo) {
            if (instruction.keyboardInfo.keys.length === 1 &&
                !instruction.keyboardInfo.bottomKeys) {
                const key = instruction.keyboardInfo.keys[0];
                const rightImage = typeof instruction.image === "string" ? (React.createElement("div", { className: "uifw-toolassistance-icon-medium" },
                    React.createElement(core_react_1.Icon, { iconSpec: instruction.image }))) : (this.getInstructionSvgImage(instruction, true));
                image = (
                // eslint-disable-next-line deprecation/deprecation
                React.createElement(core_react_1.FillCentered, null,
                    ToolAssistanceField.getKeyNode(key, 0, "uifw-toolassistance-key-modifier"),
                    rightImage));
            }
            else {
                core_bentley_1.Logger.logError(UiFramework_1.UiFramework.loggerCategory(this), `getInstructionImage: Invalid keyboardInfo provided with image`);
            }
        }
        else if (typeof instruction.image === "string") {
            if (instruction.image.length > 0) {
                const svgSource = getWebComponentSource(instruction.image);
                const className = svgSource !== undefined
                    ? "uifw-toolassistance-svg"
                    : "uifw-toolassistance-icon-large";
                image = (React.createElement("div", { className: className },
                    React.createElement(core_react_1.Icon, { iconSpec: svgSource ?? instruction.image })));
            }
        }
        else if (instruction.image === core_frontend_1.ToolAssistanceImage.Keyboard) {
            if (instruction.keyboardInfo) {
                image = ToolAssistanceField.getInstructionKeyboardImage(instruction.keyboardInfo);
            }
            else {
                core_bentley_1.Logger.logError(UiFramework_1.UiFramework.loggerCategory(this), `getInstructionImage: ToolAssistanceImage.Keyboard specified but no keyboardInfo provided`);
            }
        }
        else {
            image = this.getInstructionSvgImage(instruction, false);
        }
        return image;
    }
    static getInstructionSvgImage(instruction, mediumSize) {
        let image;
        let className = mediumSize
            ? "uifw-toolassistance-svg-medium"
            : "uifw-toolassistance-svg";
        if (typeof instruction.image !== "string" &&
            instruction.image !== core_frontend_1.ToolAssistanceImage.Keyboard) {
            const toolAssistanceImage = instruction.image;
            let svgImage = "";
            switch (toolAssistanceImage) {
                case core_frontend_1.ToolAssistanceImage.AcceptPoint:
                    svgImage = accept_point_svg_1.default;
                    break;
                case core_frontend_1.ToolAssistanceImage.CursorClick:
                    svgImage = cursor_click_svg_1.default;
                    break;
                case core_frontend_1.ToolAssistanceImage.LeftClick:
                    svgImage = mouse_click_left_svg_1.default;
                    break;
                case core_frontend_1.ToolAssistanceImage.RightClick:
                    svgImage = mouse_click_right_svg_1.default;
                    break;
                case core_frontend_1.ToolAssistanceImage.MouseWheel:
                    svgImage = mouse_click_wheel_svg_1.default;
                    break;
                case core_frontend_1.ToolAssistanceImage.LeftClickDrag:
                    svgImage = mouse_click_left_drag_svg_1.default;
                    className = mediumSize
                        ? "uifw-toolassistance-svg-medium-wide"
                        : "uifw-toolassistance-svg-wide";
                    break;
                case core_frontend_1.ToolAssistanceImage.RightClickDrag:
                    svgImage = mouse_click_right_drag_svg_1.default;
                    className = mediumSize
                        ? "uifw-toolassistance-svg-medium-wide"
                        : "uifw-toolassistance-svg-wide";
                    break;
                case core_frontend_1.ToolAssistanceImage.MouseWheelClickDrag:
                    svgImage = mouse_click_wheel_drag_svg_1.default;
                    className = mediumSize
                        ? "uifw-toolassistance-svg-medium-wide"
                        : "uifw-toolassistance-svg-wide";
                    break;
                case core_frontend_1.ToolAssistanceImage.OneTouchTap:
                    svgImage = gesture_one_finger_tap_svg_1.default;
                    break;
                case core_frontend_1.ToolAssistanceImage.OneTouchDoubleTap:
                    svgImage = gesture_one_finger_tap_double_svg_1.default;
                    break;
                case core_frontend_1.ToolAssistanceImage.OneTouchDrag:
                    svgImage = gesture_one_finger_drag_svg_1.default;
                    break;
                case core_frontend_1.ToolAssistanceImage.TwoTouchTap:
                    svgImage = gesture_two_finger_tap_svg_1.default;
                    break;
                case core_frontend_1.ToolAssistanceImage.TwoTouchDrag:
                    svgImage = gesture_two_finger_drag_svg_1.default;
                    break;
                case core_frontend_1.ToolAssistanceImage.TwoTouchPinch:
                    svgImage = gesture_pinch_svg_1.default;
                    break;
                case core_frontend_1.ToolAssistanceImage.TouchCursorTap:
                    svgImage = touch_cursor_point_svg_1.default;
                    break;
                case core_frontend_1.ToolAssistanceImage.TouchCursorDrag:
                    svgImage = touch_cursor_pan_svg_1.default;
                    className = mediumSize
                        ? "uifw-toolassistance-svg-medium-wide"
                        : "uifw-toolassistance-svg-wide";
                    break;
            }
            image = (React.createElement("div", { className: className }, svgImage && React.createElement(core_react_1.Icon, { iconSpec: svgImage })));
        }
        return image;
    }
    static getInstructionKeyboardImage(keyboardInfo) {
        let image;
        if (keyboardInfo.bottomKeys !== undefined) {
            image = (React.createElement("div", { className: "uifw-toolassistance-key-group" },
                React.createElement("span", { className: "row1" }, keyboardInfo.keys.map((key, index1) => {
                    return ToolAssistanceField.getKeyNode(key, index1, "uifw-toolassistance-key-small");
                })),
                React.createElement("br", null),
                React.createElement("span", { className: "row2" }, keyboardInfo.bottomKeys.map((key, index2) => {
                    return ToolAssistanceField.getKeyNode(key, index2, "uifw-toolassistance-key-small");
                }))));
        }
        else if (keyboardInfo.keys.length === 2) {
            image = (
            // eslint-disable-next-line deprecation/deprecation
            React.createElement(core_react_1.FillCentered, null, keyboardInfo.keys.map((key, index3) => {
                let className = "uifw-toolassistance-key-medium";
                if (key.length > 1)
                    className = "uifw-toolassistance-key-modifier";
                return ToolAssistanceField.getKeyNode(key, index3, className);
            })));
        }
        else if (keyboardInfo.keys[0]) {
            if (keyboardInfo.keys[0].length > 1)
                image = ToolAssistanceField.getKeyNode(keyboardInfo.keys[0], 0, "uifw-toolassistance-key-large");
            else
                image = ToolAssistanceField.getKeyNode(keyboardInfo.keys[0], 0);
        }
        else {
            core_bentley_1.Logger.logError(UiFramework_1.UiFramework.loggerCategory(this), `ToolAssistanceImage.Keyboard specified but ToolAssistanceKeyboardInfo not valid`);
        }
        return image;
    }
    static getKeyNode(key, index, className) {
        return (React.createElement("div", { key: index.toString(), className: (0, classnames_1.default)("uifw-toolassistance-key", className) },
            React.createElement(core_react_1.FillCentered, null, key)));
    }
}
exports.ToolAssistanceField = ToolAssistanceField;
/** @internal */
ToolAssistanceField.contextType = useUiStateStorage_1.UiStateStorageContext;
ToolAssistanceField._toolAssistanceKey = "ToolAssistance";
ToolAssistanceField._showPromptAtCursorKey = "showPromptAtCursor";
ToolAssistanceField._mouseTouchTabIndexKey = "mouseTouchTabIndex";
/** @internal */
ToolAssistanceField.defaultProps = {
    includePromptAtCursor: true,
    cursorPromptTimeout: 5000,
    fadeOutCursorPrompt: true,
    defaultPromptAtCursor: false,
};
function getWebComponentSource(iconSpec) {
    if (iconSpec.startsWith("webSvg:") && iconSpec.length > 7) {
        return iconSpec.slice(7);
    }
    return undefined;
}
//# sourceMappingURL=ToolAssistanceField.js.map