import React, { useState, useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import {
  Wrapper,
  SelectorButton,
  ArrowUp,
  ArrowDown,
  Options,
  Option,
} from './styled';

const useSelectOption = (initialOption, onChange) => {
  const [selectedOption, setSelectedOption] = useState(initialOption);
  const [isOpen, setOpen] = useState(false);
  const selectOption = option => {
    onChange(option);
    setSelectedOption(option);
    setOpen(false);
  };

  return [{ selectedOption, isOpen }, { selectOption, setOpen }];
};

const useCloseOnClickOutside = setOpen => {
  const componentNode = useRef();

  const handleClickOutside = event => {
    if (!componentNode.current.contains(event.target)) {
      setOpen(false);
    }
  };

  useEffect(() => {
    document.addEventListener('mousedown', handleClickOutside);

    return () => document.removeEventListener('mousedown', handleClickOutside);
  }, []);

  return componentNode;
};

const useSelectorBehavior = (initialOption, onChange) => {
  const [
    { selectedOption, isOpen },
    { selectOption, setOpen },
  ] = useSelectOption(initialOption, onChange);

  const componentNode = useCloseOnClickOutside(setOpen);

  return [{ selectedOption, isOpen, componentNode }, { selectOption, setOpen }];
};

const Selector = props => {
  const { options, placeholder, selected, disabled, small, onChange } = props;

  const [
    { selectedOption, isOpen, componentNode },
    { selectOption, setOpen },
  ] = useSelectorBehavior(selected, onChange);

  return (
    <Wrapper small={small} ref={componentNode}>
      <SelectorButton
        value={selectedOption.value}
        isOpen={isOpen}
        {...props}
        onClick={() => setOpen(!isOpen)}
      >
        {selectedOption.label || placeholder}
        <ArrowUp />
        <ArrowDown />
      </SelectorButton>
      {isOpen && !disabled && (
        <Options {...props}>
          {options.map(({ value, label }) => (
            <Option
              key={label}
              value={value}
              onClick={() => selectOption({ value, label })}
            >
              {label}
            </Option>
          ))}
        </Options>
      )}
    </Wrapper>
  );
};

Selector.propTypes = {
  options: PropTypes.array.isRequired,
  selected: PropTypes.object,
  placeholder: PropTypes.string,
  small: PropTypes.bool,
  disabled: PropTypes.bool,
  onChange: PropTypes.func.isRequired,
};

Selector.defaultProps = {
  selected: {},
  placeholder: 'Select',
  small: false,
  disabled: false,
};

Selector.displayName = 'Selector';

export default Selector;
