import { __assign } from "tslib";
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
import { useCallback, useEffect, useImperativeHandle, useRef } from 'react';
import { useField, Validators, ValidateOption, FieldUtils, isModelRef, } from './formulr';
import { defaultRenderError, useFormChild, isViewDrivenProps, ValidateOccasion, TouchWhen, } from './shared';
import { FormControl } from './Control';
import { FormNotice } from './Notice';
import { FormDescription } from './Description';
import id from '../utils/identity';
import { useComponentI18nData } from '../i18n/useComponentI18n';
export function defaultGetValidateOption() {
    return ValidateOption.Default;
}
function withDefaultOption(option) {
    return option !== null && option !== void 0 ? option : ValidateOption.Default;
}
export function useInitialValue(model, initialValue) {
    useEffect(function () {
        if (initialValue !== undefined) {
            model.initialize(initialValue);
        }
    }, [model, initialValue]);
}
function getValidators(_a, i18n) {
    var validators = _a.validators, required = _a.required;
    validators = validators !== null && validators !== void 0 ? validators : [];
    if (required &&
        !validators.some(function (it) {
            return it.$$id ===
                Validators.SYMBOL_REQUIRED;
        })) {
        validators = [
            Validators.required(typeof required === 'string' ? required : i18n.required),
        ].concat(validators);
    }
    return validators;
}
export function FormField(props) {
    var model;
    var i18n = useComponentI18nData('Form');
    if (isViewDrivenProps(props)) {
        var name_1 = props.name, defaultValue = props.defaultValue, destroyOnUnmount = props.destroyOnUnmount, normalizeBeforeSubmit = props.normalizeBeforeSubmit;
        model = useField(name_1, defaultValue, getValidators(props, i18n));
        model.destroyOnUnmount = Boolean(destroyOnUnmount);
        if (typeof normalizeBeforeSubmit === 'function') {
            model.normalizeBeforeSubmit = normalizeBeforeSubmit;
        }
    }
    else if (isModelRef(props.model)) {
        model = useField(props.model, props.defaultValue, getValidators(props, i18n));
    }
    else {
        model = useField(props.model);
    }
    useInitialValue(model, props.initialValue);
    useImperativeHandle(props.modelRef, function () { return model; }, [model]);
    var className = props.className, style = props.style, label = props.label, required = props.required, before = props.before, after = props.after, notice = props.notice, helpDesc = props.helpDesc, withoutError = props.withoutError, _a = props.renderError, renderError = _a === void 0 ? defaultRenderError : _a, children = props.children, _b = props.validateOccasion, validateOccasion = _b === void 0 ? ValidateOccasion.Default : _b, _c = props.getValidateOption, getValidateOption = _c === void 0 ? defaultGetValidateOption : _c, _d = props.normalize, normalize = _d === void 0 ? id : _d, normalizeBeforeBlur = props.normalizeBeforeBlur, _e = props.format, format = _e === void 0 ? id : _e, withoutLabel = props.withoutLabel, _f = props.touchWhen, touchWhen = _f === void 0 ? TouchWhen.Change : _f;
    var anchorRef = useRef(null);
    useFormChild(model, anchorRef);
    var normalizer = useCallback(function (value) {
        var prevValue = model.value;
        return normalize(value, prevValue);
    }, [model, normalize]);
    var setValue = useCallback(function (value) { return (model.value = value); }, [model]);
    var defaultOnChangeHandler = FieldUtils.useChangeHandler(model, withDefaultOption(getValidateOption('change')), props.onChange);
    var onChangeProps = props.onChange;
    var onChange = FieldUtils.useMulti(function () {
        if (touchWhen === TouchWhen.Change) {
            model.isTouched = true;
        }
    }, FieldUtils.usePipe(normalizer, ValidateOccasion.Change & validateOccasion
        ? defaultOnChangeHandler
        : function (value) {
            setValue(value);
            onChangeProps === null || onChangeProps === void 0 ? void 0 : onChangeProps(value);
        }), [
        model,
        touchWhen,
        normalizer,
        validateOccasion,
        defaultOnChangeHandler,
        onChangeProps,
    ]);
    var onBlurProps = props.onBlur;
    var onBlur = useCallback(function (e) {
        if (touchWhen === TouchWhen.Blur) {
            model.isTouched = true;
        }
        if (normalizeBeforeBlur) {
            model.value = normalizeBeforeBlur(model.value);
        }
        if (validateOccasion & ValidateOccasion.Blur) {
            model.validate(getValidateOption('blur'));
        }
        onBlurProps === null || onBlurProps === void 0 ? void 0 : onBlurProps(e);
    }, [
        getValidateOption,
        validateOccasion,
        normalizeBeforeBlur,
        touchWhen,
        model,
        onBlurProps,
    ]);
    var _g = FieldUtils.useCompositionHandler(model, {
        onCompositionStart: props.onCompositionStart,
        onCompositionEnd: props.onCompositionEnd,
    }), onCompositionStart = _g.onCompositionStart, onCompositionEnd = _g.onCompositionEnd;
    return (_jsxs(FormControl, __assign({ ref: anchorRef, className: className, style: style, label: label, required: !!required, invalid: !!model.error, withoutLabel: withoutLabel }, { children: [_jsxs("div", __assign({ className: "zent-form-control-content-inner", "data-zv": 'v10.0.12' }, { children: [before, children({
                        value: format(model.value),
                        onChange: onChange,
                        onCompositionStart: onCompositionStart,
                        onCompositionEnd: onCompositionEnd,
                        onBlur: onBlur,
                    }), after] }), void 0), withoutError ? null : renderError(model.error), !!notice && _jsx(FormNotice, { children: notice }, void 0), !!helpDesc && _jsx(FormDescription, { children: helpDesc }, void 0)] }), void 0));
}
