/**
 * amis-ui v6.11.0-beta.7
 * Copyright 2018-2025 fex
 */

import { __assign, __awaiter, __generator, __values } from 'tslib';
import { themeable, localeable } from 'amis-core';
import React__default from 'react';
import { useFieldArray, useFormContext, useFormState } from 'react-hook-form';
import useSubForm from '../hooks/use-sub-form.js';
import Button from './Button.js';
import ThemedFormField from './FormField.js';
import { Icon } from './icons.js';

/**
 * 纯组件版本的 combo 实现
 *
 * 只能用在 <Form> 里面。
 *
 * 示例:
 *
 * <Form
 *   defaultValues={{a: 1, b: 2, arr: [{a: 1, b: 2}]}}
 *   onSubmit={values => console.log(values)}
 * >
 *   {({control, getValues, setValue, handleSubmit}) => (
 *     <>
 *       <Combo
 *         name="arr"
 *         control={control}
 *         label="Combo"
 *         mode="horizontal"
 *         itemRender={({
 *           control,
 *           getValues,
 *           setValue,
 *           handleSubmit
 *         }) => (
 *           <>
 *             <Controller
 *               name="a"
 *               label="A"
 *               mode="horizontal"
 *               horizontal={{justify: true}}
 *               control={control}
 *               rules={{maxLength: 20}}
 *               render={({field, fieldState}) => (
 *                 <InputBox
 *                   {...field}
 *                   hasError={fieldState.error}
 *                   disabled={false}
 *                 />
 *               )}
 *             />
 *
 *             <Controller
 *               name="b"
 *               control={control}
 *               rules={{maxLength: 20}}
 *               render={({field, fieldState}) => (
 *                 <InputBox
 *                   {...field}
 *                   hasError={fieldState.error}
 *                   disabled={false}
 *                 />
 *               )}
 *             />
 *           </>
 *         )}
 *       />
 *     </>
 *   )}
 * </Form>
 */
