import React, { Component } from 'react';
import './index.less';

export default class Drag extends Component {
  constructor(props) {
    super(props);
    this.moving = false;
    this.Drag = null;
    this.initPosition = this.props.x !== undefined || this.props.y !== undefined;
    this.resetX = this.x = this.props.x || 0;
    this.resetY = this.y = this.props.y || 0;
  }

  componentWillMount() {
    this.init();
  }

  componentWillUnmount() {}

  init() {
    if (this.Drag) {
      this.load();
      if (!this.initPosition) this.poisition();
      if (this.props.onInit) this.props.onInit();
    } else {
      setTimeout(() => {
        this.init();
      }, 1);
    }
  }

  poisition() {
    this.resetX = this.x = this.Drag.parentElement.offsetLeft;
    this.resetY = this.y = this.Drag.parentElement.offsetTop;
    this.updatePoisition();
  }

  load() {
    this.Drag.addEventListener('mousedown', this.onMouseDown.bind(this), false);
    window.addEventListener('mouseup', this.onMouseUp.bind(this), false);
    window.addEventListener('mousemove', this.onMouseMove.bind(this), false);
  }

  unload() {
    window.removeEventListener('mouseup', this.onMouseUp.bind(this), false);
    window.removeEventListener('mousemove', this.onMouseMove.bind(this), false);
  }

  onMouseDown(e) {
    if (!this.moving) {
      this.moving = true;
      e.stopPropagation();
      if (this.props.onMoveStart) this.props.onMoveStart({ x: this.x, y: this.y }, e);
    }
  }

  onMouseUp(e) {
    if (this.moving) {
      let reset = false;
      this.moving = false;
      if (this.props.onMoveEnd) reset = this.props.onMoveEnd({ x: this.x, y: this.y }, e) === false;
      if (reset) {
        this.x = this.resetX;
        this.y = this.resetY;
        this.updatePoisition();
      }
      e.stopPropagation();
    }
  }

  onMouseMove(e) {
    if (this.moving) {
      const { scale = 1 } = this.props;
      this.x += e.movementX / scale;
      this.y += e.movementY / scale;
      this.updatePoisition();
      e.stopPropagation();
    }
  }

  updatePoisition() {
    this.Drag.style.left = `${this.x}px`;
    this.Drag.style.top = `${this.y}px`;
  }

  render() {
    return (
      <div
        ref={ref => {
          this.Drag = ref;
        }}
        className="drag"
        style={{ left: this.x, top: this.y }}
      >
        {this.props.children}
      </div>
    );
  }
}
