import * as React from 'react';
import {
    isArray,
    includes,
    isEmpty
} from 'lodash';
import {handleFileSelect} from '../function'
import Icon from '../Icon';
import PropsTypes from './types';
import * as numeral from 'numeral';
import FormComponent from '../FormComponent';
import Input from "../Input";
import ScrollArea from 'react-scrollbar'

interface State extends PropsTypes {
    files: any[],
    loading: boolean,
    fileDetail: any[],
    errorMessage: any[],
    tempFilesError: any[],
    inputOption: any,
    show: boolean
}

export default class FileUpload extends FormComponent<PropsTypes, State> {

    public state: State;

    // private input = React.createRef<HTMLInputElement>();

    constructor(props: PropsTypes, {}) {
        super(props);

        let iOption = {};
        if (props.inputOption && !isEmpty(props.inputOption)) {
            iOption = {
                editable: props.inputOption.editable || true,
                icon: props.inputOption.icon || null,
                label: props.inputOption.label || null,
                caption: props.inputOption.caption || '',
                size: props.inputOption.size || 'medium',
                customStyle: props.inputOption.customStyle || '',
                closeAfterSelect: props.inputOption.closeAfterSelect || true,
                infoText: props.inputOption.infoText || '',
                autoFocus: props.inputOption.autoFocus || false,
            }
        }

        this.state = {
            files: [],
            loading: false,
            fileDetail: [],
            errorMessage: [],
            tempFilesError: [],
            inputOption: iOption,
            show:false
            // ...props
        };
    }

    componentDidMount() {
        const {fileDetail} = this.state;
        this.validate(fileDetail.filter(t => t.status === 2).length ? 'true' : '')
    }

    errorRules(val: any) {
        const {maxSize, minSize, multiple, maxFile, minFile, mimeTypes} = this.props;

        if (val && val.length) {
            val.forEach((t:any) => {

                if (mimeTypes && isArray(mimeTypes) && !mimeTypes.filter(x => includes(t.type, x)).length) {
                    t.error = `Bu formatta dosya ekleyemezsiniz`
                }

                if (maxSize && t.size > maxSize) {
                    t.error = `Dosya boyutu en fazla ${numeral(maxSize).format('0.0 b')} olmalıdır`
                }

                if (minSize && t.size < minSize) {
                    t.error = `Dosya boyutu en az ${numeral(minSize).format('0.0 b')} olmalıdır`
                }

                if (t.size > 1000000000) {
                    t.error = 'Dosya boyutu çok büyük. İzin verilen boyut max 1 GB'
                }
            });

        }

        let fileSize: number = val.filter((t:any) => !t.error).length;
        // let fileUnreadSize:number = val.filter(t => t.error).length;

        let errMsg: any[] = [];

        if (!multiple && fileSize > 1) {
            errMsg.push('Yalnızca 1 dosya yüklenebilir')
        }

        /* if (fileUnreadSize) {
             errMsg.push('Yüklemeye çalıştığınız dosyalar okunamadı')
         }*/

        if (multiple && minFile && fileSize < minFile) {
            errMsg.push(`En az ${minFile} dosya yüklenmelidir`)
        }

        if (maxFile && multiple && fileSize > maxFile) {
            errMsg.push(`Yalnızca ${maxFile} dosya yüklenebilir`)
        }

        this.setState({
            files: val,
            errorMessage: errMsg
        });
    }

    async handleChange(val: any) {
        const {files} = this.state;
        const inputFiles = val.target.files;
        const stateFiles: any[] = [
            ...files,
            ...Array.from(inputFiles)
        ];

        await this.errorRules(stateFiles);

        this.setState({
            files: stateFiles,
            errorMessage: []
        }, () => {
            this.fileStart();
        })

    }

    fileOverWrite(callbackFile:any) {
        const {fileDetail} = this.state;
        let tempFileDetail: any[] = fileDetail;
        let isFile = tempFileDetail.filter(t => t.name === callbackFile.name);

        if (!isFile.length) {
            tempFileDetail.push(callbackFile)
        } else {
            tempFileDetail.filter((f) => {
                if (f.name === callbackFile.name) {
                    f = callbackFile
                }
            });
        }

        this.setState({
            fileDetail: tempFileDetail
        })
    }

    fileRead(callback:any) {
        const {fileDetail} = this.state;
        let tempFileDetail: any[] = fileDetail;

        tempFileDetail.filter((f) => {
            if (f.id === callback.id && !f.read) {
                f.status = callback.status;
            }
        });

        this.setState({
            fileDetail: tempFileDetail
        })
    }

    fileDone = (callback:any) => {
        const {fileDetail, errorMessage, files} = this.state;
        const {onChange, /*imageMaxHeight, imageMaxWidth, *//*imageMinHeight, imageMinWidth*/} = this.props;

        let tempFileDetail: any[] = fileDetail;
        let tempFiles: any[] = files;

        tempFileDetail.filter((f) => {
            if (f.id === callback.id && !f.read) {
                f.status = callback.status;
                f.read = callback.read;
                f.output = callback.output;
            }
        });

        this.setState({
            fileDetail: tempFileDetail,
            files: tempFiles
        }, () => {
            this.validate(errorMessage.length ? '' : 'true', errorMessage[0])
            onChange && onChange(tempFileDetail.filter(t => t.status === 2))
        })
    }

    fileProgress(callbackProgress:any) {
        const {fileDetail} = this.state;
        let tempFileDetail: any[] = fileDetail;

        tempFileDetail.filter((f) => {
            if (f.id === callbackProgress.id && !f.read) {
                f.progress = callbackProgress.progress;
            }
        });

        this.setState({
            fileDetail: tempFileDetail
        })
    }

