import React, { useRef, useState } from 'react'
import styled from 'styled-components'

export type FileInputProps = {
 onUpload: (files:File[]) => void;
 formats?: string []
};

export const FileInput = ({ onUpload, formats }: FileInputProps):JSX.Element => {
  const drop = useRef<HTMLDivElement>(null)
  const [dragging, setDragging] = useState(false)
  const [message, setMessage] = useState({
    show: false,
    text: '',
    type: '',
  })

  const showMessage = (text:string, type:string, timeout:number) => {
    setMessage({
      show: true,
      text,
      type,
    })

    setTimeout(() => setMessage({
      show: false,
      text: '',
      type: '',
    }), timeout)
  }

  const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {
    e.preventDefault()
    e.stopPropagation()
  }

  const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {
    e.preventDefault()
    e.stopPropagation()
    setDragging(false)
    const files = Array.from(e.dataTransfer.files)
    handleFileValidation(files)
  }

  const handleDragEnter = (e: React.DragEvent<HTMLDivElement>) => {
    e.preventDefault()
    e.stopPropagation()
    setDragging(true)
  }

  const handleDragLeave = (e: React.DragEvent<HTMLDivElement>) => {
    e.preventDefault()
    e.stopPropagation()
    setDragging(false)
  }

  const handleFileValidation = (files: File[]) => {
    if (formats && files.some((file) => !formats.some((format) => file.name.toLowerCase().endsWith(format.toLowerCase())))) {
      showMessage(`Only following file formats are acceptable: ${formats.join(', ')}`, 'error', 1500)
      return
    }

    if (files && files.length) {
      showMessage('Succesfully dropped the file!', 'success', 1000)
      onUpload(files)
    }
  }

  const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    e.preventDefault()
    if (drop.current) {
      if(drop.current.click) drop.current.click()
      const { files } = e.target
      handleFileValidation(Array.from(files||[]))
    }
  }

  return (
    <DragDropContainer 
      onDragOver={handleDragOver}
      onDrop={handleDrop}
      onDragEnter={handleDragEnter}
      onDragLeave={handleDragLeave}
      status={message.show ? message.type : ''}
      ref={drop}>
      {message.show && (
        <div>
          {message.text}
        </div>
      ) }
      {dragging && <div> Drop file down</div>}
      {!dragging && !message.show && (
        <>
          Drag and drop your file here or
          <Label htmlFor="file-upload">Upload a file</Label>
          <FileUploadInput
            accept='.jpeg, .png, .jpg'
            id="file-upload"
            onChange={onChange}
            type="file"
          />
        </>
      )}
    </DragDropContainer>
  )
}

const DragDropContainer = styled.div<{status?:string}>`
  width: 300px;
  padding: 40px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  font-size: 1.5rem;
  color: #555555;
  border: 2px #c3c3c3 dashed;
  border-radius: 12px;
  background-color:  ${(p) => p.status === 'error' && '#f7e7e7'};
  background-color:  ${(p) => p.status === 'success' && '#e7f7e7'};
  color:  ${(p) => p.status === 'error' && '#cf8e99'};
  color:  ${(p) => p.status === 'success' && '#8ecf99;'};
`

const FileUploadInput = styled.input`
  display: none;
`
const Label = styled.label`
  border: none;
  color: white;
  font-size: 1.1rem;
  background-color: #228be6;
  padding: 10px 10px;
  text-align: center;
  margin-top: 20px;
  cursor: pointer;
  border-radius: 10px;
  transition: all 0.2s ease-in-out;
  outline: none;

  &:hover {
    opacity: 0.8;
  }
`
