// Theirs
import React from 'react'
import Link from 'next/link'
import Router from 'next/router'
import formatDistanceToNow from 'date-fns/formatDistanceToNow'
import { useAsyncCallback } from 'actionsack'

import Button from '../components/Button'
import LoginButton from '../components/LoginButton'
import ConfirmButton from '../components/ConfirmButton'
import { useAuth } from '../components/AuthContext'
import { useAPI } from '../components/ApiContext'

import { MetaLinks } from '../components/Meta'
import Carbon from '../components/Carbon'

import { COLORS, DEFAULT_SETTINGS } from '../lib/constants'

// Ours
import Page from '../components/Page'

function correctTimestamp(n) {
  if (n < 9e12) {
    return n * 1000
  }
  return n
}

function Snippet(props) {
  const config = { ...DEFAULT_SETTINGS, ...props, fontSize: '2px', windowControls: false }

  return (
    <div className="snippet">
      <div className="column">
        <div className="carbon-container">
          <Carbon key={config.language} readOnly={true} config={config} loading={props.loading}>
            {props.code}
          </Carbon>
        </div>
        <div className="id">{props.title || props.id}</div>
        <div className="meta">
          Edited {formatDistanceToNow(correctTimestamp(props.updatedAt), { addSuffix: true })}
        </div>
      </div>
      <div className="overlay">
        <Link prefetch={false} href={`/${props.id}`}>
          <Button
            large
            border
            center
            flex="unset"
            margin="0 auto 1.5rem"
            padding="0.5rem 16px"
            color="#fff"
          >
            Open ↗
          </Button>
        </Link>
        <ConfirmButton
          large
          border
          center
          flex="unset"
          margin="0 auto"
          padding="0.5rem 20px"
          color="#fff"
          textColor={COLORS.RED}
          hoverColor={COLORS.RED}
          onClick={props.deleteSnippet}
        >
          Delete
        </ConfirmButton>
      </div>
      <style jsx>
        {`
          .snippet {
            position: relative;
            width: 266px;
            height: 266px;
            border: 1px solid ${COLORS.SECONDARY};
            border-radius: 3px;
            cursor: pointer !important;
            overflow: hidden;
          }
          .overlay {
            display: none;
            position: absolute;
            content: '↗';
            flex-direction: column;
            align-items: center;
            justify-content: center;
            background: ${COLORS.HOVER};
            opacity: 0.8;
            top: 0px;
            right: 0px;
            bottom: 0px;
            left: 0px;
            font-size: 48px;
            z-index: 999;
          }
          .snippet:hover .overlay {
            display: flex;
            background: ${COLORS.HOVER};
          }
          .column {
            display: flex;
            flex-direction: column;
            justify-content: space-between;
            height: 100%;
            overflow: hidden;
          }
          .id {
            position: absolute;
            top: 0.25rem;
            right: 0.25rem;
            border-radius: 3px;
            background: ${COLORS.SECONDARY};
            color: ${COLORS.BLACK};
            font-size: 10px;
            padding: 0.125rem;
            max-width: 80%;
            text-overflow: ellipsis;
            white-space: nowrap;
            overflow: hidden;
            z-index: 200;
          }
          .carbon-container {
            width: 100%;
            height: 100%;

            overflow: hidden;
            color: ${COLORS.SECONDARY};
            width: 266px;
          }
          .carbon-container :global(.CodeMirror__container .CodeMirror span) {
            font-size: 2px !important;
          }
          .meta {
            background: ${COLORS.SECONDARY};
            color: ${COLORS.DARK_GRAY};
            width: 100%;
            font-size: 10px;
            padding: 0.24rem;
            bottom: 0px;
          }
        `}
      </style>
    </div>
  )
}

function ActionButton(props) {
  return (
    <Button
      border
      center
      margin="0.5rem"
      flex="unset"
      color={COLORS.GRAY}
      style={{ width: 266, minHeight: 266 }}
      {...props}
    />
  )
}

function useOnMount() {
  const [mounted, mount] = React.useState(false)
  React.useEffect(() => {
    mount(true)
  }, [])

  return mounted
}

function SnippetsPage() {
  const user = useAuth()
  const api = useAPI()

  const [snippets, setSnippets] = React.useState([])
  const [page, setPage] = React.useState(0)

  const mounted = useOnMount()

  const [loadMore, { loading, data: previousRes }] = useAsyncCallback(api.snippet.list)

  React.useEffect(() => {
    if (user) {
      loadMore(page).then(newSnippets => setSnippets(curr => curr.concat(newSnippets)))
    }
  }, [loadMore, page, user])

  function deleteSnippet(id) {
    return api.snippet.delete(id).then(() => setSnippets(curr => curr.filter(s => s.id !== id)))
  }

  if (!user) {
    return <LoginButton />
  }

  return (
    <div className="container">
      {snippets.map(snippet => (
        <Snippet
          key={snippet.id}
          {...snippet}
          loading={!mounted}
          deleteSnippet={deleteSnippet.bind(null, snippet.id)}
        />
      ))}
      {snippets.length && previousRes && previousRes.length < 10 ? null : (
        <ActionButton
          disabled={loading}
          onClick={() => {
            if (snippets.length) return setPage(p => p + 1)

            Router.push('/')
          }}
        >
          <h4>{loading ? 'Loading...' : !snippets.length ? 'Create snippet +' : 'Load more +'}</h4>
        </ActionButton>
      )}
      <style jsx>
        {`
          .container {
            max-width: 872px;
            min-width: ${266 + 32 + 8}px;
            border: 3px solid ${COLORS.SECONDARY};
            border-radius: 8px;
            padding: 0.5rem;
            display: flex;
            flex-wrap: wrap;
          }
          .container :global(.snippet) {
            margin: 0.5rem;
          }
        `}
      </style>
    </div>
  )
}

export default () => (
  <Page enableHeroText={true} flex={true}>
    <MetaLinks />
    <SnippetsPage />
  </Page>
)