/*---------------------------------------------------------------------------------------------
* 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
 */
import "./AccuDrawInputField.scss";
import classnames from "classnames";
import * as React from "react";
import { Icon, useRefs } from "@itwin/core-react";
import { isLetter, SpecialKey } from "@itwin/appui-abstract";
import { Input } from "@itwin/itwinui-react";
import { FrameworkAccuDraw } from "./FrameworkAccuDraw";
import { UiFramework } from "../UiFramework";
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 = 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.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 SpecialKey.Escape:
                onEscPressed && onEscPressed();
                return;
            case SpecialKey.Enter:
                onEnterPressed && onEnterPressed();
                return;
        }
        if (isLetter(e.key)) {
            e.preventDefault();
            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.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.onAccuDrawSetFieldFocusEvent.addListener(handleSetFieldFocus);
    }, [field]);
    const inputClassNames = classnames("uifw-accudraw-input-field", className);
    const labelClassNames = classnames("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(Icon, { iconSpec: iconSpec })),
        React.createElement(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(Icon, { iconSpec: "icon-lock" }))));
});
/** Input field for AccuDraw Ui
 * @beta
 */
export const AccuDrawInputField = ForwardRefAccuDrawInput;
//# sourceMappingURL=AccuDrawInputField.js.map