import { AccessTime, CalendarMonth, ExpandMore, Gesture, PictureAsPdf, Badge, Work } from '@mui/icons-material'
import { Box, Typography, Accordion, AccordionDetails, AccordionSummary, CircularProgress } from '@mui/material'
import styles from './style.module.scss'
import { useEffect, useState } from 'react'

import * as PDFJS from "pdfjs-dist";
PDFJS.GlobalWorkerOptions.workerSrc = 'node_modules/pdfjs-dist/build/pdf.worker.mjs';

interface Props {
  selectedFiles: any[]
}

interface PdfFile {
  file: File,
  pages: string[]
  expanded?: boolean
}

interface DrawTool {
  identifier: 'signature' | 'jobtitle' | 'fullname' | 'date' | 'datetime'
  label: string
  icon: JSX.Element,
  defaultValue?: string
  selected?: boolean
}

export const DrawPDFFields = (props: Props) => {
  const { selectedFiles } = props
  
  const [pdfFiles, setPdfFiles] = useState<PdfFile[]>([])
  const [parsingPdf, setParsingPdf] = useState<boolean>(false)
  const [showDrawToolBox, setShowDrawToolBox] = useState<boolean>(false)
  
  const [selectedTool, setSelectedTool] = useState<DrawTool | null>()
  const [toolbox] = useState<DrawTool[]>([
    {
      identifier: 'signature',
      icon: <Gesture/>,
      label: 'Signature'
  
    },
    {
      identifier: 'fullname',
      icon: <Badge/>,
      label: 'Full Name'
    },
    {
      identifier: 'jobtitle',
      icon: <Work/>,
      label: 'Job Title'
    },
    {
      identifier: 'date',
      icon: <CalendarMonth/>,
      label: 'Date'
    },
    {
      identifier: 'datetime',
      icon: <AccessTime/>,
      label: 'Datetime'
    },
  ])

  useEffect(() => {
    if (selectedFiles) {
      setParsingPdf(true)
      
      parsePdfPages().finally(() => {
        setParsingPdf(false)
      })
    }
  }, [selectedFiles])

  const parsePdfPages = async () => {
    const pdfFiles: PdfFile[] = []

    for (const file of selectedFiles) {
      if (file.type.toLowerCase().includes('pdf')) {
        const data = await readPdf(file)
        const pages = await pdfToImages(data)

        pdfFiles.push({
          file: file,
          pages: pages
        })
      }
    }
    
    setPdfFiles(pdfFiles)
  }

  const getPdfPages = (pdfFile: PdfFile) => {
    return (
      <Box sx={{
        width: '100%'
      }}>
        {pdfFile.pages.map((page: string) => {
          return (
            <div style={{
              border: '1px solid #c4c4c4',
              marginBottom: '10px'
            }} className={`${styles.pdfImageWrapper} ${selectedTool ? styles.drawing : ''}`}>
              <img draggable="false" style={{ width: '100%' }} src={page}/>
            </div>
          )
        })}
      </Box>
    ) 
  }

  /**
   * Converts pdf to the images
   * @param data pdf file bytes
   */
  const pdfToImages = async (data: any): Promise<string[]> => {
    const images: string[] = [];
    const pdf = await PDFJS.getDocument(data).promise;
    const canvas = document.createElement("canvas");
  
    for (let i = 0; i < pdf.numPages; i++) {
      const page = await pdf.getPage(i + 1);
      const viewport = page.getViewport({ scale: 3 });
      const context = canvas.getContext("2d");
      canvas.height = viewport.height;
      canvas.width = viewport.width;
      await page.render({ canvasContext: context!, viewport: viewport }).promise;
      images.push(canvas.toDataURL());
    }
  
    return Promise.resolve(images)
  }
  
  const readPdf = (file: File) => {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
  
      reader.onload = (e: any) => {
        const data = e.target.result
    
        resolve(data)
      };
      
      reader.onerror = (err) => {
        console.error('err', err)
        reject(err)
      };

      reader.readAsDataURL(file);
    })
  }

  const hasExpandedPdf = () => {
    return !!pdfFiles.filter(pdfFile => !!pdfFile.expanded).length
  }

  const handleAccordionExpandChange = (event: React.SyntheticEvent<Element, Event>, expanded: boolean, pdfFile: PdfFile) => {
    pdfFile.expanded = expanded

    setPdfFiles(pdfFiles)
    setShowDrawToolBox(hasExpandedPdf())
  }

  const handleToolSelect = (drawTool: DrawTool) => {
    // If clicked on the same tool, unselect
    if (drawTool.identifier === selectedTool?.identifier) {
      setSelectedTool(null)
      return
    }

    setSelectedTool(drawTool)
  }

  if (parsingPdf) {
    return (
      <Box sx={{ width: '100%', textAlign: 'center' }}>
        <CircularProgress/>
      </Box>
    )
  }

  if (!pdfFiles.length) {
    return ''
  }

  return (
    <Box>
      <Box sx={{ mt: 1 }}>
        <Typography sx={{ mb: 1 }}>Draw fields on the PDFs:</Typography>
        
        {pdfFiles.map((pdfFile) => {
          return (
            <Accordion expanded={pdfFile.expanded} onChange={(event, expanded) => {handleAccordionExpandChange(event, expanded, pdfFile)}}>
              <AccordionSummary
                expandIcon={<ExpandMore />}
                aria-controls="panel1-content"
                id="panel1-header"
              >
                <PictureAsPdf sx={{ mr: 1 }}/>
                {pdfFile.file.name}
              </AccordionSummary>
              <AccordionDetails>
                {getPdfPages(pdfFile)}
              </AccordionDetails>
          </Accordion>
          )
        })}
      </Box>

      {showDrawToolBox && (
        <Box className={styles.drawToolBoxContainer}>
          <Box className={styles.drawToolBox}>
            {toolbox.map((drawTool: DrawTool) => {
              return (
                <Box onClick={() => {handleToolSelect(drawTool)}} className={`${styles.toolItem} ${selectedTool?.identifier === drawTool.identifier ? styles.selected : ''}`}>
                  { drawTool.icon }
                  { drawTool.label }
                </Box>
              )
            })}
          </Box>
        </Box>
      )}
    </Box>
  )
}
