import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import omit from 'lodash/omit';
import Content from './Content';
import Trigger from './Trigger';
import Item from './Item';
import Separation from './Separation';

import './dropdown.scss';


const propTypes = {
  /** @ignore */
  className: PropTypes.string,
  /** @ignore */
  children: PropTypes.oneOfType([
    PropTypes.func,
    PropTypes.node
  ]),
  variant: PropTypes.string,
  reverse: PropTypes.bool,
  active: PropTypes.bool,
  /** x-small, small, medium, large */
  size: PropTypes.oneOf(['xs', 'sm', 'md', 'lg', 'nav-bar', 'nav-bar-level-2'])
};

const defaultProps = {
  className: undefined,
  children: null,
  variant: 'primary',
  reverse: false,
  active: false,
  itemClassName: '',
  triggerClassName: '',
  contentClassName: '',
  size: 'md'
};


class Dropdown extends Component {

  static componentName = 'Dropdown';
  state = { active: false };


  componentDidMount() {
    document.addEventListener('click', this.handleClickOutside);
  }

  componentWillUnmount() {
    document.removeEventListener('click', this.handleClickOutside);
  }

  setdropDownRef = node => {
    this.dropDownRef = node;
  }

  handleClickOutside = event => {
    if (event) {
      if (this.dropDownRef && !this.dropDownRef.contains(event.target)) {
        this.setState({ isActive: false });
      }
    }
  }

  openPanel = () => {
    this.setState({ isActive: true });
  }

  closePanel = () => {
    this.setState({ isActive: false });
  }

  togglePanel = () => {
    if (!this.state.isActive) {
      this.openPanel();
    } else {
      this.closePanel();
    }
  }

  buildChildren(children) {
    return React.Children.map(children, child => {
      const { variant, size, reverse } = this.props;
      const { isActive } = this.state;
      const triggerActive = isActive || this.props.active;
      if (React.isValidElement(child)) {
        const { type: { componentName } } = child;
        switch (componentName) {
          case 'Trigger':
            return React.cloneElement(child, {
              state: triggerActive ? 'dropdown-opened' : 'dropdown-closed',
              onClick: this.togglePanel,
              variant: variant === 'launcher' ? 'icon' : variant,
              size
            });
          case 'Content':
            return React.cloneElement(child, {
              active: isActive,
              closePanel: this.closePanel,
              variant,
              reverse
            });
          default:
            return child;
        }
      }
      return child;
    });
  }

  render() {
    const { size, children, className, ...props } = this.props;
    const { isActive } = this.state;
    const childrenProps = {
      togglePanel: this.togglePanel,
      openPanel: this.openPanel,
      closePanel: this.closePanel,
      isActive,
      ...props
    };
    return (
      <div
        className={className}
        styleName={classNames('dropdown', size)}
        ref={node => { this.dropDownRef = node; }}
        {...omit(props, ['variant', 'reverse', 'active', 'itemClassName', 'triggerClassName', 'contentClassName'])}
      >
        {typeof children === 'function' ? children(childrenProps) : this.buildChildren(children)}
      </div>
    );
  }
}


Dropdown.propTypes = propTypes;
Dropdown.defaultProps = defaultProps;

Dropdown.Trigger = Trigger;
Dropdown.Content = Content;
Dropdown.Item = Item;
Dropdown.Separation = Separation;

export default Dropdown;
