import { AnchorButton, Button, ButtonGroup, Divider } from '@blueprintjs/core'
import { css } from '@emotion/react'
import { lazy, Suspense, useMemo, type FC } from 'react'
import CenteredSpinner from '../CenteredSpinner'
import Container from '../Container'
import ErrorMessage from '../ErrorMessage'
import Header from './Header'
import type { Document, RendererProps } from './types'

const ImageRenderer = lazy(() => import('./renderers/ImageRenderer'))
const NotSupportedRenderer = lazy(
  () => import('./renderers/NotSupportedRenderer')
)
const PDFRenderer = lazy(() => import('./renderers/PDFRenderer'))
const TextRenderer = lazy(() => import('./renderers/TextRenderer'))
const VideoRenderer = lazy(() => import('./renderers/VideoRenderer'))
const SUPPORTED_FILE_TYPES: {
  [name: string]: FC<RendererProps>
} = {
  // TODO: add support for audio files

  bmp: ImageRenderer,
  gif: ImageRenderer,
  jpg: ImageRenderer,
  jpeg: ImageRenderer,
  png: ImageRenderer,
  webp: ImageRenderer,

  pdf: PDFRenderer,

  txt: TextRenderer,

  // TODO: add support for svg files

  // TODO: add support for more video types
  mp4: VideoRenderer,
  webm: VideoRenderer,
}
export const SUPPORTED_FILE_EXTENSIONS = Object.keys(SUPPORTED_FILE_TYPES)

interface DocViewerProps {
  doc: Document
  loading?: boolean
  error?: Error
  contentOnly?: boolean
  onBack?: () => void
}

const grid = css`
  display: grid;
  grid-template-rows: 2rem 1fr;
  padding: 0.5rem;
  grid-gap: 1rem;
  height: 100vh;
`

const fileView = css`
  overflow-y: auto;
  display: flex;
  flex-direction: column;
`

const contentClass = css`
  flex: 1;
  overflow-y: auto;
`

const DocViewerPage: FC<DocViewerProps> = ({
  doc,
  loading,
  error,
  contentOnly,
  onBack,
}) => {
  const extension = useMemo(() => doc.fileName.split('.').pop(), [doc.fileName])

  const content = useMemo(() => {
    if (loading) {
      return <CenteredSpinner />
    }
    if (error) {
      return (
        <ErrorMessage>
          <h1>Error occurred!</h1>
          <p>{error.message}</p>
        </ErrorMessage>
      )
    }
    if (!extension || !SUPPORTED_FILE_EXTENSIONS.includes(extension)) {
      return <NotSupportedRenderer doc={doc} />
    }

    const Renderer = SUPPORTED_FILE_TYPES[extension]
    return <Renderer doc={doc} />
  }, [doc, error, extension, loading])

  if (contentOnly) {
    return content
  }

  return (
    <div css={grid}>
      <div>
        <ButtonGroup minimal>
          {onBack && (
            <>
              <Button intent='primary' icon='arrow-left' onClick={onBack}>
                Back
              </Button>
              <Divider />
            </>
          )}
          <AnchorButton
            icon='import'
            href={doc.uri}
            target='_blank'
            rel='noreferrer'
            loading={loading}
            download={doc.fileName}
          >
            Download
          </AnchorButton>
        </ButtonGroup>
      </div>

      <Container css={fileView}>
        <Header fileName={doc.fileName} />
        <Suspense fallback={<CenteredSpinner />}>
          <div css={contentClass}>{content}</div>
        </Suspense>
      </Container>
    </div>
  )
}

export default DocViewerPage
