import React, { useRef, useState, useCallback, useEffect } from "react";
import { CSSTransition } from "react-transition-group";
import flagLookup from "../../../domain/flagLookup";
import styles from "./Dropdown.module.css";

export const Item = ({ value, display, onSelect, children }) => {
  const onClick = () =>
    onSelect(value ?? children, display ?? value ?? children);
  return (
    <div
      tabIndex="0"
      role="menuitem"
      className={styles.item}
      onClick={onClick}
      onKeyDown={({ key }) => {
        if (key === "Enter") {
          onClick();
        }
      }}
    >
      {children ?? display ?? value}
    </div>
  );
};

export const Dropdown = ({ selected, open, onSelect, onClick, children }) => {
  const transitionRef = useRef(null);
  const [displayed, setDisplayed] = useState(null);
  const onSelectCallback = useCallback(
    (value, display) => {
      setDisplayed(display);
      onSelect(value);
    },
    [onSelect]
  );

  useEffect(() => {
    if (selected === undefined) {
      return;
    }

    let found = null;
    React.Children.toArray(children).forEach(element => {
      if (
        React.isValidElement(element) &&
        found === null &&
        element.props.value === selected
      ) {
        const { value, display } = element.props;
        found = display ?? value;
      }
    });
    setDisplayed(found);
  }, [children, selected]);
  return (
    <div className={styles.container}>
      <div
        className={styles.button}
        role="button"
        tabIndex="0"
        onClick={onClick}
        onKeyDown={({ key }) => {
          if (key === "Enter") {
            onClick();
          }
        }}
      >
        {displayed}
      </div>
      <CSSTransition
        nodeRef={transitionRef}
        in={open}
        timeout={200}
        mountOnEnter
        unmountOnExit
        classNames={{
          enter: styles["list-enter"],
          enterActive: styles["list-enter-active"],
          exit: styles["list-exit"],
          exitActive: styles["list-exit-active"],
        }}
      >
        <div className={styles.list} role="menu" ref={transitionRef}>
          {React.Children.toArray(children).map(child =>
            React.cloneElement(child, {
              onSelect: onSelectCallback,
              key: JSON.stringify(child.props.value),
            })
          )}
        </div>
      </CSSTransition>
    </div>
  );
};

export const CountryDropdown = ({
  countryLookup,
  selected,
  onSelect,
  onClick,
  open,
}) => {
  const transitionRef = useRef(null);
  const [search, setSearch] = useState("");
  const found = countryLookup(search) ?? [];
  const onSelectCallback = useCallback(
    code => {
      setSearch("");
      onSelect(code);
    },
    [onSelect]
  );

  return (
    <div className={styles.container}>
      <div
        className={styles.button}
        role="button"
        tabIndex="0"
        onClick={onClick}
        onKeyDown={({ key }) => {
          if (key === "Enter") {
            onClick();
          }
        }}
      >
        {flagLookup(selected)}
      </div>
      <CSSTransition
        nodeRef={transitionRef}
        in={open}
        timeout={200}
        mountOnEnter
        unmountOnExit
        classNames={{
          enter: styles["list-enter"],
          enterActive: styles["list-enter-active"],
          exit: styles["list-exit"],
          exitActive: styles["list-exit-active"],
        }}
      >
        <div className={styles.list} role="menu" ref={transitionRef}>
          <input
            className={styles.search}
            autoFocus
            type="text"
            value={search}
            onChange={({ target }) => setSearch(target.value)}
            onKeyDown={({ key }) => {
              if (key === "Enter") {
                onSelectCallback(found?.[0]?.item?.alpha2);
              } else if (key === "Escape") {
                onSelectCallback(selected);
              }
            }}
          />
          {found.map(({ item: { country, alpha2 } }) => (
            <div
              role="button"
              tabIndex="0"
              key={alpha2}
              className={styles.item}
              onClick={() => onSelectCallback(alpha2)}
              onKeyDown={({ key }) => {
                if (key === "Enter") {
                  onSelectCallback(alpha2);
                }
              }}
            >
              {flagLookup(alpha2)} - {country}
            </div>
          ))}
          <div
            className={styles.item}
            role="menuitem"
            tabIndex="0"
            onClick={() => onSelectCallback(null)}
            onKeyDown={({ key }) => {
              if (key === "Enter") {
                onSelectCallback(null);
              }
            }}
          >
            {flagLookup(null)} - All Countries
          </div>
        </div>
      </CSSTransition>
    </div>
  );
};

export const DropdownGroup = ({ children }) => {
  const [open, setOpen] = useState(null);
  return (
    <>
      {children.map(child =>
        React.cloneElement(child, {
          open: open === child.props.open,
          onClick: () =>
            setOpen(o => (o === child.props.open ? null : child.props.open)),
          onSelect: v => {
            child.props.onSelect(v);
            setOpen(null);
          },
          key: child.props.open,
        })
      )}
    </>
  );
};
