import * as React from 'react'
import Head from 'next/head'
import styled from 'styled-components'
import Editor from '../components/Editor/Editor'
import * as Storage from '../services/Storage'
import generateId from '../utilities/Id'
import Link from 'next/link'
import { formatDate } from '../utilities/Date'
import { useRouter } from 'next/router'
import { XCircle } from 'react-feather'

const Navbar = styled('aside')({
  width: 360,
  height: '100%',
  position: 'fixed',
  top: 0,
  left: -360,
  backgroundColor: 'yellow',
  '@media (min-width: 1080px)': {
    width: `${100 / 3}%`,
    left: 0,
  },
})

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 NavbarContainer = styled('span')({
  display: 'block',
  width: '100%',
  margin: '0 0 0 auto',
  padding: '0 1rem',
  boxSizing: 'border-box',
  maxWidth: 360,
})

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

const NoteLink = styled('a')({
  display: 'flex',
  textDecoration: 'none',
  color: 'inherit',
  height: '4rem',
  alignItems: 'center',
  position: 'relative',
})

const NoteLinkTitle = styled('strong')({
  display: 'block',
})

const LinkContainer = styled('div')({
  position: 'relative',
})

const NoteActions = styled('div')({
  display: 'flex',
  position: 'absolute',
  alignItems: 'stretch',
  top: 0,
  right: 0,
  height: '100%',
})

const NoteAction = styled('button')({
  height: '100%',
  width: '4rem',
  background: 'transparent',
  border: 0,
  color: 'inherit',
  cursor: 'pointer',
  outline: 0,
})

const NoteLinkBackground = styled('span')({
  opacity: 0.125,
  backgroundColor: 'currentColor',
  top: 0,
  left: 0,
  width: '100%',
  height: '100%',
  position: 'absolute',
})

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

const Notes = ({ id: idProp }) => {
  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()

  const autoSave = () => {
    if (timeoutRef.current !== null) {
      window.clearTimeout(timeoutRef.current)
    }
    timeoutRef.current = window.setTimeout(async () => {
      const newNote = await Storage.saveNote({
        ...stateRef.current,
        title,
        updatedAt: new Date().toISOString(),
      })
      if (router.query.id !== id) {
        await router.push(`/notes/${id}`, undefined, { shallow: true })
      }
      setNotes(oldNotes => {
        let notes
        if (oldNotes.some((a) => a.id === id)) {
          notes = oldNotes.map(n => n.id === id ? newNote : n)
        } else {
          notes = [newNote, ...oldNotes]
        }
        return notes.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt))
      })
      timeoutRef.current = null
    }, 3000)
  }

  const handleEditorChange = e => {
    stateRef.current.content = e
    autoSave()
  }

  const handleTitleChange = e => {
    setTitle(e.target.value)
    autoSave()
  }

  React.useEffect(() => {
    const loadNotes = async () => {
      const theNotes = await Storage.loadNotes()
      setNotes(theNotes)
    }
    loadNotes()
  }, [])

  React.useEffect(() => {
    const loadFolders = async () => {
      const theFolders = await Storage.loadFolders()
      setFolders(theFolders)
    }
    loadFolders()
  }, [])

  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])

  React.useEffect(() => {
    autoSave()
  }, [title])

  return (
    <React.Fragment>
      <Head>
        <title>{ idProp === undefined ? 'Notes | New Note' : `Notes | ${title.length > 0 ? title : '(untitled)'}`}</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <Navbar>
        <Link
          href={{
            pathname: '/notes',
          }}
          passHref
        >
          <NoteLink>
            <NavbarContainer>
              <NoteLinkTitle>
                New Note
              </NoteLinkTitle>
            </NavbarContainer>
          </NoteLink>
        </Link>
        {
          Array.isArray(notes!)
          && notes.map(n => (
            <LinkContainer
              key={n.id}
            >
              {
                n.id === id
                && (
                  <NoteLinkBackground />
                )
              }
              <Link
                href={{
                  pathname: '/notes/[id]',
                  query: { id: n.id },
                }}
                passHref
              >
                <NoteLink>
                  <NavbarContainer>
                    <NoteLinkTitle
                      style={{ opacity: n.title.length > 0 ? 1 : 0.5, }}
                    >
                      {n.title.length > 0 ? n.title : '(untitled)'}
                    </NoteLinkTitle>
                    {' '}
                    <small>
                      <time
                        dateTime={new Date(n.updatedAt).toISOString()}
                      >
                        Last updated {formatDate(new Date(n.updatedAt))}
                      </time>
                    </small>
                  </NavbarContainer>
                </NoteLink>
              </Link>
              <NoteActions>
                <NoteAction>
                  <XCircle />
                </NoteAction>
              </NoteActions>
            </LinkContainer>
          ))
        }
      </Navbar>
      <Main>
        <Container>
          {
            Array.isArray(notes!)
            && (
              <React.Fragment>
                <TitleInput
                  placeholder="Title"
                  value={title}
                  onChange={handleTitleChange}
                />
                <Editor
                  autoFocus={false}
                  key={id}
                  content={stateRef.current ? stateRef.current.content : undefined}
                  onChange={handleEditorChange}
                  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