    async fileStart() {
        const {files} = this.state;

        if (files.length) {
            for (let i in files) {
                if (Number(i) < files.length) {
                    handleFileSelect(
                        files[Number(i)],
                        files[i].error,
                        (callbackStart: any) => callbackStart && this.fileOverWrite(callbackStart),
                        (callbackRead: any) => callbackRead && this.fileRead(callbackRead),
                        (callbackDone: any) => callbackDone && this.fileDone(callbackDone),
                        (callbackProgress: any) => this.fileProgress(callbackProgress)
                    )
                }
            }
        }
    }

    /*fileOpen(): void {
        this.input.current && this.input.current.click()
    }*/

    fileRemove(id: any) {
        const {onChange} = this.props;
        const {files, fileDetail} = this.state;
        let fileDetailList: any[] = [];
        let fileList: any[] = [];

        fileDetailList = fileDetail.filter(t => t.id !== id);
        fileList = files.filter(t => t.lastModified !== id);

        this.setState({
            files: fileList,
            fileDetail: fileDetailList
        }, () => {
            onChange && onChange(fileDetailList.filter(t => t.status === 2))
        })
    }

    renderFileItems() {
        const {fileDetail} = this.state;

        if (isArray(fileDetail) && fileDetail.length) {

            let progress: any = null;
            let icon: string = 'file';
            return fileDetail.map((item: any, i: number) => {
                progress = `${item.progress}%`;

                // console.log('File', item)

                if (includes(item.type, 'zip') || includes(item.type, 'rar') || includes(item.type, '7z')) {
                    icon = 'fa-file-archive'
                } else if (includes(item.type, 'document')) {
                    icon = 'fa-file-alt'
                } else if (includes(item.type, 'image')) {
                    icon = 'fa-file-image'
                } else if (includes(item.type, 'pdf')) {
                    icon = 'fa-file-pdf'
                } else {
                    icon = 'fa-file'
                }

                if (item.error) {
                    icon = 'fa-exclamation-circle';
                }

                return <div className={`jump-ui-file-selected-list ${item.error ? 'error' : null}`} key={i}>
                    {item.status !== 2 ? <span style={{width: progress}}/> : null}
                    <div className="jump-ui-file-icon">
                        {item.status === 2 && <Icon icon={`fas ${icon}`} spin={false}/>}
                        {item.status === 0 || item.status === 1 && <Icon icon="fal fa-spinner-third" spin={true}/>}
                        {item.status === -1 && <Icon icon={`fas ${icon}`}/>}
                    </div>
                    <div className="jump-ui-file-text">
                        <div className="name">
                            {item.name}
                        </div>
                        <div className="size">
                            {item.status === 2 && !item.error ? item.size.textValue : item.error ? item.error : `Dosya okunuyor (%${item.progress} bitti)`}
                        </div>
                    </div>
                    <div className="jump-ui-file-icon remove-icon">
                        <Icon icon="fal fa-times" onClick={() => this.fileRemove(item.id)}/>
                    </div>
                </div>
            })
        }

        return null
    }

    renderInput() {

        const {inputOption, fileDetail, show} = this.state;
        const {validate, disabled} = this.props;

        return <div style={{position: 'relative'}}>
            <Input
                id={this.defaultId}
                name="Datepicker-Inputcomponent"
                caption={inputOption.caption}
                type="text"
                onChange={() => {}}
                validate={validate}
                disabled={disabled}
                readOnly={this.readOnly()}
                readOnlyInput={this.readOnly()}
                errorMessage={this.error()}
                autoFocus={inputOption.autoFocus}
                onClick={() => {
                    this.setState({show: !this.state.show})
                }}
                icon={inputOption.icon}
                value={fileDetail ? `${fileDetail.filter(t => t.status === 2).length} dosya seçili` : ''}
                size={inputOption.size}
                customStyle={inputOption.customStyle}
                infoText={inputOption.infoText}
            />

            {show
                ? <div className="jump-ui-dropdown">
                    {this.renderFileArea()}
                </div>
                : null}
        </div>
    }

    /*renderModal() {
        return <div className="jump-ui-upload-modal">
            {this.renderFileArea()}
        </div>
    }*/

    renderFileArea() {
        const {fileDetail, errorMessage} = this.state;
        const {caption, multiple, infoText} = this.props;

        return <div className={`jump-ui-file-uploader ${this.error() ? 'error' : null}`}>

            {errorMessage.length ? <div className="file-error-container">
                {errorMessage.map((t, i) => {
                    return <p key={i}>{t}</p>
                })}
            </div> : null}

            {isEmpty(this.error()) ? <div className="info-text-ui">{infoText}</div> : null}

            {this.error() ? <div className="error-message-ui">
                {this.error()}
            </div> : null}

            <div className="file-select-area">
                <Icon icon="fal fa-cloud-upload"/>
                <div className="title">
                    {caption}
                </div>
                <div className="text">
                    {fileDetail ? `${fileDetail.filter(t => t.status === 2).length} dosya seçili` : null} <br/><br/>
                </div>
                <input
                    type="file"
                    multiple={multiple}
                    onChange={(val: any) => this.handleChange(val)}
                />
            </div>

            <ScrollArea smoothScrolling={true} speed={0.8} className="file-list-area-container" contentClassName="" horizontal={false}>
                {this.renderFileItems()}
            </ScrollArea>


        </div>
    }

    public render() {
        const {uiType} = this.props;
        return uiType === 'input' ? this.renderInput() : this.renderFileArea()
    }
}
