import forEach from 'lodash/forEach';
import get from 'lodash/get';
import React, { useCallback, useContext } from 'react';
import { useDropzone } from 'react-dropzone';
import { AttachmentDispatchContext, AttachmentStateContext } from './AttachmentReducerContext';
import FileLister from './FileLister';
import { defaultUploadMetadata, IAbleToUpload, ICaseFiles, IFileLocal, onFileEdit, onFileRemove, onFilesSelect } from './reducer/AttachemntReducer';

interface IProps {
    id?: string;
    className?: string;
}

const defaultProps: Partial<IProps> = {
    id: '',
    className: '',
};

export default function FileSelector(props: IProps) {
    // Drag Drop Related
    const onDrop = useCallback((acceptedFiles: File[]) => {
        forEach(acceptedFiles, async (file) => {
            const fileAccessDetails = await getFileAccessDetails(file);
            const localFile: IFileLocal = {
                name: file.name,
                size: file.size,
                lastModified: file.lastModified,
                type: file.type,
                description: '',
                uploadProgress: {...defaultUploadMetadata},
                uploadability: {...fileAccessDetails}
            };
            onFilesSelectLocal({selectedLocalFiles: [localFile], selectedOriginalFiles: [file]});
        });
    }, []);
    const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop });

    // Attachment Reducer Related
    const { attachmentState } = useContext(AttachmentStateContext);
    const dispatchToAttachmentReducer = useContext(AttachmentDispatchContext);
    const onFilesSelectLocal = (caseFiles: ICaseFiles) => {
        onFilesSelect(dispatchToAttachmentReducer, caseFiles);
    };
    const onFileEditLocal = async (editedLocalFile: IFileLocal, fileIndexToEdit: number) => {
        onFileEdit(dispatchToAttachmentReducer, editedLocalFile, fileIndexToEdit);
    };
    const onFileRemoveLocal = async (fileIndexToRemove: number) => {
        onFileRemove(dispatchToAttachmentReducer, fileIndexToRemove);
    };

    // Others
    const getFileAccessDetails = async (file: File): Promise<IAbleToUpload> => {
        if (file.size === 0) { return Promise.resolve({ableToUpload: false, ableToUploadMessage: 'File is empty'}); }
        const reader = new FileReader();
        return new Promise<IAbleToUpload>((resolve, reject) => {
            reader.onloadend = () => resolve({ableToUpload: true, ableToUploadMessage: 'File attached, but not yet uploaded'});
            reader.onerror = (ev: any) =>  resolve({ableToUpload: false, ableToUploadMessage: 'File cannot be uploaded'});
            // only read the first 10 bytes. readAsBinaryString is not supported in IE 11
            reader.readAsArrayBuffer(file.slice(0, 10));
        });
    };

    return (
        <section className={`${props.className}`} id={`${props.id}`}>
            <label htmlFor="select-file">Select logs or diagnostic files for faster analysis</label>
            <div className="select-file-wrapper" aria-label="Press enter to select a file" {...getRootProps({tabIndex: 0})}>
                <input id="select-file" {...getInputProps()}  style={{display:'inline-block !important'}} />
                {
                    <>
                        <label htmlFor="select-file" className="select-file-field">
                            {isDragActive ? `Drop your file here...` : ``}
                        </label>
                        <button id="select-file-button" className="btn btn-app btn-bordered-blue" type="button">
                            Select File
                        </button>
                    </>
                }
            </div>
            <p className="form-instructions">Drag a file here or browse to upload</p>
            {get(attachmentState.caseFiles, 'selectedLocalFiles.length', 0) > 0 && (
                <FileLister
                    selectedLocalFiles={attachmentState.caseFiles.selectedLocalFiles}
                    onFileEdit={onFileEditLocal}
                    onFileRemove={onFileRemoveLocal}
                />
            )}
        </section>
    );
}

FileSelector.defaultProps = defaultProps;
