/**
 * @file PopOver
 * @description
 * @author fex
 */

import React from 'react';
import { findDOMNode } from 'react-dom';
import { ClassNamesFn, themeable } from '../theme';
import { camel, preventDefault } from '../utils/helper';
import { Shell } from '../utils/shell';

export interface Offset {
  x: number;
  y: number;
}

export interface PopOverPorps {
  className?: string;
  placement?: string;
  positionTop?: number;
  positionLeft?: number;
  arrowOffsetLeft?: number;
  arrowOffsetTop?: number;
  offset?: ((clip: object, offset: object) => Offset) | Offset;
  style?: { position: string, [key: string]: string };
  overlay?: boolean;
  onHide?: () => void;
  onClick?: (e: React.MouseEvent<any>) => void;
  classPrefix: string;
  classnames: ClassNamesFn;
  [propName: string]: any;
}

interface PopOverState {
  xOffset: number;
  yOffset: number;
}

export class PopOver extends React.PureComponent<PopOverPorps, PopOverState> {
  static defaultProps = {
    className: '',
    offset: {
      x: 0,
      y: 0
    },
    overlay: false,
    placement: 'auto'
  };

  state = {
    xOffset: 0,
    yOffset: 0
  };

  parent: HTMLElement;
  wrapperRef: React.RefObject<HTMLDivElement> = React.createRef();

  componentDidMount() {
    this.mayUpdateOffset();
    const dom = findDOMNode(this) as HTMLElement;
    this.parent = dom.parentNode as HTMLElement;
    this.parent.classList.add('has-popover');

    if (this.wrapperRef && this.wrapperRef.current) {
      // https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget/addEventListener#使用_passive_改善的滚屏性能
      this.wrapperRef.current.addEventListener('touchmove', preventDefault, {
        passive: false,
        capture: false
      });
    }
  }

  componentDidUpdate() {
    this.mayUpdateOffset();
  }

  componentWillUnmount() {
    this.parent && this.parent.classList.remove('has-popover');

    if (this.wrapperRef && this.wrapperRef.current) {
      this.wrapperRef.current.removeEventListener('touchmove', preventDefault);
    }
  }

  mayUpdateOffset() {
    let offset: Offset;
    let getOffset = this.props.offset;
    // 屏幕的宽度
    const bodyClient = document.documentElement.clientWidth
    // 子元素的宽度
    const childWidth = this.wrapperRef.current?.offsetWidth as number
    // 元素左边到浏览器左边的间距
    let parentLeft = this.parent?.getBoundingClientRect().left
    // 元素右边到浏览器左边的间距
    let parentRight = this.parent?.getBoundingClientRect().right
    // 判断是否超出屏幕宽度
    let whether = (childWidth + parentLeft) > bodyClient
    let moveleft = parentRight - parentLeft - childWidth
    if (this.parent?.className.includes("Modal-content")) {
      if (this.props.positionLeft as number > 0) {
        whether = (childWidth + (this.props.positionLeft as number) + parentLeft) > parentRight
        moveleft = parentRight - childWidth - (this.props.positionLeft as number) - parentLeft
      }
    }
    if (getOffset && typeof getOffset === 'function') {
      const { placement, positionTop: y, positionLeft: x } = this.props;

      offset = getOffset(
        (findDOMNode(this) as HTMLElement).getBoundingClientRect(),
        {
          x,
          y,
          placement
        }
      );
    } else {
      offset = getOffset as Offset;
    }

    this.setState({
      xOffset: whether ? moveleft : offset && offset.x ? (offset as Offset).x : 0,
      yOffset: offset && offset.y ? (offset as Offset).y : 0
    });


  }

