"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 AccuDraw
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.AccuDrawInputField = void 0;
require("./AccuDrawInputField.scss");
const classnames_1 = require("classnames");
const React = require("react");
const core_react_1 = require("@itwin/core-react");
const appui_abstract_1 = require("@itwin/appui-abstract");
const itwinui_react_1 = require("@itwin/itwinui-react");
const FrameworkAccuDraw_1 = require("./FrameworkAccuDraw");
const UiFramework_1 = require("../UiFramework");
const itwinui_icons_react_1 = require("@itwin/itwinui-icons-react");
function isLetter(char) {
    return char.length === 1 && char.toLowerCase() !== char.toUpperCase();
}
const ForwardRefAccuDrawInput = React.forwardRef(function ForwardRefAccuDrawInputField(props, ref) {
    const { className, style, id, label, iconSpec, labelClassName, labelStyle, labelCentered, field, isLocked, onValueChanged, valueChangedDelay, onEnterPressed, onEscPressed, ...inputProps } = props;
    const [stringValue, setStringValue] = React.useState("");
    const timeoutId = React.useRef(0);
    const [needValueChanged, setNeedValueChanged] = React.useState(false);
    const [needSelection, setNeedSelection] = React.useState(false);
    const [isFocusField, setIsFocusField] = React.useState(false);
    const inputElementRef = React.useRef(null);
    const refs = (0, core_react_1.useRefs)(inputElementRef, ref); // combine ref needed for target with the forwardRef needed by the Parent when parent is a Type Editor.
    React.useEffect(() => {
        const formattedValue = FrameworkAccuDraw_1.FrameworkAccuDraw.getFieldDisplayValue(field);
        setStringValue(formattedValue);
    }, [field]);
    const handleChange = React.useCallback((event) => {
        const value = event.currentTarget.value;
        // istanbul ignore next
        if (value === undefined)
            return;
        // istanbul ignore else
        if (stringValue !== value) {
            setStringValue(value);
            setNeedValueChanged(true);
        }
    }, [stringValue]);
    const unsetTimeout = () => {
        // istanbul ignore else
        if (timeoutId) {
            window.clearTimeout(timeoutId.current);
            timeoutId.current = 0;
        }
    };
    React.useEffect(() => {
        // After setStringValue & re-render
        // istanbul ignore else
        if (needValueChanged) {
            if (valueChangedDelay) {
                unsetTimeout();
                timeoutId.current = window.setTimeout(() => {
                    onValueChanged(stringValue);
                }, valueChangedDelay);
            }
            else {
                onValueChanged(stringValue);
            }
            setNeedValueChanged(false);
        }
    }, [onValueChanged, valueChangedDelay, stringValue, needValueChanged]);
    React.useEffect(() => {
        // On unmount
        return () => unsetTimeout();
    }, []);
    const handleKeyDown = React.useCallback((e) => {
        switch (e.key) {
            case appui_abstract_1.SpecialKey.Escape:
                onEscPressed && onEscPressed();
                return;
            case appui_abstract_1.SpecialKey.Enter:
                onEnterPressed && onEnterPressed();
                return;
        }
        if (isLetter(e.key)) {
            e.preventDefault();
            UiFramework_1.UiFramework.keyboardShortcuts.processKey(e.key);
            return;
        }
    }, [onEscPressed, onEnterPressed]);
    React.useEffect(() => {
        const handleSetFieldValueToUi = (args) => {
            if (args.field === field && stringValue !== args.formattedValue) {
                setStringValue(args.formattedValue);
                // istanbul ignore else
                if (isFocusField)
                    setNeedSelection(true);
            }
        };
        return FrameworkAccuDraw_1.FrameworkAccuDraw.onAccuDrawSetFieldValueToUiEvent.addListener(handleSetFieldValueToUi);
    }, [field, isFocusField, stringValue]);
    React.useEffect(() => {
        if (needSelection) {
            // istanbul ignore else
            if (inputElementRef.current)
                inputElementRef.current.select();
            setNeedSelection(false);
        }
    }, [needSelection]);
    React.useEffect(() => {
        const handleSetFieldFocus = (args) => {
            setIsFocusField(args.field === field);
        };
        return FrameworkAccuDraw_1.FrameworkAccuDraw.onAccuDrawSetFieldFocusEvent.addListener(handleSetFieldFocus);
    }, [field]);
    const inputClassNames = (0, classnames_1.default)("uifw-accudraw-input-field", className);
    const labelClassNames = (0, classnames_1.default)("uifw-accudraw-input-label", labelCentered && "uifw-label-centered", labelClassName);
    return (React.createElement(React.Fragment, null,
        React.createElement("label", { htmlFor: id, className: labelClassNames, style: labelStyle },
            label,
            iconSpec && React.createElement(core_react_1.Icon, { iconSpec: iconSpec })),
        React.createElement(itwinui_react_1.Input, { ...inputProps, ref: refs, id: id, value: stringValue, className: inputClassNames, style: style, autoComplete: "off", onChange: handleChange, onKeyDown: handleKeyDown, size: "small" }),
        React.createElement("span", { className: "uifw-accudraw-lock" }, isLocked && React.createElement(core_react_1.Icon, { iconSpec: React.createElement(itwinui_icons_react_1.SvgLock, null) }))));
});
/** Input field for AccuDraw Ui
 * @beta
 */
exports.AccuDrawInputField = ForwardRefAccuDrawInput;
//# sourceMappingURL=AccuDrawInputField.js.map