import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { findDOMNode } from 'react-dom';
import ReactCSSTransitionGroup from 'react-transition-group/CSSTransitionGroup';

export default class MenuDroppoComponent extends Component {
  static propTypes = {
    isOpen: PropTypes.bool.isRequired,
    innerStyle: PropTypes.object,
    children: PropTypes.node.isRequired,
    onClickOutside: PropTypes.func,
    containerClassName: PropTypes.string,
    zIndex: PropTypes.number,
    style: PropTypes.object.isRequired,
    useCssTransition: PropTypes.bool,
    speed: PropTypes.string,
  };

  renderPrimary() {
    const { isOpen } = this.props;
    if (!isOpen) {
      return null;
    }

    const innerStyle = this.props.innerStyle || {};

    return (
      <div className="menu-droppo" key="menu-droppo-drawer" style={innerStyle}>
        {this.props.children}
      </div>
    );
  }

  globalClickOccurred = (event) => {
    const { target } = event;
    // eslint-disable-next-line react/no-find-dom-node
    const container = findDOMNode(this);

    if (
      this.props.isOpen &&
      target !== container &&
      !isDescendant(this.container, event.target) &&
      this.props.onClickOutside
    ) {
      this.props.onClickOutside(event);
    }
  };

  componentDidMount() {
    if (this && document.body) {
      document.body.addEventListener('click', this.globalClickOccurred);
      // eslint-disable-next-line react/no-find-dom-node
      const container = findDOMNode(this);
      this.container = container;
    }
  }

  componentWillUnmount() {
    if (this && document.body) {
      document.body.removeEventListener('click', this.globalClickOccurred);
    }
  }

  render() {
    const { containerClassName = '', style } = this.props;
    const speed = this.props.speed || '300ms';
    const { useCssTransition } = this.props;
    const zIndex = 'zIndex' in this.props ? this.props.zIndex : 0;

    const baseStyle = {
      position: 'fixed',
      ...style,
      zIndex,
    };

    return (
      <div
        style={baseStyle}
        className={`menu-droppo-container ${containerClassName}`}
      >
        <style>
          {`
          .menu-droppo-enter {
            transition: transform ${speed} ease-in-out;
            transform: translateY(-200%);
          }

          .menu-droppo-enter.menu-droppo-enter-active {
            transition: transform ${speed} ease-in-out;
            transform: translateY(0%);
          }

          .menu-droppo-leave {
            transition: transform ${speed} ease-in-out;
            transform: translateY(0%);
          }

          .menu-droppo-leave.menu-droppo-leave-active {
            transition: transform ${speed} ease-in-out;
            transform: translateY(-200%);
          }
        `}
        </style>
        {useCssTransition ? (
          <ReactCSSTransitionGroup
            className="css-transition-group"
            transitionName="menu-droppo"
            transitionEnterTimeout={parseInt(speed, 10)}
            transitionLeaveTimeout={parseInt(speed, 10)}
          >
            {this.renderPrimary()}
          </ReactCSSTransitionGroup>
        ) : (
          this.renderPrimary()
        )}
      </div>
    );
  }
}

function isDescendant(parent, child) {
  let node = child.parentNode;
  while (node !== null) {
    if (node === parent) {
      return true;
    }
    node = node.parentNode;
  }

  return false;
}