  render() {
    const {
      placement,
      activePlacement,
      positionTop,
      positionLeft,
      arrowOffsetLeft,
      arrowOffsetTop,
      style,
      children,
      offset,
      overlay,
      onHide,
      classPrefix: ns,
      classnames: cx,
      className,
      multiple,
      ...rest
    } = this.props;
    const { xOffset, yOffset } = this.state;
    let outerStyle: any = {
      display: 'block',
      ...style
    };
    if (this.wrapperRef.current) {
      // 屏幕的宽度
      const bodyClient = document.documentElement.clientWidth
      const clientData = this.wrapperRef.current.getBoundingClientRect()
      const formControlData = this.wrapperRef.current.closest(`.${ns}Form-control`)?.getBoundingClientRect()
      const isOverSize = document.documentElement.clientHeight - formControlData?.bottom! <= clientData.height + 5
      const warpperRect = this.wrapperRef?.current?.closest('[class*="Field--quickEditable"]')?.getBoundingClientRect()
      const isCoverScreen = formControlData?.left! + clientData.width > bodyClient
      const tableActions = this.wrapperRef.current.closest(`.${ns}Table-actions`) || this.wrapperRef.current.closest(`.${ns}Crud-toolbar-item`)
      if(tableActions && this.wrapperRef.current.closest('.has-popover')) {
        const { top, height, left } = this.wrapperRef.current.closest('.has-popover')!.getBoundingClientRect()
        outerStyle = {
          display: 'block',
            ...style,
            position: 'fixed',
            top: top + height,
            left: this.wrapperRef.current.closest(`.${ns}Crud-toolbar-item`) ? left - 140 : left
        }
      } else {
        // 旧壳逻辑 - 估计是因为内核版本问题导致的这个差异
      if (Shell.hasShell() && !(window['AppShell'] as any).openNewWin) {
        if (this.wrapperRef.current.closest(`.ant-modal-body`) || this.wrapperRef.current.closest(`.${ns}Modal-body`)) {

          if (this.props.className?.includes('batchEidtPopOver')) {
            outerStyle = {
              display: 'block',
              ...style,
              position: 'absolute',
              top: (positionTop as number) + yOffset + (positionTop ? positionTop >= 0 ? 5 : -5 : 0),
              left: ((positionLeft as number) < 0 ? xOffset : (positionLeft as number) + xOffset)
            }
          } else {
            outerStyle = {
              ...outerStyle,
              position: 'fixed',
              width: 'unset',
              top: isOverSize ? formControlData?.top! - clientData.height : formControlData?.top! + formControlData?.height!,
              left: formControlData?.left! + (isCoverScreen ? (bodyClient - formControlData?.left! - clientData.width - 32) : 0)
            }
          }
        } else {
          outerStyle = {
            ...outerStyle,
            position: 'fixed',
            width: 'unset',
            top: isOverSize ? formControlData?.top! - clientData.height : formControlData?.top! + formControlData?.height!,
            left: formControlData?.left! + (isCoverScreen ? (bodyClient - formControlData?.left! - clientData.width - 32) : 0)
          }
        }
      } else {
        if (this.wrapperRef.current.closest(`.ant-modal-body`)) {
          if (this.wrapperRef.current.closest(`.row-edit-form`)) {
            outerStyle = {
              ...outerStyle,
              width: 'unset',
              position: 'fixed',
              top: isOverSize ? formControlData?.top! - clientData.height - 55 : formControlData?.top! + formControlData?.height! - 45,
              left: this.wrapperRef.current.closest(`.ant-drawer-body`) ? formControlData?.left! :
                formControlData?.left! - this.wrapperRef.current.closest(`.${ns}Modal-body`)?.getBoundingClientRect().left!,
            };
          } else {
            outerStyle = {
              ...outerStyle,
              width: 'unset',
              position: 'fixed',
              top: isOverSize ? formControlData?.top! - clientData.height : formControlData?.top! + formControlData?.height!,
              left: formControlData?.left! + (isCoverScreen ? (bodyClient - formControlData?.left! - clientData.width - 32) : 0)
            };
          }
        } else if (this.wrapperRef.current.closest(`.${ns}Modal-body`)) {
          const batchEditBtnDom = this.wrapperRef.current.closest(`.${ns}TableCell-batchEditBtn`)?.getBoundingClientRect()
          // 又快速编辑 快速编辑优先
          if (this.wrapperRef?.current?.closest('[class*="Field--quickEditable"]')) {
            outerStyle = {
              ...outerStyle,
              width: 'unset',
              position: 'fixed',
              top: 'unset',
              left: 'unset'
            }
          } else if (this.props.className?.includes('batchEidtPopOver')) {
            outerStyle = {
              display: 'block',
              ...style,
              width: 'unset',
              position: 'fixed',
              top: isOverSize ? batchEditBtnDom?.top! - clientData.height : batchEditBtnDom!.top + batchEditBtnDom?.height!,
              left: batchEditBtnDom?.left! - this.wrapperRef.current.closest(`.${ns}Modal-body`)?.getBoundingClientRect().left!
            }
          } else {
            const modalData = this.wrapperRef.current.closest(`.${ns}Modal`)?.getBoundingClientRect()
            outerStyle = {
              display: 'block',
              ...style,
              width: 'unset',
              position: 'fixed',
              top: multiple ? formControlData?.top! - clientData.height - modalData?.top! - 1 : isOverSize ? formControlData?.top! - clientData.height - modalData?.top! - 1 : formControlData?.top! + formControlData?.height! - modalData?.top!,
              left: formControlData?.left! - this.wrapperRef.current.closest(`.${ns}Modal-body`)?.getBoundingClientRect().left! + (isCoverScreen ? (bodyClient - formControlData?.left! - clientData.width - 32) : 0)
            }
          }
        } else {
          // 又快速编辑 快速编辑优先
          if (this.wrapperRef?.current?.closest('[class*="Field--quickEditable"]')) {
            outerStyle = {
              ...outerStyle,
              position: 'fixed',
              width: 'unset',
              top: (warpperRect?.top || 0) + (warpperRect?.height || 0),
              left: warpperRect?.left! + (isCoverScreen ? (bodyClient - formControlData?.left! - clientData.width - 16) : 0)
            }
          } else
            outerStyle = {
              ...outerStyle,
              position: 'fixed',
              width: 'unset',
              top: isOverSize ? formControlData?.top! - clientData.height : formControlData?.top! + formControlData?.height!,
              left: formControlData?.left! + (isCoverScreen ? (bodyClient - formControlData?.left! - clientData.width - 16) : 0)
            }

        }
      }
      }
    } else {
      outerStyle = {
        display: 'block',
        ...style,
        // Jay 增加间隙，优化样式
        // top: (positionTop as number) + yOffset,
        // left: (positionLeft as number) + xOffset,
        top: (positionTop as number) + yOffset + (positionTop ? positionTop >= 0 ? 5 : -5 : 0),
        left: ((positionLeft as number) < 0 ? xOffset : (positionLeft as number) + xOffset)
      };
    }
    if (outerStyle.position === 'fixed' && outerStyle.top < 0) {
      outerStyle = {
        ...outerStyle,
        top: 10
      }
    }
    return (
      <div
        ref={this.wrapperRef}
        className={cx(
          `${ns}PopOver`,
          className,
          `${ns}PopOver--${camel(activePlacement)}`
        )}
        style={outerStyle}
        {...rest}
      >
        {overlay ? (
          <div className={`${ns}PopOver-overlay`} onClick={onHide} />
        ) : null}
        {children}
      </div>
    );
  }
}

export default themeable(PopOver);
