"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CnSender = void 0;
const React = __importStar(require("react"));
require("./cn-sender.scss");
const slot_text_area_1 = __importDefault(require("./compoments/slot-text-area"));
const context_1 = require("./context");
const use_proxy_imperative_handle_1 = __importDefault(require("./hooks/use-proxy-imperative-handle"));
const classnames_1 = __importDefault(require("classnames"));
const use_controlled_state_1 = __importDefault(require("./hooks/use-controlled-state"));
const send_button_1 = __importDefault(require("./compoments/send-button"));
const LoadingButton_1 = __importDefault(require("./compoments/LoadingButton"));
const record_button_1 = __importDefault(require("./compoments/record-button"));
const use_record_1 = __importStar(require("./hooks/use-record"));
const uuid_1 = require("uuid");
/** Used for actions render needed components */
const ForwardSender = React.forwardRef((props, ref) => {
    const { prefixCls: customizePrefixCls, styles = {}, classNames = {}, className, rootClassName, style, defaultValue, value, slotConfig, schema, readOnly, submitType = 'enter', onSubmit, loading, components, onCancel, onChange, suffix, onKeyUp, onKeyDown, disabled, allowRecord, onRecordMessage, prefix, footer, header, onPaste, onPasteFile, autoSize = { maxRows: 8 }, placeholder, onFocus, onBlur, skill, popupTriggerKey = '/', // 新增，默认值为 "/"
    customPopupProps, // 新增
    sendButtonProps, // 新增：发送按钮配置
    canEmptySubmit = false, // 新增：是否允许内容为空时提交
    ...restProps } = props;
    // const id = React.useId();
    const isSlotMode = Array.isArray(slotConfig) || (skill === null || skill === void 0 ? void 0 : skill.value);
    // ============================= MISC =============================
    // ============================= Refs =============================
    const containerRef = React.useRef(null);
    const inputRef = React.useRef(null);
    (0, use_proxy_imperative_handle_1.default)(ref, () => {
        var _a;
        return {
            nativeElement: containerRef.current,
            inputElement: (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.nativeElement,
            focus: (options) => { var _a; return (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus(options); },
            blur: () => { var _a; return (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.blur(); },
            insert: (...args) => { var _a, _b; return (_b = (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.insert) === null || _b === void 0 ? void 0 : _b.call(_a, ...args); },
            clear: () => { var _a; return (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.clear(); },
            getValue: () => {
                var _a, _b;
                return (_b = (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.getValue()) !== null && _b !== void 0 ? _b : {
                    value: '',
                    slotConfig: [],
                    formValue: {},
                    skill: undefined,
                };
            },
        };
    });
    const mergedCls = (0, classnames_1.default)(className, rootClassName, classNames.root, 'cn-sender-main', {
        [`cn-sender-disabled`]: disabled,
    });
    // ============================ Action List Class =============================
    const prefixCls = 'cn-sender';
    const actionListCls = `${prefixCls}-actions-list`;
    const actionBtnCls = `${prefixCls}-actions-btn`;
    // ============================ Value =============================
    const [innerValue, setInnerValue] = (0, use_controlled_state_1.default)(defaultValue || '', value);
    // ============================ Action context Data ============================
    const [submitDisabled, setSubmitDisabled] = React.useState(!innerValue);
    const triggerValueChange = (nextValue, event, slotConfigParam, skillParam) => {
        setInnerValue(nextValue);
        onChange === null || onChange === void 0 ? void 0 : onChange(nextValue, event, slotConfigParam !== null && slotConfigParam !== void 0 ? slotConfigParam : [], skillParam);
    };
    // ============================ Record ============================
    // 保存上一次录音的文本，用于计算增量
    const lastRecordTextRef = React.useRef('');
    // 录音功能（仅在 allowRecord 为 true 时启用）
    const recordInfo = (0, use_record_1.default)({
        onRecordMessage: (param) => {
            if (param.method === 'setInputText') {
                // 将录音转文字后的文本填充到输入框
                if (inputRef.current && param.text) {
                    const currentText = lastRecordTextRef.current;
                    // 计算增量文本（新增的部分）
                    const incrementalText = param.text.slice(currentText.length);
                    if (incrementalText) {
                        // 在输入框末尾插入增量文本
                        inputRef.current.insert([{ type: 'text', value: incrementalText }], 'end');
                    }
                    // 更新保存的文本
                    lastRecordTextRef.current = param.text;
                }
                // 调用外部回调
                onRecordMessage === null || onRecordMessage === void 0 ? void 0 : onRecordMessage(param);
            }
        },
    });
    // 处理录音按钮点击
    const handleRecordClick = React.useCallback(() => {
        if (recordInfo.recordStatus === use_record_1.RECORD_STATUS.RECORDING) {
            recordInfo.stopRecord();
            // 停止录音时，重置保存的文本
            lastRecordTextRef.current = '';
        }
        else {
            // 开始录音时，重置保存的文本
            lastRecordTextRef.current = '';
            recordInfo.startRecord({ fillMode: 'input', conversationId: (0, uuid_1.v4)() });
        }
    }, [recordInfo]);
    // ============================ Record ============================
    // const [recordPermission, triggerRecord, recordRecording] = useRecord((transcript) => {
    //   if (isSlotMode) {
    //     (inputRef.current as SlotTextAreaRef)?.insert?.([
    //       {
    //         type: 'text',
    //         value: transcript,
    //       },
    //     ]);
    //   } else {
    //     triggerValueChange(`${innerValue} ${transcript}`);
    //   }
    // }, allowRecord);
    // ============================ Events ============================
    const triggerSend = React.useCallback(() => {
        if ((inputRef === null || inputRef === void 0 ? void 0 : inputRef.current) && onSubmit && !loading && !submitDisabled) {
            const inputValue = inputRef.current.getValue();
            // 转换为 searchTokenList 并打印（如果存在 slotConfig 和 formValue）
            // if (inputValue?.slotConfig && inputValue?.formValue) {
            //   const tokens = convertToSearchTokenList(inputValue.slotConfig, inputValue.formValue);
            // }
            onSubmit(inputValue.value, inputValue.slotConfig, inputValue.skill, inputValue.formValue);
        }
    }, [onSubmit, loading, submitDisabled]);
    const triggerClear = () => {
        var _a, _b;
        triggerValueChange('');
        if (isSlotMode) {
            (_b = (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.clear) === null || _b === void 0 ? void 0 : _b.call(_a);
        }
    };
    // ============================ Action ============================
    const actionNode = (
    // <>操作按钮</>
    React.createElement("div", { className: `${actionListCls}-presets` },
        allowRecord && (React.createElement(record_button_1.default, { isRecording: recordInfo.recordStatus === use_record_1.RECORD_STATUS.RECORDING, onRecordClick: handleRecordClick, disabled: readOnly || disabled })),
        loading ? React.createElement(LoadingButton_1.default, null) : React.createElement(send_button_1.default, null)));
    // ============================ Suffix ============================
    let suffixNode = actionNode;
    if (typeof suffix === 'function') {
        suffixNode = suffix(actionNode, {
        // components: sharedRenderComponents,
        });
    }
    else if (suffix || suffix === false) {
        suffixNode = suffix;
    }
    // ============================ Prefix ============================
    const prefixNode = typeof prefix === 'function'
        ? prefix(actionNode, {
        // components: sharedRenderComponents
        })
        : prefix || null;
    // ============================ Header ============================
    const headerNode = typeof header === 'function'
        ? header(actionNode, {
        // components: sharedRenderComponents
        })
        : header || null;
    // ============================ Footer ============================
    const footerNode = typeof footer === 'function'
        ? footer(actionNode, {
        // components: sharedRenderComponents
        })
        : footer || null;
    // Custom actions context props
    const actionsContextProps = {
        prefixCls: actionBtnCls,
        onSend: triggerSend,
        // 如果允许空提交，则不禁用；否则当内容为空时禁用
        onSendDisabled: canEmptySubmit ? false : !innerValue,
        onClear: triggerClear,
        onClearDisabled: !innerValue,
        onCancel,
        onCancelDisabled: !loading,
        // onSpeech: () => triggerSpeech(false),
        // onSpeechDisabled: !speechPermission,
        // speechRecording,
        disabled,
        setSubmitDisabled,
        sendButtonProps, // 传递发送按钮配置
        canEmptySubmit, // 传递是否允许空提交
    };
    // ============================ Context ============================
    const contextValue = React.useMemo(() => ({
        value: innerValue,
        onChange: triggerValueChange,
        slotConfig,
        schema,
        onKeyUp,
        onKeyDown,
        onPaste,
        onPasteFile,
        disabled,
        readOnly,
        submitType,
        styles,
        classNames,
        autoSize,
        components,
        triggerSend,
        placeholder,
        onFocus,
        onBlur,
        skill,
        popupTriggerKey, // 新增
        customPopupProps, // 新增
        containerRef, // 弹层挂载容器，运行态下保证弹窗定位正确
        ...restProps,
    }), [
        innerValue,
        triggerValueChange,
        slotConfig,
        schema,
        onKeyUp,
        onKeyDown,
        onPaste,
        onPasteFile,
        disabled,
        readOnly,
        submitType,
        styles,
        classNames,
        autoSize,
        components,
        triggerSend,
        placeholder,
        onFocus,
        onBlur,
        skill,
        popupTriggerKey, // 新增
        customPopupProps, // 新增
        containerRef,
        restProps,
    ]);
    // ============================ Focus =============================
    const onContentMouseDown = () => {
        // If input focused but click on the container,
        // input will lose focus.
        // We call `preventDefault` to prevent this behavior
        // if (!isSlotMode && e.target !== containerRef.current?.querySelector(`.${inputCls}`)) {
        //   e.preventDefault();
        // }
        // if (e.target === containerRef.current?.querySelector(`.${inputCls}`)) {
        //   inputRef.current?.focus();
        // }
    };
    // ============================ Render ============================
    return (React.createElement("div", { 
        // key={id}
        ref: containerRef, className: mergedCls, style: {
            ...style,
            ...styles.root,
        } },
        React.createElement(context_1.SenderContext.Provider, { value: contextValue },
            React.createElement(context_1.ActionButtonContext.Provider, { value: actionsContextProps },
                headerNode && (React.createElement(context_1.SendHeaderContext.Provider, { value: { prefixCls } }, headerNode)),
                React.createElement("div", { className: (0, classnames_1.default)(`${prefixCls}-content`, classNames.content), style: styles.content, onMouseDown: onContentMouseDown },
                    prefixNode && React.createElement("div", null, prefixNode),
                    React.createElement(slot_text_area_1.default, { ref: inputRef }),
                    suffixNode && (React.createElement("div", { className: (0, classnames_1.default)(actionListCls, classNames.suffix), style: styles.suffix }, suffixNode))),
                footerNode && (React.createElement("div", { className: (0, classnames_1.default)(`cn-sender-footer`, classNames.footer) }, footerNode))))));
});
ForwardSender.displayName = 'ForwardSender';
exports.CnSender = ForwardSender;
exports.CnSender.displayName = 'CnSender';
