/**
 * Created by baoyinghai on 5/26/17.
 */
import React from 'react';
import { BIT, COLUMN_COUNT, LINE_COUNT } from '../constant';
import { calculateStyle, createShadow } from './common';
import { isOccupy } from '../components/DashBoard/board';

export default Comp => {

  class MoveAble extends React.Component {

    constructor(props) {
      super(props);
      this.refStr = 'dash-board-move-able-'  + this.props.index + '-' + new Date().getTime();
    }

    _rmPX = str => {
      if (str && str.length > 2 && str.endsWith('px')) {
        return parseInt(str.substring(0, str.length - 2), 10);
      }
      return 0;
    };

    addBodyClass = () => {
      const body = document.querySelector('body');
      this.userSelect = body.style.userSelect;
      body.style.userSelect = 'none';
    };

    removeBodyClass = () => {
      const body = document.querySelector('body');
      body.style.userSelect = this.userSelect;
    };

    render() {
      const { layout, updateLayout, index, calculateHitBitBeside } = this.props;
      const style = calculateStyle(layout);
      const event = {
        onMouseDown: e => {
          e.stopPropagation();
          this.addBodyClass();
          const hitArr = calculateHitBitBeside(index);
          const startClientX = e.clientX;
          const startClientY = e.clientY;
          const wrapper = document.querySelector('.' + this.refStr + '.move-container');
          const cloneWrapper = createShadow(style);
          wrapper.parentNode.appendChild(cloneWrapper);
          const left = this._rmPX(wrapper.style.left);
          const top = this._rmPX(wrapper.style.top);
          wrapper.style.zIndex = 10;
          this.offsetX = 0;
          this.offsetY = 0;
          this.tempOffsetX = 0;
          this.tempOffsetY = 0;
          this.xFn = Math.floor;
          this.yFn = Math.floor;
          const mouseMoveHandler = moveEvent => {
            moveEvent.stopPropagation();
            let changeLeft = true;
            let changeTop = true;
            this.isMove = true;
            const newLeft = left + (moveEvent.clientX - startClientX);
            const newTop = top + (moveEvent.clientY - startClientY);
            if (newLeft < 0 || newLeft > (COLUMN_COUNT - layout.width) * BIT) {
              changeLeft = false;
            }
            if (newTop < 0 || newTop > (LINE_COUNT - layout.height) * BIT) {
              changeTop = false;
            }
            if (changeLeft) {
              const oldLeft = this._rmPX(wrapper.style.left);
              if (newLeft < oldLeft - 2) {
                this.xFn = Math.floor;
              }
              if (newLeft > oldLeft + 2) {
                this.xFn = Math.ceil;
              }
              wrapper.style.left = newLeft + 'px';
              this.tempOffsetX = this.xFn((moveEvent.clientX - startClientX) / BIT);
            }
            if (changeTop) {
              const oldTop = this._rmPX(wrapper.style.top);
              if (newTop < oldTop - 2) {
                this.yFn = Math.floor;
              }
              if (newTop > oldTop + 2) {
                this.yFn = Math.ceil;
              }
              wrapper.style.top = newTop + 'px';
              this.tempOffsetY = this.yFn((moveEvent.clientY - startClientY) / BIT);
            }
            if (!isOccupy(layout.x + this.tempOffsetX, layout.y + this.tempOffsetY, layout.width, layout.height, hitArr)) {
              if (this.tempOffsetX !== this.offsetX) {
                this.offsetX = this.tempOffsetX;
                cloneWrapper.style.left = this.offsetX * BIT + left + 'px';
              }
              if (this.tempOffsetY !== this.offsetY) {
                this.offsetY = this.tempOffsetY;
                cloneWrapper.style.top = this.offsetY * BIT + top + 'px';
              }
            }
          };

          const mouseUpHandler = upEvent => {
            console.log('upper');
            upEvent.stopPropagation();
            this.removeBodyClass();
            wrapper.style.zIndex = 0;
            wrapper.parentNode.removeChild(cloneWrapper);
            window.removeEventListener('mousemove', mouseMoveHandler);
            window.removeEventListener('mouseup', mouseUpHandler);
            if (this.isMove) {
              updateLayout(index, {...layout, x: layout.x + this.offsetX, y: layout.y + this.offsetY});
              this.isMove = false;
              this.offsetX = 0;
              this.offsetY = 0;
            }
          };

          window.addEventListener('mousemove', mouseMoveHandler);
          window.addEventListener('mouseup', mouseUpHandler);
        }
      };
      return (
        <div {...event} className={this.refStr + " move-container"} style={style} >
          <Comp refStr={this.refStr} {...this.props} moveAble={true} moveStyle={style} />
        </div>
      );
    }
  };

  return MoveAble;
};