import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
// (C) 2020-2026 GoodData Corporation
import { PureComponent, } from "react";
import cx from "classnames";
import { v4 as uuid } from "uuid";
import { UiIconButton } from "../@ui/UiIconButton/UiIconButton.js";
import { ENUM_KEY_CODE } from "../typings/utilities.js";
import { runAutofocus } from "./focus.js";
/**
 * @internal
 */
export class InputPure extends PureComponent {
    inputNodeRef = null;
    autofocusDispatcher = () => { };
    a11yIdBase = uuid();
    static defaultProps = {
        autofocus: false,
        className: "",
        clearOnEsc: false,
        disabled: false,
        hasError: false,
        hasWarning: false,
        isSearch: false,
        isSmall: false,
        maxlength: 255,
        onChange: (..._args) => { },
        onEscKeyPress: (..._args) => { },
        onEnterKeyPress: (..._args) => { },
        onBlur: (..._args) => { },
        onFocus: (..._args) => { },
        placeholder: "",
        prefix: "",
        readonly: false,
        suffix: "",
        label: "",
        labelPositionTop: false,
        value: "",
    };
    componentDidMount() {
        const { autofocus } = this.props;
        this.autofocusDispatcher = runAutofocus(this.inputNodeRef, autofocus ?? false);
    }
    componentWillUnmount() {
        this.autofocusDispatcher();
    }
    componentDidUpdate(prevProps) {
        if (prevProps.autofocus !== this.props.autofocus) {
            this.autofocusDispatcher();
            this.autofocusDispatcher = runAutofocus(this.inputNodeRef, this.props.autofocus ?? false);
        }
    }
    onChange = (e) => {
        this.props.onChange?.(e.target.value, e);
    };
    onKeyPress = (e) => {
        switch (e.keyCode) {
            case ENUM_KEY_CODE.KEY_CODE_ESCAPE:
                if (this.props.clearOnEsc) {
                    e.stopPropagation();
                    this.onClear();
                }
                this.props.onEscKeyPress?.(e);
                break;
            case ENUM_KEY_CODE.KEY_CODE_ENTER:
                this.props.onEnterKeyPress?.();
                break;
            default:
                break;
        }
    };
    onClear = (e) => {
        this.props.onChange?.("", e);
        this.autofocusDispatcher = runAutofocus(this.inputNodeRef, true);
    };
    getLabelClassNames(className) {
        return cx({
            "gd-input": true,
            "gd-input-small": this.props.isSmall,
            "gd-input-search": this.props.isSearch,
            "gd-input-with-prefix": !!this.props.prefix,
            "gd-input-with-suffix": !!this.props.suffix,
            "gd-input-with-icon-button": !!this.props.iconButton,
            "gd-input-with-label": !!this.props.label,
            "gd-input-label-top": this.props.labelPositionTop,
            "has-error": this.props.hasError,
            "has-warning": this.props.hasWarning,
            "is-disabled": this.props.disabled,
        }, className);
    }
    getInputClassNames() {
        return cx({
            "gd-input-field": true,
            "gd-input-field-small": this.props.isSmall,
        });
    }
    getA11yIdBase() {
        return this.props.id ?? this.a11yIdBase;
    }
    getPrefixA11yId() {
        return `${this.getA11yIdBase()}-a11y-prefix`;
    }
    getSuffixA11yId() {
        return `${this.getA11yIdBase()}-a11y-suffix`;
    }
    renderPrefix(prefix, ariaLabel) {
        return prefix ? (_jsxs(_Fragment, { children: [
                _jsx("span", { className: "gd-input-prefix", "aria-hidden": "true", children: prefix }), ariaLabel ? (_jsx("span", { className: "sr-only", id: this.getPrefixA11yId(), children: ariaLabel })) : null] })) : (false);
    }
    renderSuffix(suffix, ariaLabel) {
        return suffix ? (_jsxs(_Fragment, { children: [
                _jsx("span", { className: "gd-input-suffix", "aria-hidden": "true", children: suffix }), ariaLabel ? (_jsx("span", { className: "sr-only", id: this.getSuffixA11yId(), children: ariaLabel })) : null] })) : (false);
    }
    renderLabel(label, htmlFor) {
        return label ? (_jsx("label", { htmlFor: htmlFor, className: "gd-input-label", children: label })) : (false);
    }
    renderSearch(isSearch) {
        return isSearch ? _jsx("span", { className: "gd-input-icon gd-icon-search" }) : false;
    }
    renderClearIcon(clearOnEsc) {
        return clearOnEsc && this.props.value.length > 0 ? (_jsx("button", { type: "button", className: "gd-input-icon-clear gd-icon-clear s-input-clear", "aria-label": "Input clear", onClick: (e) => {
                // react events use delegation and don't bubble, click on clear needs to be kept local
                // to avoid handling by overlay close handler and others
                e.stopPropagation();
                this.onClear();
            } })) : (false);
    }
    renderIconButton(iconButton, iconButtonLabel, onIconButtonClick) {
        return iconButton ? (_jsx("span", { className: "gd-input-icon-button", children: _jsx(UiIconButton, { icon: iconButton, label: iconButtonLabel, size: "medium", variant: "tertiary", onClick: onIconButtonClick, accessibilityConfig: {
                    ariaLabel: iconButtonLabel,
                } }) })) : (false);
    }
    getAriaDescribedBy() {
        const { prefix, suffix, accessibilityConfig } = this.props;
        const describedBy = [
            prefix && accessibilityConfig?.prefixAriaLabel ? this.getPrefixA11yId() : undefined,
            suffix && accessibilityConfig?.suffixAriaLabel ? this.getSuffixA11yId() : undefined,
            accessibilityConfig?.ariaDescribedBy,
        ]
            .filter(Boolean)
            .join(" ")
            .trim();
        return describedBy.length ? describedBy : undefined;
    }
    renderInput() {
        const { clearOnEsc, disabled, isSearch, placeholder, prefix, readonly, suffix, maxlength, value, onBlur, onFocus, name, type, required, accessibilityConfig, autocomplete, iconButton, iconButtonLabel, onIconButtonClick, dataTestId, } = this.props;
        return (_jsxs("div", { className: "gd-input-wrapper", children: [
                _jsx("input", { ref: (ref) => {
                        this.inputNodeRef = ref;
                    }, type: type ?? "text", id: this.getA11yIdBase(), name: name, required: required, className: this.getInputClassNames(), disabled: disabled, maxLength: maxlength, onChange: this.onChange, onBlur: onBlur, onFocus: onFocus, onKeyDown: this.props.onKeyDown ?? this.onKeyPress, placeholder: placeholder, readOnly: readonly, value: value, role: accessibilityConfig?.role, "aria-label": accessibilityConfig?.ariaLabel ?? undefined, "aria-describedby": this.getAriaDescribedBy(), "aria-labelledby": accessibilityConfig?.ariaLabelledBy, "aria-expanded": accessibilityConfig?.ariaExpanded, "aria-controls": accessibilityConfig?.ariaControls, "aria-activedescendant": accessibilityConfig?.ariaActiveDescendant, "aria-readonly": readonly || undefined, "aria-autocomplete": accessibilityConfig?.ariaAutocomplete, "aria-invalid": accessibilityConfig?.ariaInvalid, autoComplete: isSearch ? "off" : autocomplete, "data-testid": dataTestId }), this.renderSearch(isSearch ?? false), this.renderClearIcon(clearOnEsc ?? false), this.renderPrefix(prefix ?? "", accessibilityConfig?.prefixAriaLabel), this.renderSuffix(suffix ?? "", accessibilityConfig?.suffixAriaLabel), this.renderIconButton(iconButton, iconButtonLabel ?? "", onIconButtonClick)] }));
    }
    render() {
        const { className, label } = this.props;
        if (label) {
            return (_jsxs("div", { className: this.getLabelClassNames(className ?? ""), children: [this.renderLabel(label, this.getA11yIdBase()), this.renderInput()] }));
        }
        return _jsx("div", { className: this.getLabelClassNames(className ?? ""), children: this.renderInput() });
    }
    focus(options) {
        if (this.inputNodeRef) {
            this.inputNodeRef.focus(options);
        }
    }
}
