import * as React from 'react';
import {CSSProperties} from 'react';
import {BasicConfig, BasicContainer, BasicContainerPropsInterface} from '../../render/core/Container/types';
import {IsBoolean, IsDefined, IsJSON, IsString} from 'class-validator';
import componentLoader from '../../render/util/componentLoader';
import {Radio} from '@native-ads/antd';
import {RadioGroupProps} from '@native-ads/antd/lib/radio';
import {RadioProps} from '@native-ads/antd/es/radio';
import RadioButton from '@native-ads/antd/es/radio/radioButton';

const RadioGroup = Radio.Group;

export class RadioOptionItem {
    /**
     * 多组单选按钮的文字
     */
    label: string;

    /**
     * 多组单选按钮的值
     */
    value: string;

    /**
     * 禁用选项
     */
    disabled?: boolean;
}

export class RadioConfig extends BasicConfig {
    /**
     * Radil的数据模型Key
     */
    @IsDefined()
    name: string;

    /**
     * 初始的值
     */
    defaultValue?: string;

    /**
     * 模式
     */
    mode: 'radio' | 'button' | 'menu';

    /**
     * 是否禁用
     * @public
     * @default false
     */
    @IsBoolean()
    disabled: boolean;

    /**
     * unknown
     */
    @IsString()
    prefixCls?: string;

    /**
     * 单个选择框的文字
     * @public
     * @default ''
     */
    @IsString()
    text?: string;

    /**
     * 多组单选按钮.
     */
    options?: RadioOptionItem[];

    /**
     * CSS class
     */
    @IsString()
    className?: string;

    /**
     * RadioGroup中, 按钮的大小
     */
    size: 'large' | 'default' | 'small';

    /**
     * 内联CSS属性
     */
    @IsJSON()
    style?: CSSProperties;
}

export class RadioPropsInterface extends BasicContainerPropsInterface {
    info: RadioConfig;
}

export class AbstractRadio extends BasicContainer<RadioPropsInterface, {}> {
    constructor(props: RadioPropsInterface) {
        super(props);

        this.handleChange = this.handleChange.bind(this);
        this.handleRadioGroupChange = this.handleRadioGroupChange.bind(this);
    }

    componentWillMount() {
        const info = this.getPropsInfo(this.props.info);
        if (this.props.$setData && info.name && info.defaultValue) {
            const $setData = this.props.$setData;
            $setData(info.name, info.defaultValue);
        }
    }

    componentWillReceiveProps(nextProps: RadioPropsInterface) {
        let info = this.getPropsInfo(nextProps.info, nextProps, [], true);
        if (!info.name) {
            return;
        }
        let value = this.getValueFromDataStore(info.name, nextProps.$data);

        if (info.options && this.props.$deleteData) {
            let isValueInDisabledOption = info.options.some(op => {
                return op.disabled === true && op.value === value;
            });

            if (isValueInDisabledOption) {
                this.props.$deleteData(info.name);
            }
        }
    }

    private mapOptions(info: RadioConfig): RadioProps {
        return {
            prefixCls: info.prefixCls,
            className: info.className,
            style: info.style,
            disabled: info.disabled
        };
    }

    private mapRadioGroupOptions(info: RadioConfig): RadioGroupProps {
        return {
            size: info.size,
            name: info.name,
        };
    }

    private handleChange(event: React.ChangeEvent<HTMLInputElement>) {
        let checked = event.target.checked;
        if (this.props.$setData) {
            const info = this.getPropsInfo(this.props.info);
            this.props.$setData(info.name, checked);
        }

        this.commonEventHandler('onChange', {
            checked: checked
        });
    }

    private handleRadioGroupChange(event: React.ChangeEvent<HTMLInputElement>) {
        let value = event.target.value;
        if (this.props.$setData) {
            const info = this.getPropsInfo(this.props.info);
            this.props.$setData(info.name, value);
        }

        this.commonEventHandler('onRadioGroupChange', {
            value: value
        });
    }

    render() {
        let info = this.getPropsInfo(this.props.info, this.props, [], true);

        if (!info.name) {
            return <div>name property is required for Radio Element</div>;
        }

        if (!this.isUnderContainerEnv()) {
            return <div>Radio Element is out of RCRE control, please put it inside container component</div>;
        }

        let value = this.getValueFromDataStore(info.name);

        // Radio组
        if (info.options) {
            let radioGroupProps = this.mapRadioGroupOptions(info);
            let radioChildren = info.options.map(op => {
                switch (info.mode) {
                    case 'button':
                        return (
                            <RadioButton
                                value={op.value}
                                key={op.value}
                                disabled={op.disabled}
                            >
                                {op.label}
                            </RadioButton>
                        );
                    default:
                        return <Radio value={op.value} key={op.value} disabled={op.disabled}>{op.label}</Radio>;
                }
            });
            return React.createElement(RadioGroup, {
                value: value,
                onChange: this.handleRadioGroupChange,
                onMouseEnter: (event: React.MouseEvent<HTMLDivElement>) => {
                    this.commonEventHandler('onMouseEnter', {
                        event: event
                    });
                },
                onMouseLeave: (event: React.MouseEvent<HTMLDivElement>) => {
                    this.commonEventHandler('onMouseLeave', {
                        event: event
                    });
                },
                ...radioGroupProps
            }, radioChildren);
        } else {
            let radioProps = this.mapOptions(info);
            return React.createElement(Radio, {
                checked: value,
                onChange: this.handleChange,
                onMouseEnter: (event: React.MouseEvent<HTMLInputElement>) => {
                    this.commonEventHandler('onMouseEnter', {
                        event: event
                    });
                },
                onMouseLeave: (event: React.MouseEvent<HTMLInputElement>) => {
                    this.commonEventHandler('onMouseLeave', {
                        event: event
                    });
                },
                ...radioProps
            }, info.text);
        }
    }
}

componentLoader.addComponent('radio', AbstractRadio, RadioPropsInterface);
