/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/* eslint-disable deprecation/deprecation */
/** @packageDocumentation
 * @module Item
 */
import "./KeyinBrowser.scss";
// cSpell:ignore Modeless keyins keyinbrowser testid
import * as React from "react";
import { IModelApp, NotifyMessageDetails, OutputMessagePriority, OutputMessageType } from "@itwin/core-frontend";
import { AutoSuggest, InputLabel } from "@itwin/core-react";
import { Button, LabeledInput } from "@itwin/itwinui-react";
import { UiFramework } from "../UiFramework";
import { SpecialKey } from "@itwin/appui-abstract";
/**
 * Component used to allow users to select, provide arguments, and execute a key-in.
 * @beta @deprecated in 3.0. Key-in browser replaced by [KeyinPalettePopup]($appui-react).
 */
export class KeyinBrowser extends React.PureComponent {
    /** @internal */
    constructor(props) {
        super(props);
        this._toolIdLabel = UiFramework.translate("keyinbrowser.keyin");
        this._argsLabel = UiFramework.translate("keyinbrowser.args");
        this._argsTip = UiFramework.translate("keyinbrowser.argsTip");
        this._executeLabel = UiFramework.translate("keyinbrowser.execute");
        this._suggestPlaceholder = UiFramework.translate("keyinbrowser.placeholder");
        this._toolIdKey = "keyinbrowser:keyin";
        this._isMounted = false;
        this._onClick = async () => {
            return this._execute();
        };
        this._outputMessage = (msg) => {
            const details = new NotifyMessageDetails(OutputMessagePriority.Error, msg, undefined, OutputMessageType.Alert);
            IModelApp.notifications.outputMessage(details);
        };
        // istanbul ignore next
        this._onKeyinSelected = (selected) => {
            const currentToolId = selected.value;
            const currentArgs = this.getToolArgs(currentToolId);
            // istanbul ignore else
            if (this._isMounted)
                this.setState({ currentToolId, currentArgs });
        };
        this._onArgumentsChange = (event) => {
            // istanbul ignore else
            if (this._isMounted)
                this.setState({ currentArgs: event.target.value });
        };
        this._onKeyDown = async (event) => {
            if (SpecialKey.Enter === event.key) {
                event.stopPropagation();
                return this._execute();
            }
            // istanbul ignore else
            if (SpecialKey.Escape === event.key) {
                // istanbul ignore else
                if (this.props.onCancel)
                    this.props.onCancel();
                return;
            }
        };
        this._onInputFocus = (event) => {
            // istanbul ignore else
            if (event.target) {
                event.target.select();
            }
        };
        this._onAutoSuggestEnter = (event) => {
            event.stopPropagation();
            const inputValue = event.target.value;
            // istanbul ignore else
            if (this._processInputValue(inputValue)) {
                setTimeout(async () => {
                    await this._execute();
                });
            }
        };
        this._onAutoSuggestTab = (event) => {
            event.stopPropagation();
            const inputValue = event.target.value;
            this._processInputValue(inputValue);
        };
        this._onAutoSuggestEscape = (event) => {
            event.stopPropagation();
            // istanbul ignore else
            if (this.props.onCancel)
                this.props.onCancel();
        };
        /** Calculate suggestions for any given input value. */
        this._getSuggestions = async (value) => {
            const inputValue = value.trim().toLowerCase();
            const inputLength = inputValue.length;
            return Promise.resolve(inputLength === 0 ?
                /* istanbul ignore next */ [] :
                this.state.keyins.filter((data) => {
                    return data.label.toLowerCase().includes(inputValue) || data.englishKeyin.toLowerCase().includes(inputValue);
                }));
        };
        const currentToolId = this.getSavedToolId();
        const currentArgs = this.getToolArgs(currentToolId);
        this.state = {
            keyins: [],
            currentToolId,
            currentArgs,
        };
    }
    /** @internal */
    componentDidMount() {
        this._isMounted = true;
        let keyins = this.getToolKeyinMap();
        this.setState({ keyins });
        setTimeout(() => {
            keyins = keyins.sort((a, b) => a.label.localeCompare(b.label));
            // istanbul ignore else
            if (this._isMounted)
                this.setState({ keyins });
        });
    }
    /** @internal */
    componentWillUnmount() {
        this._isMounted = false;
    }
    getArgsKey(toolId) {
        if (toolId && toolId.length > 0)
            return `keyinbrowser:${toolId}`;
        return undefined;
    }
    getSavedToolId() {
        const toolId = window.localStorage.getItem(this._toolIdKey);
        return toolId ? toolId : undefined;
    }
    getToolArgs(toolId) {
        const argsKey = this.getArgsKey(toolId);
        if (argsKey && argsKey.length > 0) {
            const args = window.localStorage.getItem(argsKey);
            // istanbul ignore if
            if (args && /* istanbul ignore next */ args.length > 0 && /* istanbul ignore next */ args[0] === "[") {
                return JSON.parse(args).join("|");
            }
        }
        return "";
    }
    getToolKeyinMap() {
        const keyins = [];
        IModelApp.tools.getToolList()
            .forEach((tool) => keyins.push({ value: tool.toolId, label: tool.keyin, englishKeyin: tool.englishKeyin }));
        return keyins;
    }
    getArgsArray() {
        // istanbul ignore else
        if (this.state.currentArgs.length > 0) {
            return this.state.currentArgs.split("|");
        }
        return [];
    }
    async _execute() {
        let toolId;
        let args = [];
        let runStatus = false;
        // istanbul ignore else
        if (this.state.currentToolId && this.state.currentToolId.length > 0) {
            const foundTool = IModelApp.tools.find(this.state.currentToolId);
            // istanbul ignore else
            if (foundTool) {
                toolId = foundTool.toolId;
                args = this.getArgsArray();
                const maxArgs = foundTool.maxArgs;
                if (args.length < foundTool.minArgs || (undefined !== maxArgs && args.length > maxArgs)) {
                    this._outputMessage(UiFramework.translate("keyinbrowser.incorrectArgs"));
                    return;
                }
                let key = "keyinbrowser:keyin";
                window.localStorage.setItem(key, toolId);
                // istanbul ignore if
                if (args && args.length > 0) {
                    key = `keyinbrowser:${toolId}`;
                    const objectAsString = JSON.stringify(args);
                    window.localStorage.setItem(key, objectAsString);
                }
                const tool = new foundTool();
                runStatus = false;
                try {
                    runStatus = args.length > 0 ? /* istanbul ignore next */ await tool.parseAndRun(...args) : await tool.run();
                    !runStatus && this._outputMessage(UiFramework.translate("keyinbrowser.failedToRun"));
                }
                catch (e) {
                    // istanbul ignore next
                    this._outputMessage(`${UiFramework.translate("keyinbrowser.exceptionOccurred")}: ${e}`);
                }
            }
        }
        // istanbul ignore else
        if (this.props.onExecute)
            this.props.onExecute({ toolId, args, runStatus });
    }
    _processInputValue(inputValue) {
        let currentKeyin = "";
        let foundTool;
        if (this.state.currentToolId && this.state.currentToolId.length > 0) {
            foundTool = IModelApp.tools.find(this.state.currentToolId);
            // istanbul ignore else
            if (foundTool)
                currentKeyin = foundTool.keyin;
        }
        // istanbul ignore next
        if (inputValue !== currentKeyin) {
            const inputValueLower = inputValue.trim().toLowerCase();
            foundTool = IModelApp.tools.getToolList()
                .find((tool) => tool.keyin.toLowerCase() === inputValueLower || tool.englishKeyin.toLowerCase() === inputValueLower);
            if (!foundTool) {
                this._outputMessage(UiFramework.translate("keyinbrowser.couldNotFindTool"));
                return false;
            }
            else {
                const currentToolId = foundTool.toolId;
                // istanbul ignore else
                if (this._isMounted)
                    this.setState({ currentToolId });
            }
        }
        return true;
    }
    /** @internal */
    render() {
        return (React.createElement("div", { className: "uif-keyinbrowser-div" },
            React.createElement(InputLabel, { label: this._toolIdLabel },
                React.createElement(AutoSuggest, { value: this.state.currentToolId, style: { width: "250px" }, placeholder: this._suggestPlaceholder, options: this.state.keyins, onSuggestionSelected: this._onKeyinSelected, onPressEnter: this._onAutoSuggestEnter, onPressTab: this._onAutoSuggestTab, onPressEscape: this._onAutoSuggestEscape, onInputFocus: this._onInputFocus, getSuggestions: this._getSuggestions, "data-testid": "uif-keyin-autosuggest" })),
            React.createElement(LabeledInput, { label: this._argsLabel, title: this._argsTip, value: this.state.currentArgs, "data-testid": "uif-keyin-arguments", id: "uif-keyin-arguments", onKeyDown: this._onKeyDown, onChange: this._onArgumentsChange, onFocus: this._onInputFocus, size: "small" }),
            React.createElement(Button, { styleType: "cta", "data-testid": "uif-keyin-browser-execute", onClick: this._onClick }, this._executeLabel)));
    }
}
//# sourceMappingURL=KeyinBrowser.js.map