import * as React from 'react'
import { createPortal } from 'react-dom'

import { lock, unlock, clearBodyLocks } from '../../utils/body-scroll-lock'

import {
  Container,
  PanelContainer,
  PanelContentContainer,
} from './index.style'

interface Props {
  show: boolean;
  height?: string;
  /**
   * 弹出内容左右两侧的间距，默认为rem(24)，string，带单位的字符串
   */
  gapWidth?: string;
  isEdit: boolean;
  close: () => any;
  scrollRef?: HTMLElement | undefined;
  children: React.ReactNode;
  background?: {
    topImage?: {
      url: string,
    };
    centerImage?: {
      url: string,
    };
    bottomImage?: {
      url: string,
    };
  };
  maskBg?: string;
  overflow?: 'visible' | 'hidden';
}
export interface State {
  panelShow: boolean;
  aniType: 'unfold' | 'fold' | ''
}

let isBodyLocked = false;

class PopupCom extends React.Component<Props, State> {
  constructor(props: Props) {
    super(props);
    this.randomId = 'PopupCom_' + Math.random(); 
  }

  state: State = {
    aniType: '',
    panelShow: false,
  }

  randomId: string;

  panelContent: HTMLElement;

  currentScroller: HTMLElement;

  componentWillReceiveProps(nextProps: Props) {
    if (this.state.panelShow && nextProps.scrollRef && nextProps.scrollRef !== this.props.scrollRef) {
      this.updateLock(nextProps.scrollRef);
    }
  }

  updateLock = (scroller: HTMLElement) => {
    this.unlock();
    this.lock(scroller);
  }

  lock = (scoller?: HTMLElement) => {
    if (this.props.isEdit) {
      return;
    }
    if (isBodyLocked) {
      // console.log('Body alread has lock, unlock first.');
      clearBodyLocks();
    }
    this.currentScroller = scoller || this.props.scrollRef || this.panelContent;
    // console.log('lock', this.currentScroller);
    isBodyLocked = true;
    lock(this.currentScroller)
  }

  unlock = () => {
    if (this.props.isEdit || !this.currentScroller) {
      return;
    }
    // console.log('unlock', this.randomId, this.currentScroller);
    isBodyLocked = false;
    unlock(this.currentScroller);
  }

  componentDidMount() {
    if (this.props.show) {
      this.lock();
      this.setState({
        panelShow: true
      })
      setTimeout(() => {
        this.setState({
          aniType: 'unfold'
        })
      }, 10)
    } else {
      this.unlock()
      this.setState({
        aniType: 'fold'
      })
      setTimeout(() => {
        this.setState({
          panelShow: false
        })
      }, 300)
    }
  }

  componentDidUpdate(preProps: any) {
    // console.log('prepProps', preProps, this.props);
    const { show: prevShow } = preProps;
    const { show: currentShow } = this.props;
    if (prevShow !== currentShow) {
      if (currentShow === false) {
        this.unlock();
        this.setState({
          aniType: 'fold'
        })
        setTimeout(() => {
          this.setState({
            panelShow: false
          })
        }, 300)
      } 
      if (currentShow === true) {
        this.lock();
        this.setState({
          panelShow: true
        })
        setTimeout(() => {
          this.setState({
            aniType: 'unfold'
          })
        }, 10)
      }
    }
  }


  handleClosePanel = (e: React.MouseEvent<HTMLDivElement>) => {
    // @ts-ignore
    if (e.target.getAttribute('id') === this.randomId) {
      this.props.close()
    }
  }

  render() {
    const {
      children,
      height,
      gapWidth,
      isEdit,
      background,
      overflow,
      maskBg,
    } = this.props
    const {
      aniType,
      panelShow
    } = this.state
    return (
      createPortal((
        <Container
          isEdit={isEdit}
          show={panelShow}
          onClick={this.handleClosePanel}
          id={this.randomId}
          bg={maskBg}
          className={
            `${
              aniType === 'unfold'
                ? 'unfold-con'
                : ''
            }`
          }
        >
          <PanelContainer 
            aniType={aniType}
            height={height}
            background={background}
            gapWidth={gapWidth}
            overflow={overflow}
            className={
              `${
                aniType === 'unfold'
                  ? 'unfold-panel'
                  : ''
              }`
            }
          >
            <PanelContentContainer overflow={overflow} ref={ref => this.panelContent = ref}>
              {children}
            </PanelContentContainer>
          </PanelContainer>
        </Container>
      ), isEdit && document.getElementById('viewport') ? document.getElementById('viewport') : document.getElementById('app')!)
    )
  }
}

const Popup = React.memo(PopupCom);
export {
  Popup
}