import * as React from 'react'
import * as PropTypes from 'prop-types'
import { Icon } from '../../../../react-common/src'
import pkg from '../../../../../package.json'
import styled from 'styled-components'
import Link from 'next/link'
import Nav from '../Nav/Nav'
import { MouseEventHandler } from 'react'
import ThemeToggle from '../ThemeToggle/ThemeToggle'

const StyledLink = styled('a')({
  display: 'block',
  textDecoration: 'none',
  marginTop: '4rem',
  marginBottom: '3rem',
})

const Container = styled('span')({
  display: 'flex',
  alignItems: 'center',
  padding: '0 1rem',
  height: '2rem',
  margin: '0 0 0 auto',
  boxSizing: 'border-box',
  '@media (min-width: 720px)': {
    maxWidth: 'var(--max-width)',
  },
})

const Base = styled('aside')({
  '--max-width': 240,
  display: 'none',
  '@media only screen': {
    display: 'block',
    position: 'fixed',
    top: 0,
    width: '100%',
    height: '100%',
    backgroundColor: 'var(--color-bg)',
    zIndex: 4,
    transitionProperty: 'color, background-color, left',
    transitionTimingFunction: 'ease',
    transitionDuration: '350ms',
    overflow: 'auto',
    '@media (min-width: 720px)': {
      left: '0 !important',
      width: `${100 / 4}%`,
      maxWidth: 'none',
      height: '100%',
      '+ *': {
        paddingLeft: `${100 / 4}%`,
        boxSizing: 'border-box',
      },
    },
  },
})

const SidebarToggle = styled('a')({
  display: 'none',
  '@media only screen': {
    width: '4rem',
    height: '4rem',
    position: 'fixed',
    top: 0,
    left: 0,
    display: 'grid',
    placeContent: 'center',
    zIndex: 5,
    '@media (min-width: 720px)': {
      display: 'none',
    },
    '::before': {
      backgroundColor: 'var(--color-bg)',
      content: "''",
      position: 'absolute',
      top: 0,
      left: 0,
      width: '100%',
      height: '100%',
      opacity: 0.75,
      zIndex: -1,
    },
  },
})

const Actions = styled('div')({
  marginBottom: '4rem',
  display: 'grid',
  gap: '1rem',
  alignItems: 'center',
  gridTemplateColumns: 'auto auto',
})

const NavWrapper = styled('nav')({
  '--size-link': '3rem',
  marginBottom: '4rem',
})

const RepoLink = styled('a')({
  display: 'inline-grid',
  width: '1.5rem',
  height: '1.5rem',
  placeContent: 'center',
})

const propTypes = {
  data: PropTypes.shape({
    nav: PropTypes.array,
  }),
  brand: PropTypes.elementType,
  initialTheme: PropTypes.string,
}

type Props = PropTypes.InferProps<typeof propTypes>

const Sidebar: React.FC<Props> = ({
  data,
  brand: BrandRaw,
  initialTheme,
}) => {
  const [sidebar, setSidebar] = React.useState(false)
  const navRef = React.useRef<HTMLDivElement>(null)
  const Brand = BrandRaw!

  const toggleSidebar = (b: boolean): MouseEventHandler => (e) => {
    e.preventDefault()
    setSidebar(b)
  }

  const handleSidebarClose = (e: MouseEvent) => {
    let currentElement = e.target as HTMLElement
    while (currentElement !== e.currentTarget) {
      if (currentElement.tagName === 'A') {
        setSidebar(false)
        break
      }
      const { parentElement } = currentElement
      if (parentElement as HTMLElement === null) {
        break
      }
      currentElement = parentElement as HTMLElement
    }
  }

  React.useEffect(() => {
    navRef.current.addEventListener('click', handleSidebarClose, { capture: true })
    return () => {
      navRef.current.removeEventListener('click', handleSidebarClose, { capture: true })
    }
  }, [])

  return (
    <React.Fragment>
      <SidebarToggle
        onClick={toggleSidebar(!sidebar)}
      >
        {
          !sidebar && (
            <Icon
              name="menu"
            />
          )
        }
        {
          sidebar && (
            <Icon
              name="x"
            />
          )
        }
      </SidebarToggle>
      <Base
        ref={navRef}
        style={{
          left: sidebar ? 0 : '-100%',
        }}
      >
        <NavWrapper>
          <Link
            href="/"
            passHref
          >
            <StyledLink>
              <Container>
                <Brand />
              </Container>
            </StyledLink>
          </Link>
          <Container>
            <Actions>
              <ThemeToggle
                initialTheme={initialTheme}
              />
              <RepoLink
                href={pkg.repository}
                target="_blank"
                rel="noopener noreferrer"
              >
                <Icon
                  name="code"
                  label="Visit Repository"
                />
              </RepoLink>
            </Actions>
          </Container>
          <Nav
            data={data!.nav}
          />
        </NavWrapper>
      </Base>
    </React.Fragment>
  )
}

Sidebar.propTypes = propTypes

export default Sidebar