import { IField, IReactConstant, IReactFieldProps } from '@wowpic/xform-types';
import { Form, Tooltip } from 'antd';
import React, { FunctionComponent, useCallback, useEffect, useState } from 'react';
import { COMPONENT_LIST } from './components';
import { optionsCtor } from './utils';

const findComponent = (name: string): IReactConstant =>
    COMPONENT_LIST.find((component: IReactConstant) => component.name === name);

const Field: FunctionComponent<IReactFieldProps> = ({ core, field }) => {
    const [state, setState] = useState<IField>(field);
    const { type, status, valid, validStatus, message } = state || {};
    let { props = {}, ui } = state || {};

    // 实际上 field 地址不会发生改变，即使从返回值里拿也没用，所以手动生成一个新对象来进行更新
    const setField = useCallback(() => setState({ ...field }), [field]);

    // 因为 field 地址不会改变，变的只是 state，所以以下事件监听只会触发一次
    useEffect(() => {
        field.on('FIELD_CHANGE', setField);
        field.on('VALUE_CHANGE', setField);
        field.on('VALID_CHANGE', setField);
        field.on('OPTIONS_CHANGE', setField);
        return () => {
            field.removeListener('FIELD_CHANGE', setField);
            field.removeListener('VALUE_CHANGE', setField);
            field.removeListener('VALID_CHANGE', setField);
            field.removeListener('OPTIONS_CHANGE', setField);
        };
    }, [field, setField]);

    const onChange = useCallback(
        (value: any) => {
            field.setValue(value);
            if (props.onChange) {
                props.onChange(value, field, core);
            }
        },
        [core, props, field]
    );

    const onBlur = useCallback(() => {
        field.blur();
    }, [field]);

    // 获取组件对象
    const Component = typeof type === 'string' ? core.getComponent(type) : type;
    // 获取内置组件对象及其配置
    const component = findComponent(type);
    // 优先从 state 中取 value 和 options，否则从 props 中取
    const value = state.value != null ? state.value : props.value;
    const options = optionsCtor(
        state.options && state.options.length ? state.options : props.options
    );
    // 处理隐藏和禁用状态
    if (status === 'hidden') {
        return null;
        // 将自定义组件的preview放开
    }
    if (status === 'preview') {
        const preview =
            component && component.preview && value != null
                ? component.preview(value, options)
                : value;
        const showPreview = preview != null ? String(preview) : '-';
        return <Form.Item {...ui}>{showPreview}</Form.Item>;
    }
    if (status === 'disabled') {
        props = { ...props, disabled: true };
    }
    // 展示错误信息
    if (!valid) {
        ui = {
            ...ui,
            hasFeedback: component && !component.hideIcon,
            validateStatus: validStatus,
            help: message
        };
    }

    if (!Component) {
        return null;
    }

    return (
        <Form.Item {...ui} {...(ui?.label ? { label: <Tooltip title={`${ui.label}(${field.key})`} placement="left">{ui.label}</Tooltip> } : null)}>
            <Component
                {...props}
                field={field}
                options={options}
                value={value}
                onChange={onChange}
                onBlur={onBlur} />
        </Form.Item>
    );
};

export default Field;