import React, { useEffect, useMemo, useState } from 'react'
import useTheme from '../use-theme'
import withDefaults from '../utils/with-defaults'
import { setChildrenProps } from '../utils/collections'
import TreeLeaf from './tree-leaf'
import Expand from '../shared/expand'
import TreeIndents from './tree-indents'
import { useTreeContext } from './tree-context'
import TreeFolderIcon from './tree-folder-icon'
import TreeStatusIcon from './tree-status-icon'
import { sortChildren, makeLeafPath, stopPropagation } from './tree-help'

interface Props {
  name: string
  extra?: string
  parentPath?: string
  level?: number
  className?: string
}

const defaultProps = {
  level: 0,
  className: '',
  parentPath: ''
}

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

const TreeFolder: React.FC<React.PropsWithChildren<TreeFolderProps>> = ({
  name,
  children,
  parentPath,
  level: parentLevel,
  extra,
  className,
  ...props
}) => {
  const theme = useTheme()
  const { initialExpand, isImperative } = useTreeContext()
  const [expanded, setExpanded] = useState<boolean>(initialExpand)

  // eslint-disable-next-line react-hooks/exhaustive-deps
  useEffect(() => setExpanded(initialExpand), []) // only set once

  const currentPath = useMemo(() => makeLeafPath(name, parentPath), [])

  const nextLeafs = setChildrenProps(
    children,
    {
      parentPath: currentPath,
      level: parentLevel + 1
    },
    [TreeFolder, TreeLeaf]
  )
  const { onNodeClick } = useTreeContext()
  const clickHandler = (event: React.MouseEvent) => {
    setExpanded(!expanded)
    if (onNodeClick) {
      stopPropagation(event)
      onNodeClick(currentPath)
    }
  }

  const sortedLeafs = isImperative ? nextLeafs : sortChildren(nextLeafs, TreeFolder)

  return (
    <div className={`folder ${className}`} onClick={clickHandler} {...props}>
      <div className="names">
        <TreeIndents count={parentLevel} />
        <span className="status">
          <TreeStatusIcon active={expanded} />
        </span>
        <span className="icon">
          <TreeFolderIcon />
        </span>
        <span className="name">
          {name}
          {extra && <span className="extra">{extra}</span>}
        </span>
      </div>
      <Expand isExpanded={expanded}>
        <div className="content" onClick={stopPropagation}>
          {sortedLeafs}
        </div>
      </Expand>

      <style jsx>{`
        .folder {
          cursor: pointer;
          line-height: 1;
          user-select: none;
        }

        .folder:hover .name,
        .folder:hover .icon :global(> svg) {
          color: ${theme.palette.brand.primary[11]};
          stroke: ${theme.palette.brand.primary[11]};
        }

        .names {
          display: flex;
          height: 1.75rem;
          align-items: center;
          margin-left: calc(1.375rem * ${parentLevel});
          position: relative;
        }

        .names > :global(.indent) {
          position: absolute;
          top: 50%;
          transform: translateY(-50%);
          width: 1px;
          height: 100%;
          margin-left: -1px;
        }

        .status {
          position: absolute;
          left: calc(-0.575rem);
          top: 50%;
          transform: translate(-50%, -50%);
          width: 0.875rem;
          height: 0.875rem;
          z-index: 10;
          background-color: ${theme.palette.background};
        }

        .icon {
          width: 1.5rem;
          height: 100%;
          margin-right: 0.125rem;
        }

        .status,
        .icon {
          display: inline-flex;
          align-items: center;
          justify-content: center;
        }

        .name {
          transition: opacity 100ms ease 0ms;
          color: ${theme.palette.accents_12};
          white-space: nowrap;
          font-size: 0.875rem;
        }

        .extra {
          font-size: 0.75rem;
          align-self: baseline;
          padding-left: 4px;
          color: ${theme.palette.accents_10};
        }

        .name:hover {
          opacity: 0.7;
        }

        .content {
          display: flex;
          flex-direction: column;
          height: auto;
        }
      `}</style>
    </div>
  )
}

export default withDefaults(TreeFolder, defaultProps)
