/*---------------------------------------------------------------------------------------------
 * 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 { Logger, ProcessDetector } from "@itwin/core-bentley";
import { ToolAssistanceImage, ToolAssistanceInputMethod, } from "@itwin/core-frontend";
import { FillCentered, Icon } from "@itwin/core-react";
import { Button, Tabs, ToggleSwitch } from "@itwin/itwinui-react";
import classnames from "classnames";
import * as React from "react";
import { UiFramework } from "../../UiFramework.js";
import { useCursorPrompt } from "../../cursor/cursorprompt/CursorPrompt.js";
import { MessageManager } from "../../messages/MessageManager.js";
import { UiStateStorageContext } from "../../uistate/useUiStateStorage.js";
import "./ToolAssistanceField.scss";
import { SvgAdd, SvgClose, SvgCursorClick, SvgGestureOneFingerDrag, SvgGestureOneFingerTap, SvgGestureOneFingerTapDouble, SvgGesturePinch, SvgGestureTwoFingerDrag, SvgGestureTwoFingerTap, SvgMouseClickLeft, SvgMouseClickRight, SvgMouseClickWheel, SvgPin, } from "@itwin/itwinui-icons-react";
import { ToolAssistanceDialog } from "../../layout/footer/tool-assistance/Dialog.js";
import { ToolAssistanceInstruction as NZ_ToolAssistanceInstruction } from "../../layout/footer/tool-assistance/Instruction.js";
import { ToolAssistanceItem } from "../../layout/footer/tool-assistance/Item.js";
import { ToolAssistanceSeparator } from "../../layout/footer/tool-assistance/Separator.js";
import { StatusBarDialog } from "../../statusbar/dialog/Dialog.js";
import { StatusBarPopover } from "../../statusbar/popup/StatusBarPopover.js";
import { UiStateStorageStatus, } from "../../uistate/UiStateStorage.js";
import { SvgTouchCursorPoint } from "../../icons/SvgTouchCursorPoint.js";
import { SvgTouchCursorPan } from "../../icons/SvgTouchCursorPan.js";
import { SvgMouseClickLeftDrag } from "../../icons/SvgMouseClickLeftDrag.js";
import { SvgMouseClickRightDrag } from "../../icons/SvgMouseClickRightDrag.js";
import { SvgMouseClickWheelDrag } from "../../icons/SvgMouseClickWheelDrag.js";
import { useTranslation } from "../../hooks/useTranslation.js";
import { useActiveTool } from "../../hooks/useActiveTool.js";
import { useControlledState } from "../../hooks/useControlledState.js";
const toolAssistanceKey = "ToolAssistance";
const showPromptAtCursorKey = "showPromptAtCursor";
const mouseTouchTabIndexKey = "mouseTouchTabIndex";
/** 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.
 */
