import React from 'react'
import withDefaults from '../utils/with-defaults'
import useTheme from '../use-theme'

const Panel: React.FC<React.PropsWithChildren<{ active?: boolean }>> = ({ active, children }) => {
  const theme = useTheme()
  return (
    <div>
      {children}
      <style jsx>{`
        div {
          padding-top: 56px;
          padding-bottom: 64px;
          background: ${theme.palette.background};
          bottom: 128px;
          overflow-x: hidden;
          overflow-y: auto;
          position: absolute;
          right: 0;
          top: 0;
          transition: left 0.25s, opacity 0.25s, visibility 0.25s;
          transition-timing-function: cubic-bezier(0.5, 0.2, 0.2, 0.5);
          width: 100%;

          left: ${active ? 0 : '20%'};
          opacity: ${active ? 1 : 0};
          visibility: ${active ? 'visibile' : 'hidden'};
        }

        @media (min-width: ${theme.layout.breakpointMobile}) {
          div {
            padding-top: 32px;
            padding-bottom: 64px;
            border-top: 1px solid ${theme.palette.border};
            left: 0;
            bottom: 92px;
            min-height: 402px;
            overflow: hidden;
            top: 64px;
            transition: none;
            z-index: 2;
          }
        }
        @media (min-width: ${theme.layout.breakpointTablet}) {
          div {
            padding-bottom: 64px;
          }
        }
      `}</style>
    </div>
  )
}
const Breadcrumb: React.FC<React.PropsWithChildren<{ onClick: () => void; active?: boolean }>> = ({
  active,
  onClick,
  children
}) => {
  const theme = useTheme()
  return (
    <div onClick={onClick}>
      {children}
      <style jsx>{`
        div {
          display: flex;
          align-items: center;
          position: fixed;
          top: 63px;
          left: ${active ? 0 : '20%'};
          width: 100%;
          margin-bottom: 16px;
          background: ${theme.palette.background};
          border-bottom: 1px solid ${theme.palette.border};
          padding: 6px 20px 20px 20px;
          cursor: pointer;
          z-index: 1;
          transition: left 0.2s cubic-bezier(0.5, 0.2, 0.2, 0.5);
        }

        @media (min-width: ${theme.layout.breakpointMobile}) {
          div {
            display: none;
            padding: 6px 32px 20px 32px;
          }
        }
        div > :global(*:first-child) {
          margin-right: 18px;
          transform: rotate(-90deg);
        }
      `}</style>
    </div>
  )
}

const NavButton: React.FC<
  React.ButtonHTMLAttributes<any> & { active?: boolean; className?: string }
> = ({ active, onClick, className, children }) => {
  const theme = useTheme()
  return (
    <button type="button" className={className} onClick={onClick}>
      {children}
      <style jsx>{`
        button {
          background-color: transparent;
          border-style: none;
          cursor: pointer;
          font: inherit;
          letter-spacing: 0.01em;
          align-items: center;
          display: flex;
          justify-content: space-between;
          padding: 6px 16px;
          width: 100%;
        }

        button:focus:not([keyboard-focus]) {
          outline-width: 0;
        }

        button > :global(svg) {
          height: ${theme.layout.gap};
          width: ${theme.layout.gap};
          transition: transform 0.3s;
          transform: rotate(90deg);
          display: none;
        }

        @media (min-width: ${theme.layout.breakpointMobile}) {
          button {
            padding: 0;
          }
          button > :global(svg) {
            display: block;
            margin: 2px 0 0 8px;
            transform: rotate(${active ? '180deg' : '0'});
          }
        }
      `}</style>
    </button>
  )
}

const Container: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => {
  const theme = useTheme()
  return (
    <div>
      {children}
      <style jsx>{`
        div {
          display: flex;
          margin: 0 auto;
          width: 100%;
          max-width: ${theme.layout.pageWidthWithMargin};
          padding: 0 20px;
        }
        @media (min-width: ${theme.layout.breakpointMobile}) {
          div {
            height: 100%;
            padding: 0 32px;
          }
        }
      `}</style>
    </div>
  )
}

const PanelContent: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => {
  const theme = useTheme()
  return (
    <div className="panel-content">
      {children}
      <style jsx>{`
        div {
          padding-bottom: 32px;
          position: relative;
          width: 100%;
        }

        @media (min-width: ${theme.layout.breakpointMobile}) {
          div {
            display: flex;
            line-height: 2;
            padding: 0;
          }
        }
      `}</style>
    </div>
  )
}

const StyledListElement: React.FC<React.PropsWithChildren<{ className?: string }>> = ({
  className,
  children
}) => {
  const theme = useTheme()

  return (
    <li className={className}>
      {children}
      <style jsx>{`
        li {
          align-items: center;
          display: flex;
          flex-shrink: 0;
          justify-content: space-between;
          font-size: 1.125rem;
          line-height: 2;
          letter-spacing: 0.01em;
          padding: 0 4px;
        }
        @media (min-width: ${theme.layout.breakpointMobile}) {
          li {
            font-size: initial;
            line-height: initial;
            letter-spacing: initial;
            border: none;
            height: 100%;
            padding: 0;
          }
          li + li {
            margin-left: 32px;
          }
        }
      `}</style>
    </li>
  )
}

interface Props {
  className?: string
  label: string
  icon?: React.ReactNode
  active?: boolean
  onToggle?: (newPanel: string | undefined) => void
  onBreadcrumbClick?: () => void
  promos?: [React.ReactNode]
}

const defaultProps = {
  center: false,
  className: '',
  promos: [] as Array<React.ReactNode>
}

type NativeAttrs = Omit<React.HTMLAttributes<any>, keyof Props>
export type FlyoutMenuProps = Props & typeof defaultProps & NativeAttrs

const FlyoutMenu: React.FC<React.PropsWithChildren<FlyoutMenuProps>> = ({
  children,
  className,
  active,
  icon,
  label,
  onToggle,
  onBreadcrumbClick,
  promos,
  ...props
}) => {
  return (
    <StyledListElement className={className} {...props}>
      <NavButton active={active} className="link" onClick={() => onToggle && onToggle(label)}>
        {label}
        {icon}
      </NavButton>
      <Panel active={active}>
        <Breadcrumb active={active} onClick={() => onBreadcrumbClick && onBreadcrumbClick()}>
          {icon}
          {label}
        </Breadcrumb>
        <Container>
          <PanelContent>{children}</PanelContent>
          {promos && promos.map((promo) => promo)}
        </Container>
      </Panel>
    </StyledListElement>
  )
}

export default withDefaults(FlyoutMenu, defaultProps)
