// @flow
import React from 'react';
import cn from 'classnames';
// import { Scrollbars } from 'react-custom-scrollbars';

import SelectPanel from './selectPanel';
// import { Scroll } from '..';

/* eslint-env browser */
/** Props, передаваемые в Dropdown
  * @property {Object} children - элементы, которые будут отображаться в хедере
  * (выбранные элементы)
  * @property {Object} contentProps - Props, которые не используются в этом компоненте
  * и которые нужно прокинуть дальше (в компонент SelectPanel)
  * @property {boolean} shouldToggleOnHover - если true, то список с выбором будет открываться
  * при наведении курсора мышки на элемент (по умолчанию открывается после клика)
  */
type DropdownProps = {
  children?: Object,
  contentProps: Object,
  shouldToggleOnHover?: boolean
};
/** State компонента Dropdown
  * @property {boolean} expanded - "раскрыт" или нет список с выбором
  * @property {boolean} panelIsDown - направление открытия выпадающего списка, по умолчанию вниз
  */
type DropdownState = {
  expanded: boolean,
  panelIsDown: boolean,
};
/** Компонент Dropdown - выводит список выбранных элементов и отображает панель выбора */
export default class Dropdown extends React.Component<DropdownProps, DropdownState> {
  state = {
    expanded: false,
    panelIsDown: true,
  }

  wrapper: ?Object

  componentDidMount() {
    document.addEventListener('touchstart', this.handleDocumentClick);
    document.addEventListener('mousedown', this.handleDocumentClick);
  }

  componentWillUnmount() {
    document.removeEventListener('touchstart', this.handleDocumentClick);
    document.removeEventListener('mousedown', this.handleDocumentClick);
  }

  handleDocumentClick = (event: Event) => {
    const { contentProps: { keyboardRef } } = this.props;
    if (!this.state.expanded) {
      return;
    }
    const notDropdown = this.wrapper && !this.wrapper?.contains(event.target);
    const notKeyboard = keyboardRef ? !keyboardRef?.contains(event.target) : true;
    if (notDropdown && notKeyboard) {
      this.setState({ expanded: false });
    }
  }

  handleMouseEnter = () => {
    this.handleHover(true);
  }

  handleMouseLeave = () => {
    this.handleHover(false);
  }

  handleHover = (toggleExpanded: boolean) => {
    const { shouldToggleOnHover } = this.props;

    if (shouldToggleOnHover) {
      this.toggleExpanded(toggleExpanded);
    }
  }

  handleHeadingClick = (e) => {
    const { contentProps: { selected, options, isMulti } } = this.props;
    const noneSelected = selected.length === 0;
    const allSelected = selected.length === options.length;

    if (!isMulti) {
      this.toggleExpanded();
      return;
    }

    if (this.heading === e.target || noneSelected || allSelected) {
      this.toggleExpanded();
      return;
    }
  }

  toggleExpanded = (value: ?boolean) => {
    const { expanded } = this.state;

    const newExpanded = value === undefined ? !expanded : !!value;

    this.setState({ expanded: newExpanded });

    if (!newExpanded && this.wrapper) {
      this.wrapper.focus();
    }
  }

  getDirection = (coords: Object) => {
    const panelBottomCoordinates = coords.top + coords.height;
    const windowHeight = document.documentElement ? document.documentElement.clientHeight : 0;

    if (panelBottomCoordinates > windowHeight && coords.top - coords.height > 0) {
      this.setState({ panelIsDown: false });
    } else {
      this.setState({ panelIsDown: true });
    }
  };

  resetStatePanel = () => {
    this.setState({ panelIsDown: true });
  }

  renderPanel() {
    const { contentProps } = this.props;
    const classes = cn({
      'omni-select__dropdown-content': true,
      'omni-select__dropdown-content_bottom': this.state.panelIsDown,
      'omni-select__dropdown-content_top': !this.state.panelIsDown,
    });

    return (
      <div className={classes}>
        <SelectPanel {...contentProps}
          getDirection={this.getDirection}
          toggleExpanded={this.toggleExpanded}
          resetState={this.resetStatePanel}
          panelIsDown={this.state.panelIsDown}
        />
      </div>
    );
  }

  render() {
    const { expanded } = this.state;
    const { children, contentProps: { state } } = this.props;
    const headingClasses = cn({
      'omni-select__dropdown-heading': true,
      [`omni-select_${state}`]: !!state,
    });
    return (
      <div
        className="omni-select__dropdown"
        role="combobox"
        onMouseEnter={this.handleMouseEnter}
        onMouseLeave={this.handleMouseLeave}
        // eslint-disable-next-line no-return-assigg
        ref={ref => this.wrapper = ref}
      >
        <div
          className={headingClasses}
          onClick={this.handleHeadingClick}
        >
            <span
              className="omni-select__dropdown-heading-value"
              ref={ref => this.heading = ref}
            >
                {children}
            </span>
            <span
              className="omni-select__dropdown-arrow"
              onClick={() => this.toggleExpanded(!expanded)}
            >
              <span className={expanded ? 'omni-select__dropdown-arrow_up' : 'omni-select__dropdown-arrow_down'}/>
            </span>
        </div>
        {expanded && this.renderPanel()}
      </div>
    );
  }
}
