import * as React from 'react'
import Head from 'next/head'
import styled from 'styled-components'
import { useRouter } from 'next/router'
import Editor from '../components/Editor/Editor'
import Navbar from '../components/Navbar/Navbar'
import generateId from '../utilities/Id'
import { formatDate } from '../utilities/Date'
import * as Note from '../controllers/Note'
import * as Folder from '../controllers/Folder'

const Main = styled('main')({
  margin: '2rem 0',
  '@media (min-width: 1080px)': {
    paddingLeft: `${100 / 3}%`,
    boxSizing: 'border-box',
  },
})

const Container = styled('div')({
  width: '100%',
  margin: '0 auto',
  padding: '0 1rem',
  boxSizing: 'border-box',
  '@media (min-width: 720px)': {
    maxWidth: 720,
  },
})

const TitleInput = styled('input')({
  border: 0,
  background: 'transparent',
  padding: 0,
  display: 'block',
  width: '100%',
  font: 'inherit',
  fontSize: '3rem',
  fontWeight: 'bold',
  color: 'inherit',
  outline: 0,
})

const PostMeta = styled('small')({
  opacity: 0.5,
  height: '1.25rem',
  display: 'block',
  lineHeight: 1.25,
})

const PostPrimary = styled('div')({
  marginBottom: '2rem',
})

type NoteInstance = { id: string, title: string, content?: object, updatedAt: string, }

const Notes = ({ id: idProp }) => {
  // TODO remove extra state for ID
  const [id, setId, ] = React.useState(idProp)
  const [title, setTitle, ] = React.useState('')
  const [notes, setNotes, ] = React.useState(null)
  const [folders, setFolders, ] = React.useState(null)
  const stateRef = React.useRef<NoteInstance>({ id, title: '', updatedAt: new Date().toISOString(), })
  const timeoutRef = React.useRef<number>(null)
  const router = useRouter()

  React.useEffect(() => {
    Note.load({ setNotes })
  }, [])

  React.useEffect(() => {
    Folder.load({ setFolders })
  }, [])

  React.useEffect(() => {
    if (!Array.isArray(notes!)) {
      return
    }
    const theNote = notes.find(n => n.id === id)
    stateRef.current = theNote ? theNote : { id, title: '', updatedAt: new Date().toISOString(), }
    setTitle(stateRef.current.title)
  }, [id, notes])

  React.useEffect(() => {
    setId(idProp || generateId())
  }, [idProp])

  return (
    <React.Fragment>
      <Head>
        <title>{ idProp === undefined ? 'Notes | New Note' : `Notes | Edit Note - ${title.length > 0 ? title : '(untitled)'}`}</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <Navbar
        closeHref={{
          pathname: router.pathname,
          query: Object
            .entries(router.query)
            .filter(([key]) => key !== 'navbar')
            .reduce(
              (theQuery, [key, value]) => ({
                ...theQuery,
                [key]: value,
              }),
              {}
            ),
        }}
        secondaryVisible={Boolean(router.query.navbar)}
        primaryItemsStart={[
          {
            id: 'sidebar',
            mobileOnly: true,
            active: Boolean(router.query.navbar),
            href: {
              pathname: router.pathname,
              query: {
                ...router.query,
                navbar: 'true',
              },
            },
            iconName: 'menu',
            title: 'Menu',
          },
          {
            id: 'folders',
            active: router.pathname.startsWith('/notes') && !Boolean(router.query.navbar),
            href: {
              pathname: '/notes',
            },
            iconName: 'note',
            title: 'Notes',
          },
          {
            id: 'search',
            href: {
              pathname: '/notes',
              query: {
                action: 'search',
              },
            },
            iconName: 'search',
            title: 'Search',
          },
          {
            id: 'binned',
            href: {
              pathname: '/notes',
              query: {
                status: 'binned',
              },
            },
            iconName: 'bin',
            title: 'Bin',
          },
        ]}
        primaryItemsEnd={[
          {
            id: 'user',
            href: {
              pathname: '/me',
            },
            iconName: 'user',
            title: 'User',
          },
        ]}
        secondaryItemsHeader={[
          {
            id: 'parent',
            href: {
              pathname: '/notes',
              query: {
                folder: '00000000-0000-0000-000000000000',
                navbar: router.query.navbar,
              },
            },
            iconName: 'back',
            title: 'Folder Name',
            // todo use history back
          },
          {
            id: 'note',
            href: {
              pathname: '/notes',
              query: {
                action: 'new',
                parentFolderId: '00000000-0000-0000-000000000000',
              },
            },
            iconName: 'new-note',
            title: 'Create Note',
          },
          {
            id: 'folder',
            href: {
              pathname: '/folders',
              query: {
                action: 'new',
                parentFolderId: '00000000-0000-0000-000000000000',
              },
            },
            iconName: 'new-folder',
            title: 'Create Child Folder',
          },
          {
            id: 'map',
            href: {
              pathname: '/notes',
              query: {
                action: 'view-map',
                parentFolderId: '00000000-0000-0000-000000000000',
              },
            },
            iconName: 'mind-map',
            title: 'View Folder Mind Map',
          },
        ]}
        secondaryItems={
          Array.isArray(notes!)
            ? notes.map(n => ({
              id: n.id,
              active: n.id === id,
              href: {
                pathname: '/notes/[id]',
                query: { id: n.id },
              },
              iconName: 'note',
              replace: true,
              title: n.title.trim(),
              subtitle: (
                <time
                  dateTime={new Date(n.updatedAt).toISOString()}
                >
                  {formatDate(new Date(n.updatedAt))}
                </time>
              ),
              actions: [
                {
                  id: 'bin',
                  iconName: 'bin',
                  onClick: Note.remove({ setNotes, notes, router, })(n),
                }
              ],
            }))
            : []
        }
      />
      <Main>
        <Container>
          {
            Array.isArray(notes!)
            && (
              <React.Fragment>
                <PostPrimary>
                  <TitleInput
                    placeholder="Title"
                    value={title}
                    onChange={Note.updateTitle({
                      stateRef,
                      timeoutRef,
                      router,
                      id,
                      setNotes,
                      setTitle,
                    })}
                  />
                  <PostMeta>
                    {
                      stateRef.current.updatedAt
                      && router.query.id
                      && (
                        <time
                          dateTime={new Date(stateRef.current.updatedAt).toISOString()}
                        >
                          Last updated {formatDate(new Date(stateRef.current.updatedAt))}
                        </time>
                      )
                    }
                  </PostMeta>
                </PostPrimary>
                <Editor
                  autoFocus={false}
                  key={id}
                  content={stateRef.current ? stateRef.current.content : undefined}
                  onChange={Note.updateContent({
                    stateRef,
                    timeoutRef,
                    router,
                    id,
                    setNotes,
                  })}
                  placeholder="Start typing here..."
                />
              </React.Fragment>
            )
          }
        </Container>
      </Main>
    </React.Fragment>
  )
}

export const getServerSideProps = async ctx => {
  if (ctx.params) {
    return {
      props: {
        id: ctx.params?.id
      }
    }
  }

  return {
    props: {}
  }
}

export default Notes