function Combo(_a) {
    var _this = this;
    var _b, _c;
    var control = _a.control, name = _a.name, wrap = _a.wrap, mode = _a.mode, label = _a.label, labelAlign = _a.labelAlign, labelClassName = _a.labelClassName, description = _a.description, fieldClassName = _a.fieldClassName, className = _a.className, style = _a.style, multiLine = _a.multiLine, itemsWrapperClassName = _a.itemsWrapperClassName, itemClassName = _a.itemClassName, addButtonClassName = _a.addButtonClassName, addButtonLevel = _a.addButtonLevel, addButtonSize = _a.addButtonSize, itemRender = _a.itemRender, __ = _a.translate, cx = _a.classnames, addable = _a.addable, scaffold = _a.scaffold, addButtonText = _a.addButtonText, removable = _a.removable, rules = _a.rules, isRequired = _a.isRequired, minLength = _a.minLength, maxLength = _a.maxLength;
    var subForms = React__default.useRef({});
    var subFormRef = React__default.useCallback(function (subform, index) {
        if (subform) {
            subForms.current[index] = subform;
        }
        else {
            delete subForms.current[index];
        }
    }, [subForms]);
    var finalRules = __assign({}, rules);
    if (isRequired) {
        finalRules.required = true;
    }
    if (minLength) {
        finalRules.minLength = minLength;
    }
    if (maxLength) {
        finalRules.maxLength = maxLength;
    }
    finalRules.validate = React__default.useCallback(function (items) { return __awaiter(_this, void 0, void 0, function () {
        var map, result, _a, _b, key, valid, e_1_1;
        var e_1, _c;
        return __generator(this, function (_d) {
            switch (_d.label) {
                case 0:
                    map = subForms.current;
                    if (!(typeof (rules === null || rules === void 0 ? void 0 : rules.validate) === 'function')) return [3 /*break*/, 2];
                    return [4 /*yield*/, rules.validate(items)];
                case 1:
                    result = _d.sent();
                    if (result) {
                        return [2 /*return*/, result];
                    }
                    _d.label = 2;
                case 2:
                    _d.trys.push([2, 7, 8, 9]);
                    _a = __values(Object.keys(map)), _b = _a.next();
                    _d.label = 3;
                case 3:
                    if (!!_b.done) return [3 /*break*/, 6];
                    key = _b.value;
                    return [4 /*yield*/, (function (methods) {
                            return new Promise(function (resolve) {
                                methods.handleSubmit(function () { return resolve(true); }, function () { return resolve(false); })();
                            });
                        })(map[key])];
                case 4:
                    valid = _d.sent();
                    if (!valid) {
                        return [2 /*return*/, __('validateFailed')];
                    }
                    _d.label = 5;
                case 5:
                    _b = _a.next();
                    return [3 /*break*/, 3];
                case 6: return [3 /*break*/, 9];
                case 7:
                    e_1_1 = _d.sent();
                    e_1 = { error: e_1_1 };
                    return [3 /*break*/, 9];
                case 8:
                    try {
                        if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
                    }
                    finally { if (e_1) throw e_1.error; }
                    return [7 /*endfinally*/];
                case 9: return [2 /*return*/];
            }
        });
    }); }, [subForms]);
    var _d = useFieldArray({
        control: control,
        name: name,
        shouldUnregister: true,
        rules: finalRules
    }), fields = _d.fields, append = _d.append; _d.update; var remove = _d.remove;
    var _e = useFormContext(); _e.trigger; var setValue = _e.setValue;
    // useFieldArray 的 update 会更新行 id，导致重新渲染
    // 正在编辑中的元素失去焦点，所以自己写一个
    var lightUpdate = React__default.useCallback(function (index, value) {
        // const arr = control._getFieldArray(name);
        // arr[index] = {...value};
        // control._updateFieldArray(name, arr);
        // trigger(name);
        // control._subjects.watch.next({});
        setValue("".concat(name, ".").concat(index), value);
    }, [control]);
    function renderBody() {
        var _a;
        return (React__default.createElement("div", { className: cx("Combo Combo--multi", className, multiLine ? "Combo--ver" : "Combo--hor") },
            React__default.createElement("div", { className: cx("Combo-items", itemsWrapperClassName) }, fields.map(function (field, index) { return (React__default.createElement("div", { key: field.id, className: cx("Combo-item", itemClassName) },
                React__default.createElement(ComboItem, { control: control, update: lightUpdate, index: index, value: field, itemRender: itemRender, translate: __, classnames: cx, formRef: subFormRef }),
                React__default.createElement("a", { onClick: function () { return remove(index); }, key: "delete", className: cx("Combo-delBtn ".concat(removable === false ||
                        (minLength && fields.length <= minLength)
                        ? 'is-disabled'
                        : '')), "data-tooltip": __('delete'), "data-position": "bottom" },
                    React__default.createElement(Icon, { icon: "status-close", className: "icon" })))); })),
            addable !== false && (!maxLength || fields.length < maxLength) ? (React__default.createElement("div", { className: cx("Combo-toolbar") },
                React__default.createElement(Button, { className: cx("Combo-addBtn", addButtonClassName), level: addButtonLevel !== null && addButtonLevel !== void 0 ? addButtonLevel : 'primary', onClick: function () { return append(__assign({}, scaffold)); }, size: (_a = addButtonSize) !== null && _a !== void 0 ? _a : 'sm' },
                    React__default.createElement(Icon, { icon: "plus", className: "icon" }),
                    React__default.createElement("span", null, __(addButtonText || 'add'))))) : null));
    }
    var errors = useFormState({
        control: control
    }).errors;
    return wrap === false ? (renderBody()) : (React__default.createElement(ThemedFormField, { className: fieldClassName, style: style, label: label, labelAlign: labelAlign, labelClassName: labelClassName, description: description, mode: mode, isRequired: isRequired, hasError: !!((_b = errors[name]) === null || _b === void 0 ? void 0 : _b.message), errors: (_c = errors[name]) === null || _c === void 0 ? void 0 : _c.message }, renderBody()));
}
function ComboItem(_a) {
    var value = _a.value, itemRender = _a.itemRender, index = _a.index, translate = _a.translate, update = _a.update, cx = _a.classnames, formRef = _a.formRef;
    var indexRef = React__default.useRef(index);
    React__default.useEffect(function () {
        indexRef.current = index;
    }, [index]);
    var methods = useSubForm(value, translate, function (data) {
        return update(indexRef.current, data);
    });
    React__default.useEffect(function () {
        formRef === null || formRef === void 0 ? void 0 : formRef(methods, index);
        return function () {
            formRef === null || formRef === void 0 ? void 0 : formRef(null, index);
        };
    }, [methods]);
    var child = itemRender(methods, index);
    if ((child === null || child === void 0 ? void 0 : child.type) === React__default.Fragment) {
        child = child.props.children;
    }
    if (Array.isArray(child)) {
        child = (React__default.createElement("div", { className: cx('Form-row') }, child.map(function (child, index) { return (React__default.createElement("div", { className: cx('Form-col', child === null || child === void 0 ? void 0 : child.props.columnClassName), key: child.key || index }, child)); })));
    }
    return React__default.createElement("div", { className: cx('Combo-itemInner') }, child);
}
var Combo$1 = themeable(localeable(Combo));

export { Combo, ComboItem, Combo$1 as default };
