import * as React from 'react';
import {
    BasicConfig, BasicContainer, BasicContainerPropsInterface,
} from '../../render/core/Container/types';
import {Upload, Icon, message, Modal} from '@native-ads/antd';
import {UploadChangeParam, UploadProps} from '@native-ads/antd/lib/upload';
import componentLoader from '../../render/util/componentLoader';
import {SET_FORM_ITEM_PAYLOAD} from '../../render/core/Form/actions';
import * as _ from 'lodash';
import Button from '@native-ads/antd/lib/button/button';

export class UploadConfig extends BasicConfig {
    /**
     * Upload的数据模型Key
     */
    name: string;

    /**
     * 上传的地址
     */
    action: string;

    /**
     * 上传所需参数
     */
    data?: object;

    /**
     * 上传数据格式的限制
     */
    uploadType?: string[];

    /**
     * 上传大小的限制
     */
    uploadSize?: number;

    /**
     * 上传数量的限制
     */
    uploadNum?: number;

    /**
     * 上传图片的宽度限制
     */
    uploadWidth?: number;

    /**
     * 上传图片的高度限制
     */
    uploadHeight?: number;

    /**
     * 上传列表的内建样式
     */
    listType?: 'text' | 'picture' | 'picture-card' ;

    /**
     * 自定义类
     */
    className?: string;

    /**
     * 自定义样式
     */
    style?: React.CSSProperties;
}

export class UploadPropsInterface extends BasicContainerPropsInterface {
    info: UploadConfig;

    /**
     * 更新表单元素的属性
     */
    $setFormItem: (payload: Partial<SET_FORM_ITEM_PAYLOAD>) => void;
}

export class UploadStateInterface {
    previewVisible: boolean;
    previewImage: string;
}

export class AbstractUpload extends BasicContainer<UploadPropsInterface, UploadStateInterface> {
    constructor(props: UploadPropsInterface) {
        super(props);
        this.state = {
            previewVisible: false,
            previewImage: '',
        };
    }

    handleCancel = () => this.setState({previewVisible: false});

    handlePreview = (file: any) => {
        this.setState({
            previewImage: file.url || file.thumbUrl,
            previewVisible: true,
        });
    }

    getBase64 (img: any, callback: Function) {
        const reader = new FileReader();
        reader.addEventListener('load', () => callback(reader.result));
        reader.readAsDataURL(img);
    }

    validateType (content: UploadChangeParam, uploadType: string[]) {
        const file = content.file;
        let validateType: boolean;
        if (uploadType.length > 0) {
            validateType = uploadType.indexOf(file.type) > -1;
        } else {
            validateType = true;
        }
        return validateType;
    }

    validateSize (content: UploadChangeParam, uploadSize: number) {
        const file = content.file;
        let validateSize = file.size < uploadSize * 1024;
        return validateSize;
    }

