import React from "react"
import { useState } from "react"
import { useContextMenu } from "react-contexify"
import { RouteComponentProps } from "react-router-dom"
import downloadFile from "../functions/downloadFile"
import genDownloadLink from "../functions/genDownloadLink"
import normalizeDirPath from "../functions/normalizeDirPath"
import uploadFile from "../functions/uploadFile"
import { useCopyMutation, useCreateDirMutation, useDeleteDirMutation, useDeleteFileMutation, useMoveMutation, useOpenDirQuery } from "../generated/graphql"
import Breadcrum from "./Breadcrum"
import CreateDirButton from "./CreateDirButton"
import DragAndDrop from "./DragAndDrop"
import FileBrowserContextMenu, { Action, CONTEXT_MENU_DIR, CONTEXT_MENU_FILE } from "./FileBrowserContextMenu"
import FileOpen from "./FileOpen"
import FileUploadButton from "./FileUploadButton"
import { ReactComponent as Spinner } from "./../assets/spinner.svg"
import FileBrowserList from "./FileBrowserList"

function uriToPath(pathname:string) {
	// strip the "/f" from e.g. "/f/dir1/dir2"
	return pathname.substr(2)
}

function pathToUri(path:string) {
	return (path.startsWith("/")?"/f":"/f/") + path
}

const FileBrowser: React.FC<RouteComponentProps> = (props) => {
	const path = uriToPath(props.location.pathname)

	const [openFileId, setOpenFileId] = useState("")
	const [showFile, setShowFile] = useState(false)

	const [srcID,setSrcID] = useState("")
	const [pasteAction,setPasteAction] = useState<Action>()

	const [deleteMutation] = useDeleteFileMutation()
	const [copyMutation] = useCopyMutation()
	const [moveMutation] = useMoveMutation()
	const [createDirMutation] = useCreateDirMutation()
	const [deleteDirMutation] = useDeleteDirMutation()

	const { show: showFileContext } = useContextMenu({
		id: CONTEXT_MENU_FILE,
	})

	const { show: showDirContext } = useContextMenu({
		id: CONTEXT_MENU_DIR,
	})

	const { data, loading, refetch: refetchDir } = useOpenDirQuery({
		variables:{
			path
		}
	})

	async function handleDrop(files:FileList) {
		const wait: Promise<boolean>[] = []
		for (let i = 0; i < files.length; i++) {
			const file = files[i]
			wait.push(uploadFile(file, path + file.name))
		}

		await Promise.all(wait)
		refetchDir()
	}

	async function onContextSelect(action:Action, id: string) {
		switch (action) {
		case Action.FileDelete:
			await deleteMutation({variables:{id}})
			refetchDir()
			break
		case Action.FileCopy:
		case Action.FileMove:
			setSrcID(id)
			setPasteAction(action)
			break
		case Action.FilePaste:
			if (pasteAction === Action.FileCopy){
				await copyMutation({variables:{src:srcID,dest:path}})
				refetchDir()
			}

			if (pasteAction === Action.FileMove){
				await moveMutation({variables:{src:srcID,dest:path}})
				refetchDir()
			}
			break
		case Action.DirDelete:
			await deleteDirMutation({variables:{path:id}})
			refetchDir()
			break
		case Action.FileDownload:
			downloadFile(genDownloadLink(id))
			break
		default:
			break
		}
	}

	return (
		<div className="dark:text-gray-300">
			<FileBrowserContextMenu
				onSelect={onContextSelect}
				pasteActive={!!srcID}
			/>
			<DragAndDrop
				handleDrop={async (files)=>{
					await handleDrop(files)
				}}
			>
				<div className="flex justify-between">
					<Breadcrum path={path} onDirClick={(newPath)=>{
						props.history.push(pathToUri(newPath))
					}}/>
					<div className="ml-auto">
						<CreateDirButton 
							onPressed={async (dirName)=>{
								const fullPath = normalizeDirPath(path + dirName)
								await createDirMutation({variables:{path: fullPath}})
								refetchDir()
							}}
						/>
					</div>
					<div>
						<FileUploadButton 
							onUpload={(files)=>handleDrop(files)}
						/>
					</div>

				</div>
				<div>
					<FileBrowserList 
						directorys={data?.directorys || []}
						files={data?.files || []}

						onDirClick={(e,path)=>{
							props.history.push(pathToUri(path))
						}}

						onDirContext={(e,path)=>{
							e.preventDefault()
							showDirContext(e,{props:{id:path}})
						}}

						onFileClick={(e,id)=>{
							setOpenFileId(id)
							setShowFile(true)
						}}

						onFileContext={(e,id)=>{
							e.preventDefault()
							showFileContext(e,{props:{id}})
						}}
					/>
					{loading && 
						<div className="flex justify-center mt-4">
							<Spinner />
						</div>
					}
				</div>
				<FileOpen id={openFileId} show={showFile} onCloseClick={()=>{
					setShowFile(false)
				}} />
			</DragAndDrop>
		</div>
	)
}

export default FileBrowser