export function ToolAssistanceField(props) {
    const { includePromptAtCursor = true, cursorPromptTimeout = 5000, fadeOutCursorPrompt = true, defaultPromptAtCursor = false, uiStateStorage: uiStateStorageProp, promptAtContent = false, visible: visibleProp, onVisibleChange, pinned: pinnedProp, onPinnedChange, } = props;
    const uiStateStorageCtx = React.useContext(UiStateStorageContext);
    const uiStateStorage = uiStateStorageProp ?? uiStateStorageCtx;
    const { translate } = useTranslation();
    const activeTool = useActiveTool();
    const [state, setState] = React.useState(() => {
        return {
            instructions: undefined,
            toolIconSpec: "",
            showPromptAtCursor: defaultPromptAtCursor,
            mouseTouchTabIndex: 0,
        };
    });
    const { showPromptAtCursor, toolIconSpec, mouseTouchTabIndex, instructions } = state;
    const mainInstruction = state.instructions?.mainInstruction.text;
    const { open } = useCursorPrompt({
        show: showPromptAtCursor,
        timeout: cursorPromptTimeout,
        iconSpec: toolIconSpec,
        instruction: mainInstruction,
        fadeOut: fadeOutCursorPrompt,
        promptAtContent,
    });
    const handleClose = () => {
        if (pinned) {
            setPinned(false);
        }
        setVisible(false);
    };
    const getDisplayableInstructions = (section) => {
        const displayableInstructions = section.instructions.filter((instruction) => {
            const includeMouseInstructions = showMouseTouchTabs
                ? mouseTouchTabIndex === 0 && showMouseInstructions
                : showMouseInstructions;
            const includeTouchInstructions = showMouseTouchTabs
                ? mouseTouchTabIndex === 1 && showTouchInstructions
                : showTouchInstructions;
            return (isBothInstruction(instruction) ||
                (includeMouseInstructions && isMouseInstruction(instruction)) ||
                (includeTouchInstructions && isTouchInstruction(instruction)));
        });
        return displayableInstructions;
    };
    React.useEffect(() => {
        void (async () => {
            const result = await uiStateStorage.getSetting(toolAssistanceKey, showPromptAtCursorKey);
            if (result.status !== UiStateStorageStatus.Success)
                return;
            setState((prev) => ({
                ...prev,
                showPromptAtCursor: result.setting,
            }));
        })();
    }, [uiStateStorage]);
    React.useEffect(() => {
        void (async () => {
            const result = await uiStateStorage.getSetting(toolAssistanceKey, mouseTouchTabIndexKey);
            if (result.status !== UiStateStorageStatus.Success)
                return;
            setState((prev) => ({
                ...prev,
                mouseTouchTabIndex: result.setting,
            }));
        })();
    }, [uiStateStorage]);
    React.useEffect(() => {
        return MessageManager.onToolAssistanceChangedEvent.addListener((args) => {
            setState((prev) => ({
                ...prev,
                instructions: args.instructions,
            }));
            open();
        });
    }, [open]);
    React.useEffect(() => {
        return UiFramework.frontstages.onToolIconChangedEvent.addListener((args) => {
            setState((prev) => ({
                ...prev,
                toolIconSpec: args.iconSpec,
            }));
            open();
        });
    }, [open]);
    const hasMouseInstructions = !!instructions?.sections?.some((section) => {
        return section.instructions.some((instruction) => isMouseInstruction(instruction));
    });
    const hasTouchInstructions = !!instructions?.sections?.some((section) => {
        return section.instructions.some((instruction) => isTouchInstruction(instruction));
    });
    const isMobileBrowser = React.useMemo(() => {
        return ProcessDetector.isMobileBrowser;
    }, []);
    const showMouseInstructions = !isMobileBrowser && hasMouseInstructions;
    const showTouchInstructions = hasTouchInstructions;
    const showMouseTouchTabs = showMouseInstructions && showTouchInstructions;
    const sectionInstructions = (instructions?.sections ?? [])
        .map((section) => {
        const displayableInstructions = getDisplayableInstructions(section);
        return {
            displayableInstructions,
            section,
        };
    })
        .filter((section) => {
        return section.displayableInstructions.length > 0;
    });
    const prompt = instructions?.mainInstruction.text;
    const tooltip = React.useMemo(() => {
        const lineBreak = "\u000d\u000a";
        const moreInfo = translate("toolAssistance.moreInfo");
        const postfix = `${lineBreak}${moreInfo}`;
        if (activeTool) {
            return `${activeTool.flyover}${prompt ? ` > ${prompt}` : ""}${postfix}`;
        }
        if (prompt) {
            return `${prompt}${postfix}`;
        }
        return moreInfo;
    }, [prompt, activeTool, translate]);
    const dialogTitle = activeTool?.flyover ?? translate("toolAssistance.title");
    const tabs = [
        translate("toolAssistance.mouse"),
        translate("toolAssistance.touch"),
    ];
    const [visible, setVisible] = useControlledState(false, visibleProp, onVisibleChange);
    const [pinned, setPinned] = useControlledState(false, pinnedProp, onPinnedChange);
    return (React.createElement(StatusBarPopover, { visible: visible, onVisibleChange: setVisible, closeOnOutsideClick: !pinned, content: React.createElement(ToolAssistanceDialog, { buttons: React.createElement(StatusBarDialog.TitleBarButton, { onClick: () => {
                    if (pinned) {
                        handleClose();
                        return;
                    }
                    setPinned(true);
                }, title: translate(pinned ? "dialog.close" : "toolAssistance.pin") }, pinned ? React.createElement(SvgClose, null) : React.createElement(SvgPin, null)), title: dialogTitle },
            React.createElement("div", null,
                showMouseTouchTabs && (React.createElement(Tabs.Wrapper, { type: "pill", value: String(mouseTouchTabIndex) },
                    React.createElement(Tabs.TabList, { className: "uifw-toolAssistance-tabs" }, tabs.map((tab, index) => (React.createElement(Tabs.Tab, { key: index, className: "uifw-tab", value: String(index), label: tab, onClick: async () => {
                            setState((prev) => ({
                                ...prev,
                                mouseTouchTabIndex: index,
                            }));
                            void uiStateStorage.saveSetting(toolAssistanceKey, mouseTouchTabIndexKey, index);
                        } })))))),
                instructions ? (React.createElement("div", { className: "uifw-toolAssistance-content" },
                    React.createElement(NZ_ToolAssistanceInstruction, { key: "main", image: React.createElement(InstructionImage, { instruction: instructions.mainInstruction }), text: instructions.mainInstruction.text, isNew: instructions.mainInstruction.isNew }),
                    sectionInstructions.map((sectionInstruction, index) => {
                        const { section, displayableInstructions } = sectionInstruction;
                        return (React.createElement(React.Fragment, { key: index.toString() },
                            React.createElement(ToolAssistanceSeparator, null, section.label),
                            displayableInstructions.map((instruction, index1) => {
                                return (React.createElement(NZ_ToolAssistanceInstruction, { key: `${index1.toString()}-${index.toString()}`, image: React.createElement(InstructionImage, { instruction: instruction }), text: instruction.text, isNew: instruction.isNew }));
                            })));
                    }),
                    includePromptAtCursor && (React.createElement(React.Fragment, null,
                        React.createElement(ToolAssistanceSeparator, { key: "prompt-sep" }),
                        React.createElement(ToolAssistanceItem, { key: "prompt-item" },
                            React.createElement(ToggleSwitch, { label: translate("toolAssistance.promptAtCursor"), labelPosition: "right", checked: state.showPromptAtCursor, onChange: (e) => {
                                    const checked = e.target.checked;
                                    setState((prev) => ({
                                        ...prev,
                                        showPromptAtCursor: checked,
                                    }));
                                    void uiStateStorage.saveSetting(toolAssistanceKey, showPromptAtCursorKey, checked);
                                } })))))) : undefined)) },
        React.createElement(Button, { styleType: "borderless", startIcon: instructions ? (
            // eslint-disable-next-line @typescript-eslint/no-deprecated
            React.createElement(Icon, { iconSpec: state.toolIconSpec })) : (React.createElement(React.Fragment, null)), className: classnames("uifw-statusFields-toolAssistance-toolAssistanceField", props.className), title: tooltip, style: props.style, labelProps: { className: "prompt" } },
            prompt,
            React.createElement(StatusBarPopover.ExpandIndicator, null))));
}
function isBothInstruction(instruction) {
    return (instruction.inputMethod === undefined ||
        instruction.inputMethod === ToolAssistanceInputMethod.Both);
}
function isMouseInstruction(instruction) {
    return instruction.inputMethod === ToolAssistanceInputMethod.Mouse;
}
function isTouchInstruction(instruction) {
    return instruction.inputMethod === ToolAssistanceInputMethod.Touch;
}
function getWebComponentSource(iconSpec) {
    if (iconSpec.startsWith("webSvg:") && iconSpec.length > 7) {
        return iconSpec.slice(7);
    }
    return undefined;
}
function InstructionImage({ instruction, }) {
    let image;
    if (instruction.iconElement)
        return instruction.iconElement;
    if ((typeof instruction.image === "string" ||
        instruction.image !== 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(Icon, { iconSpec: instruction.image }))) : (React.createElement(InstructionSvgImage, { instruction: instruction, mediumSize: true }));
            image = (
            // eslint-disable-next-line @typescript-eslint/no-deprecated
            React.createElement(FillCentered, null,
                React.createElement(KeyNode, { keyboardKey: key, className: "uifw-toolassistance-key-modifier" }),
                rightImage));
        }
        else {
            Logger.logError(UiFramework.loggerCategory("ToolAssistanceField"), `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(Icon, { iconSpec: svgSource ?? instruction.image })));
        }
    }
    else if (instruction.image === ToolAssistanceImage.Keyboard) {
        if (instruction.keyboardInfo) {
            image = (React.createElement(InstructionKeyboardImage, { keyboardInfo: instruction.keyboardInfo }));
        }
        else {
            Logger.logError(UiFramework.loggerCategory("ToolAssistanceField"), `getInstructionImage: ToolAssistanceImage.Keyboard specified but no keyboardInfo provided`);
        }
    }
    else {
        image = (React.createElement(InstructionSvgImage, { instruction: instruction, mediumSize: false }));
    }
    return image;
}
function InstructionSvgImage({ instruction, mediumSize, }) {
    let image;
    let className = mediumSize
        ? "uifw-toolassistance-svg-medium"
        : "uifw-toolassistance-svg";
    if (typeof instruction.image !== "string" &&
        instruction.image !== ToolAssistanceImage.Keyboard) {
        const toolAssistanceImage = instruction.image;
        let svgImage;
        switch (toolAssistanceImage) {
            case ToolAssistanceImage.AcceptPoint:
                svgImage = React.createElement(SvgAdd, null);
                break;
            case ToolAssistanceImage.CursorClick:
                svgImage = React.createElement(SvgCursorClick, null);
                break;
            case ToolAssistanceImage.LeftClick:
                svgImage = React.createElement(SvgMouseClickLeft, null);
                break;
            case ToolAssistanceImage.RightClick:
                svgImage = React.createElement(SvgMouseClickRight, null);
                break;
            case ToolAssistanceImage.MouseWheel:
                svgImage = React.createElement(SvgMouseClickWheel, null);
                break;
            case ToolAssistanceImage.LeftClickDrag:
                svgImage = React.createElement(SvgMouseClickLeftDrag, null);
                className = mediumSize
                    ? "uifw-toolassistance-svg-medium-wide"
                    : "uifw-toolassistance-svg-wide";
                break;
            case ToolAssistanceImage.RightClickDrag:
                svgImage = React.createElement(SvgMouseClickRightDrag, null);
                className = mediumSize
                    ? "uifw-toolassistance-svg-medium-wide"
                    : "uifw-toolassistance-svg-wide";
                break;
            case ToolAssistanceImage.MouseWheelClickDrag:
                svgImage = React.createElement(SvgMouseClickWheelDrag, null);
                className = mediumSize
                    ? "uifw-toolassistance-svg-medium-wide"
                    : "uifw-toolassistance-svg-wide";
                break;
            case ToolAssistanceImage.OneTouchTap:
                svgImage = React.createElement(SvgGestureOneFingerTap, null);
                break;
            case ToolAssistanceImage.OneTouchDoubleTap:
                svgImage = React.createElement(SvgGestureOneFingerTapDouble, null);
                break;
            case ToolAssistanceImage.OneTouchDrag:
                svgImage = React.createElement(SvgGestureOneFingerDrag, null);
                break;
            case ToolAssistanceImage.TwoTouchTap:
                svgImage = React.createElement(SvgGestureTwoFingerTap, null);
                break;
            case ToolAssistanceImage.TwoTouchDrag:
                svgImage = React.createElement(SvgGestureTwoFingerDrag, null);
                break;
            case ToolAssistanceImage.TwoTouchPinch:
                svgImage = React.createElement(SvgGesturePinch, null);
                break;
            case ToolAssistanceImage.TouchCursorTap:
                svgImage = React.createElement(SvgTouchCursorPoint, null);
                break;
            case ToolAssistanceImage.TouchCursorDrag:
                svgImage = React.createElement(SvgTouchCursorPan, null);
                className = mediumSize
                    ? "uifw-toolassistance-svg-medium-wide"
                    : "uifw-toolassistance-svg-wide";
                break;
        }
        image = (React.createElement("div", { className: className }, svgImage && React.createElement(Icon, { iconSpec: svgImage })));
    }
    return image;
}
function InstructionKeyboardImage({ 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, index) => {
                return (React.createElement(KeyNode, { key: index, keyboardKey: key, className: "uifw-toolassistance-key-small" }));
            })),
            React.createElement("br", null),
            React.createElement("span", { className: "row2" }, keyboardInfo.bottomKeys.map((key, index) => {
                return (React.createElement(KeyNode, { key: index, keyboardKey: key, className: "uifw-toolassistance-key-small" }));
            }))));
    }
    else if (keyboardInfo.keys.length === 2) {
        image = (
        // eslint-disable-next-line @typescript-eslint/no-deprecated
        React.createElement(FillCentered, null, keyboardInfo.keys.map((key, index) => {
            let className = "uifw-toolassistance-key-medium";
            if (key.length > 1)
                className = "uifw-toolassistance-key-modifier";
            return (React.createElement(KeyNode, { key: index, keyboardKey: key, className: className }));
        })));
    }
    else if (keyboardInfo.keys[0]) {
        if (keyboardInfo.keys[0].length > 1)
            image = (React.createElement(KeyNode, { keyboardKey: keyboardInfo.keys[0], className: "uifw-toolassistance-key-large" }));
        else
            image = React.createElement(KeyNode, { keyboardKey: keyboardInfo.keys[0] });
    }
    else {
        Logger.logError(UiFramework.loggerCategory("ToolAssistanceField"), `ToolAssistanceImage.Keyboard specified but ToolAssistanceKeyboardInfo not valid`);
    }
    return image;
}
function KeyNode({ keyboardKey, className, }) {
    return (React.createElement("div", { className: classnames("uifw-toolassistance-key", className) },
        React.createElement(FillCentered, null, keyboardKey)));
}
//# sourceMappingURL=ToolAssistanceField.js.map