import React from 'react';
import { bool, string, number, arrayOf, func, node, shape } from 'prop-types';
import styled from 'styled-components';
import classNames from 'classnames';
import { REM_UNIT_MD, REM_UNIT_LG } from '@vincent_za/styles';
import { PROP_ASYNC_STATUS, SHAPE_ASYNC_STATUS_INITIAL, throttle } from '@vincent_za/utils';
import TooltipWrap from '../TooltipWrap/container';
import { MODAL_CLASSNAME_TRIGGER_TEMPLATE_ACTIVE } from './constants';
import Modal from './Modal/component';

export const ModalContentFooter = styled.footer`
  display: flex;
  margin-top: ${REM_UNIT_LG};
`;

export const ModalContentTitle = styled.div`
  display: ${props => props.isHidden ? 'none' : 'flex'};
  padding: ${REM_UNIT_MD} 0;

  & + ${ModalContentFooter} {
    padding-bottom: 0;
  }
`;

const TriggerTemplateWrap = styled.div`
  outline: none;
`;

class ModalWrap extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      position: {
        xPos: 0,
        yPos: 0,
      },
    };
    this.throttledResize = throttle(100)(this.onResize);
  }

  componentDidMount() {
    this.updateCoordinates();
    window.addEventListener('resize', this.throttledResize);
  }

  shouldComponentUpdate(nextProps, nextState) {
    if (nextState.position !== this.state.position) return true;
    if (nextProps.activeModalIds !== this.props.activeModalIds) return true;
    if (nextProps.activeOverlayModalIds !== this.props.activeOverlayModalIds) return true;
    if (nextProps.children !== this.props.children) return true;
    if (nextProps.customStyles !== this.props.customStyles) return true;
    if (nextProps.id !== this.props.id) return true;
    if (nextProps.offset !== this.props.offset) return true;
    if (nextProps.title !== this.props.title) return true;
    if (nextProps.asyncStatus !== this.props.asyncStatus) return true;
    return false;
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.throttledResize);
  }

  onResize = () => this.updateCoordinates();

  onClick = (event) => {
    const { hasOverlay, onOverlayToggle, id } = this.props;
    onOverlayToggle({ event, id, hasOverlay, showOverlay: true });
  }

  updateCoordinates = () => {
    const { isRootEl } = this.props;
    const clientRect = this.modalRef.getBoundingClientRect();

    return this.setState({
      position: {
        xPos: isRootEl ? clientRect.x + this.props.offset.x : 0,
        yPos: isRootEl ? clientRect.y + this.props.offset.y : 0,
      },
    });
  }

  addModalRef = (el) => { this.modalRef = el; };

  render() {
    const {
      isTouchDevice,
      activeModalIds,
      activeOverlayModalIds,
      children,
      className,
      customStyles,
      grid,
      id,
      isDraggable,
      isResizable,
      isCentered,
      isFixed,
      hasOverlay,
      isRightAligned,
      isNoContentSpacing,
      isNoContentHorizontalSpacing,
      width,
      height,
      onOverlayToggle,
      portalSelector,
      title,
      tooltipLabel,
      tooltipPosition,
      triggerTemplate,
    } = this.props;

    const isModalActive = activeOverlayModalIds.includes(id) || activeModalIds.includes(id);
    return (
      <div className={className}>
        {
          !tooltipLabel ?
            <TriggerTemplateWrap
              className={classNames({ [MODAL_CLASSNAME_TRIGGER_TEMPLATE_ACTIVE]: isModalActive })}
              onClick={this.onClick}
              ref={this.addModalRef}
            >
              {triggerTemplate}
            </TriggerTemplateWrap> :
            <TooltipWrap isDisabled={isModalActive || !tooltipLabel} position={tooltipPosition} tooltip={tooltipLabel}>
              <TriggerTemplateWrap
                className={classNames({ [MODAL_CLASSNAME_TRIGGER_TEMPLATE_ACTIVE]: isModalActive })}
                onClick={this.onClick}
                ref={this.addModalRef}
              >
                {triggerTemplate}
              </TriggerTemplateWrap>
            </TooltipWrap>
        }
        <Modal
          isTouchDevice={isTouchDevice}
          isModalActive={isModalActive}
          isCentered={isCentered}
          activeModalIds={activeModalIds}
          activeOverlayModalIds={activeOverlayModalIds}
          customStyles={customStyles}
          grid={grid}
          id={id}
          isDraggable={isDraggable}
          isResizable={isResizable}
          isFixed={isFixed}
          hasOverlay={hasOverlay}
          isRightAligned={isRightAligned}
          isNoContentSpacing={isNoContentSpacing}
          isNoContentHorizontalSpacing={isNoContentHorizontalSpacing}
          width={width}
          height={height}
          onOverlayToggle={onOverlayToggle}
          portalSelector={portalSelector}
          title={title}
          {...this.state}
        >
          {children}
        </Modal>
      </div>
    );
  }
}

ModalWrap.propTypes = {
  isTouchDevice: bool.isRequired,
  isRightAligned: bool,
  isCentered: bool,
  isDraggable: bool,
  isResizable: bool,
  isNoContentSpacing: bool,
  isNoContentHorizontalSpacing: bool,
  isRootEl: bool,
  isFixed: bool,
  hasOverlay: bool,
  width: number,
  height: number,
  title: string.isRequired,
  activeOverlayModalIds: arrayOf(string).isRequired,
  // offset: shape(PROP_OFFSET),
  activeModalIds: arrayOf(string),
  triggerTemplate: node.isRequired,
  tooltipLabel: string,
  tooltipPosition: string,
  id: string.isRequired,
  grid: arrayOf(number),
  onOverlayToggle: func.isRequired,
  className: string,
  portalSelector: string,
  customStyles: string,
  children: node.isRequired,
  asyncStatus: shape(PROP_ASYNC_STATUS),
};

ModalWrap.defaultProps = {
  isRightAligned: false,
  isCentered: false,
  isDraggable: false,
  isResizable: false,
  hasOverlay: false,
  isRootEl: false,
  isFixed: false,
  isNoContentSpacing: false,
  isNoContentHorizontalSpacing: false,
  width: undefined,
  height: undefined,
  offset: {
    x: 0,
    y: 0,
  },
  activeModalIds: undefined,
  grid: undefined,
  tooltipLabel: '',
  tooltipPosition: 'right',
  portalSelector: undefined,
  customStyles: undefined,
  className: undefined,
  asyncStatus: SHAPE_ASYNC_STATUS_INITIAL,
};

export default ModalWrap;
