import { Button, Input } from 'antd';
import React, { useEffect, useRef, useState, useCallback, FunctionComponent, FormEvent } from 'react';
import { registerComponent, XComponent, XForm } from '../packages/react/src/index';
import { IReactComponentProps, IRuleTrigger, ISchema, IValidateResult } from '../packages/types/src/index';

class ClassComponent extends XComponent {
    constructor(props: IReactComponentProps) {
        super(props);

        this.state = {
            value: this.props.value
        };
    }

    validate(trigger: IRuleTrigger, value: any) {
        console.log(trigger, value);
    }

    reset() {
        this.setState({
            value: ''
        });
    }

    onInput(e: any) {
        const value = e.target.value;
        this.setState({
            value
        });
        this.props.onChange(value);
    }

    onBlur() {
        this.props.onBlur();
    }

    render() {
        const { value } = this.state;

        return (
            <Input value={value} onInput={e => this.onInput(e)} onBlur={() => this.onBlur()}/>
        );
    }
}

const FunctionComponent: FunctionComponent<IReactComponentProps> = ({
    field,
    value: defaultValue,
    onChange,
    onBlur
}) => {
    const [value, setValue] = useState('');

    const onInput = useCallback(
        (e: FormEvent) => {
            const { value } = e.target as HTMLInputElement;
            // 需要手动触发onChange事件，并且把值传递过去
            onChange(value);
        },
        [onChange]
    );

    const onValidate = useCallback(async (trigger, value) => {
        let message = '';
        let valid = true;
        if (trigger === 'submit' && !Number.isInteger(Number(value))) {
            valid = false;
            message = '请输入数字';
        }
        const status = valid ? 'normal' : 'error';
        return { valid, message, status } as IValidateResult;
    },[]);

    // 需要手动触发onBlur事件，主要用于校验时候的blur场景
    const onBlur2 = useCallback(() => {
        onBlur();
    }, [onBlur]);

    // 触发验证，如果不需要 rules 校验，想要在组件内自行实现错误提示的，可以通过这个事件取到校验的时机
    // trigger 类型有 change、submit、blur
    // 最后需要设置下 valid、message、status

    // 触发重置，用于获取重置时机，更新组件值
    const onReset = useCallback(() => {
        setValue('');
    }, []);

    // 按照需求自由订阅事件
    useEffect(() => {
        field.onValidate(onValidate);
        // field.on('VALIDATE', onValidate);
        field.on('RESET', onReset);

        return () => {
            field.removeListener('RESET', onReset);
        };
    }, []);

    useEffect(() => {
        setValue(defaultValue);
    }, [defaultValue]);

    return <Input value={value} onInput={onInput} onBlur={onBlur2} />;
};

registerComponent('ClassComponent', ClassComponent);
registerComponent('FunctionComponent', FunctionComponent);

const schema: ISchema = [
    {
        key: 'classComponent',
        type: 'ClassComponent',
        ui: {
            label: '自定义Class组件'
        },
        value: '测试',
        rules: [
            {
                type: 'email',
                trigger: 'change',
                message: '必须为邮箱'
            }
        ]
    },
    {
        key: 'functionComponent',
        type: 'FunctionComponent',
        ui: {
            label: '自定义Function组件'
        },
        value: '测试'
    }
];

export default function() {
    const formRef = useRef(null);

    const onSubmit = () => {
        formRef.current.submit().then((data: any) => {
            console.log(data);
        });
    };

    const onReset = () => {
        formRef.current.reset();
    };

    const onEmpty = () => {
        formRef.current.empty();
    };

    return (
        <>
            <XForm
                ref={formRef}
                schema={schema}
                labelCol={{ span: 6 }}
                wrapperCol={{ span: 12 }}
            />
            <div style={{display: 'flex', justifyContent: 'center'}}>
                <Button type="primary" onClick={onSubmit}>提交</Button>
                <Button style={{ marginLeft: '10px' }} onClick={onReset}>重置</Button>
                <Button style={{ marginLeft: '10px' }} onClick={onEmpty}>清空</Button>
            </div>
        </>
    );
}