import React, {
  FC,
  MutableRefObject,
  useEffect,
  useRef,
  useState,
} from 'react';
import classNames from 'classnames';

import css from './index.module.css';
import { getModifier } from '../../helpers/getModifier';
import { Link } from '../../index';

export interface DropdownListOptions {
  [key: string]: DropdownListOption;
}

export interface DropdownListOption {
  value: string;
  name: string;
  url: string;
}

export interface DropdownListProps {
  options: DropdownListOptions;
  value?: string;
  type?: 'normal' | 'filled' | 'category';
  onChange?: (val: string) => void;
  category?: string;
}

const DropdownList: FC<DropdownListProps> = ({
  options,
  value,
  type = 'normal',
  onChange,
  category,
}) => {
  const [showPanel, togglePanel] = useState(false);
  // Define type, otherwise  Typescript throws error
  const dropdown: MutableRefObject<HTMLDivElement> = useRef();

  // Close dropdown when clicked outside
  const handleClick = (e): void => {
    if (dropdown.current && dropdown.current.contains(e.target)) {
      if (
        !(
          e.target instanceof HTMLUListElement ||
          e.target instanceof HTMLSpanElement
        )
      ) {
        return;
      }
      togglePanel(prevState => !prevState);
      return;
    }
    togglePanel(false);
  };

  useEffect(() => {
    // add when mounted
    document.addEventListener('mousedown', handleClick);

    // return function to be called when unmounted
    return (): void => {
      document.removeEventListener('mousedown', handleClick);
    };
  }, []);

  const dropdownClassNames = classNames(css.dropdown, {
    [`${css[`dropdown${getModifier(type)}`]}`]: type,
  });

  return (
    <div className={dropdownClassNames} data-testid="Dropdown" ref={dropdown}>
      <div
        className={classNames(css.dropdown__wrapper, {
          [`${css.dropdown__wrapper__open}`]: showPanel,
        })}
      >
        <ul className={css.dropdown__select}>
          <span className={css.dropdown__label}>
            {options[value]
              ? `${type === 'category' ? `${category}: ` : ''} ${
                  options[value].name
                }`
              : ''}
          </span>
          {showPanel &&
            options &&
            Object.keys(options).map(key => {
              return options[key].value != value ? (
                <li
                  key={options[key].value}
                  value={options[key].value}
                  className={css.dropdown__list}
                  onClick={(event): void => {
                    event.stopPropagation();
                    if (onChange) {
                      togglePanel(false);
                      onChange(options[key].value);
                    }
                  }}
                >
                  {type === 'category' && <>{options[key].name}</>}

                  {type !== 'category' && (
                    <Link
                      className={css.dropdown__link}
                      to={options[key].url}
                      variant="normal"
                    >
                      {options[key].name}
                    </Link>
                  )}
                </li>
              ) : null;
            })}
        </ul>
      </div>
    </div>
  );
};

export default DropdownList;