    handleChange = (content: UploadChangeParam,
                    uploadType: string[],
                    uploadSize: number,
                    uploadWidth?: number,
                    uploadHeight?: number) => {
        const fileList = content.fileList;
        const file = content.file;
        const info = this.props.info;
        if (info.name && this.props.$setData) {
            this.props.$setData(info.name, fileList);
        }
        if (content.file.status === 'done') {
            // 上传后验证
            // 验证类型
            let validateTypeStatus = this.validateType(content, uploadType);

            if (!validateTypeStatus) {
                message.error('You can only upload ' + uploadType.join(',') + ' file!');
            }

            // 验证大小
            let validateSizeStatus = this.validateSize(content, uploadSize);

            if (!validateSizeStatus) {
                message.error('File must smaller than ' + uploadSize + 'KB!');
            }

            // 验证尺寸
            if (!_.isNil(uploadWidth) && !_.isNil(uploadHeight)) {
                // 如果需要验证尺寸
                // 获取图片文件
                this.getBase64(content.file.originFileObj, (thumbUrl: any) => {
                    let validateWidthHeightStatus: boolean = true;
                    let img = new Image();
                    img.onload = () => {
                        const width = img.width;
                        const height = img.height;

                        if (width > uploadWidth || height > uploadHeight) {
                            validateWidthHeightStatus = false;
                        }

                        if (!validateWidthHeightStatus) {
                            message.error('Image must smaller than ' + uploadWidth + 'x' + uploadHeight);
                        }
                        const valid = validateTypeStatus && validateSizeStatus && validateWidthHeightStatus;

                        fileList.map((item) => {
                            if (item.uid === file.uid) {
                                Object.assign(item, {
                                    'validateTypeStatus': validateTypeStatus,
                                    'validateSizeStatus': validateSizeStatus,
                                    'validateWidthHeightStatus': validateWidthHeightStatus,
                                });
                                if (file.response) {
                                    file.url = file.response.url;
                                }
                                if (!valid) {
                                    item.status = 'error';
                                }
                            }
                        });

                        // 验证之后更新状态
                        if (info.name && this.props.$setData) {
                            this.props.$setData(info.name, fileList);
                        }

                        // 表单验证
                        if (this.props.$setFormItem) {
                            this.props.$setFormItem({
                                formItemName: info.name,
                                valid: valid,
                                status: valid ? 'success' : 'error',
                            });
                        }
                    };
                    img.src = thumbUrl;
                });
            } else {
                // 如果不需要验证尺寸
                const valid = validateTypeStatus && validateSizeStatus;
                fileList.map((item) => {
                    if (item.uid === file.uid) {
                        Object.assign(item, {
                            'validateTypeStatus': validateTypeStatus,
                            'validateSizeStatus': validateSizeStatus,
                        });

                        if (file.response) {
                            file.url = file.response.url;
                        }

                        if (!valid) {
                            item.status = 'error';
                        }
                    }
                });

                // 验证之后更新状态
                if (info.name && this.props.$setData) {
                    this.props.$setData(info.name, fileList);
                }

                // 表单验证
                if (this.props.$setFormItem) {
                    this.props.$setFormItem({
                        formItemName: info.name,
                        valid: valid,
                        status: valid ? 'success' : 'error',
                    });
                }
            }
        }

        if (content.file.status === 'removed') {
            // 删除之后验证表单
            let validStatus: boolean = false;
            if (fileList.length > 0) {
                const validList = fileList.map((item: any) => {
                    if (item.validateWidthHeight) {
                        return item.validateWidthHeightStatus && item.validateSizeStatus && item.validateTypeStatus;
                    } else {
                        return item.validateSizeStatus && item.validateTypeStatus;
                    }
                });
                validStatus = validList.reduce((pre: boolean, next: boolean) => {
                    return pre && next;
                });
            }
            if (this.props.$setFormItem) {
                this.props.$setFormItem({
                    formItemName: info.name,
                    valid: validStatus,
                    status: validStatus ? 'success' : 'error'
                });
            }
        }

        if (content.file.status === 'error') {
            // 表单验证
            message.error('Upload fail');
            if (this.props.$setFormItem) {
                this.props.$setFormItem({
                    formItemName: info.name,
                    valid: false,
                    status: 'error'
                });
            }
        }
    }

    private mapUploadOptions(info: UploadConfig): UploadProps {
        return {
            className: info.className,
            style: info.style,
            listType: info.listType
        };
    }

    render() {
        let info = this.getPropsInfo(this.props.info);
        const uploadProps = this.mapUploadOptions(info);

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

        if (!this.isUnderContainerEnv()) {
            return <div>Upload component should be under container component</div>;
        }

        let value = this.getValueFromDataStore(info.name) || [];
        const {previewVisible, previewImage} = this.state;

        const action = info.action;
        const data = info.data || {};
        const uploadType = info.uploadType || [];
        const uploadSize = info.uploadSize || 500;
        const uploadNum = info.uploadNum || 3;
        const uploadWidth = info.uploadWidth;
        const uploadHeight = info.uploadHeight;

        let modalElement: React.ReactNode;
        let uploadButton: React.ReactNode;
        if (info.listType === 'picture-card') {
            // 图片类型的上传格式
            // 图片预览框
            modalElement = (
                <Modal visible={previewVisible} footer={null} onCancel={this.handleCancel}>
                    <img alt="example" style={{width: '100%'}} src={previewImage}/>
                </Modal>
            );
            // 图片上传按钮
            uploadButton = (
                <div>
                    <Icon type="plus"/>
                    <div className="ant-upload-text">上传</div>
                </div>
            );
        }

        let buttonElement: React.ReactNode;
        if (info.listType === 'text') {
            // 文本、视频类型的上传格式
            // 上传按钮
            buttonElement = (
                <Button>
                    <Icon type="upload" /> 上传
                </Button>
            );
        }
        return (
            <div className="clearfix">
                <Upload
                    {...uploadProps}
                    action={action}
                    data={data}
                    fileList={value}
                    onPreview={this.handlePreview}
                    onChange={(content) => {
                        this.handleChange(content, uploadType, uploadSize, uploadWidth, uploadHeight);
                    }}
                >
                    {value.length >= uploadNum ? null : uploadButton}
                    {buttonElement}
                </Upload>
                {modalElement}
            </div>
        );
    }
}

componentLoader.addComponent('upload', AbstractUpload, UploadPropsInterface);
