import React, { useState, useEffect, useRef } from 'react';

import Icon from '../Icon';
import Divider from '../Divider';
import ClickAwayListener from '../ClickAwayListener';

import {
  Container,
  Selected,
  Content,
  InputContent,
  OptionWrapper,
  Option,
} from './styled';

type Props = {
  onChange?: (item: SelectOptionType) => void;
  options: SelectOptionType[];
  defaultValue?: React.ReactNode;
  isDivide?: boolean;
  useInput?: boolean;
  style?: Record<string, string>;
};

const SelectBox: React.FC<Props> = ({
  onChange,
  options,
  defaultValue,
  isDivide,
  useInput,
  style,
}: Props) => {
  const selectRef = useRef<HTMLDivElement>(null);
  const optionRef = useRef<HTMLDivElement>(null);
  const [isCollapse, setCollapse] = useState(true);
  const [value, setValue] = useState(defaultValue);

  const handleClick = (): void => {
    setCollapse(!isCollapse);
  };

  const handleSelect = (index: number): void => {
    setValue(options[index].content);
    handleBlur();

    if (onChange) {
      onChange(options[index]);
    }
  };

  const handleBlur = (): void => {
    setCollapse(true);
  };

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>): void => {
    setValue(e.target.value || 0);
  };

  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>): void => {
    if (e.keyCode === 13 && onChange && value) {
      const param = {
        key: '',
        content: '',
        child: parseInt(value as string, 10),
      };
      onChange(param);
      setCollapse(true);
    }
  };

  useEffect(() => {
    if (defaultValue) {
      setValue(defaultValue);
    } else {
      setValue(options[0].content);
    }
  }, [defaultValue]);

  useEffect(() => {
    if (!isCollapse && selectRef.current) {
      const position = selectRef.current.getBoundingClientRect();
      if (optionRef.current) {
        optionRef.current.style.top = `${
          selectRef.current.clientHeight + position.top
        }px`;
        optionRef.current.style.left = `${position.left}px`;
      }
    }
  });

  return (
    <ClickAwayListener onClick={handleBlur}>
      <Container style={style}>
        <Selected
          ref={selectRef}
          onMouseDown={handleClick}
          onBlur={handleBlur}
          tabIndex={0}
          data-testid="selected"
        >
          {useInput &&
          (typeof value === 'string' || typeof value === 'number') ? (
            <InputContent
              value={value}
              onChange={handleChange}
              onKeyDown={handleKeyDown}
            />
          ) : (
            <Content>{value}</Content>
          )}
          {isDivide ? <Divider /> : null}
          <Icon glyph="down-arrow" />
        </Selected>
        {!isCollapse ? (
          <OptionWrapper ref={optionRef} data-testid="option-list">
            {options.map((option: SelectOptionType, index: number) => (
              <Option
                key={option.key}
                onMouseDown={(): void => {
                  handleSelect(index);
                }}
              >
                {option.content}
              </Option>
            ))}
          </OptionWrapper>
        ) : null}
      </Container>
    </ClickAwayListener>
  );
};

SelectBox.defaultProps = {
  isDivide: false,
  useInput: false,
  style: {},
  defaultValue: '',
};

export default SelectBox;
