"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = exports.Rotatable = void 0;

var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));

var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));

var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));

var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));

var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));

var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));

var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));

var _react = _interopRequireDefault(require("react"));

var _propTypes = _interopRequireDefault(require("prop-types"));

var _styles = require("@material-ui/core/styles");

var _anchorUtils = require("./anchor-utils");

var _reactPortal = require("react-portal");

var _pointGeometry = _interopRequireDefault(require("@mapbox/point-geometry"));

var _transformOrigin = require("./transform-origin");

var _classnames = _interopRequireDefault(require("classnames"));

function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2["default"])(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2["default"])(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2["default"])(this, result); }; }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }

var Anchor = (0, _styles.withStyles)({
  anchor: {
    position: 'absolute',
    zIndex: 100,
    width: '200px',
    height: '80px'
  }
})(function (_ref) {
  var classes = _ref.classes,
      left = _ref.left,
      top = _ref.top,
      color = _ref.color,
      fill = _ref.fill;
  color = color || 'green';
  fill = fill || 'white';
  return /*#__PURE__*/_react["default"].createElement(_reactPortal.Portal, null, /*#__PURE__*/_react["default"].createElement("svg", {
    className: classes.anchor,
    style: {
      left: left - 10,
      top: top - 10
    }
  }, /*#__PURE__*/_react["default"].createElement("circle", {
    cx: 10,
    cy: 10,
    r: 8,
    strokeWidth: 1,
    stroke: color,
    fill: fill
  })));
});
/**
 * Tip o' the hat to:
 * https://bl.ocks.org/joyrexus/7207044
 */

var Rotatable = /*#__PURE__*/function (_React$Component) {
  (0, _inherits2["default"])(Rotatable, _React$Component);

  var _super = _createSuper(Rotatable);

  function Rotatable(props) {
    var _this;

    (0, _classCallCheck2["default"])(this, Rotatable);
    _this = _super.call(this, props);
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "initHandles", function () {
      var handle = _this.props.handle;

      if (Array.isArray(handle)) {
        _this.handles = [];
        handle.forEach(function (h) {
          var el = _this.rotatable.querySelector(".".concat(h["class"]));

          if (el) {
            var mousedownHandler = _this.rotateStart(h.origin);

            el.addEventListener('mousedown', mousedownHandler);
            el.addEventListener('mouseup', _this.rotateStop);

            _this.handles.push({
              el: el,
              mousedownHandler: mousedownHandler
            });
          }
        });
      }
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "addMouseUpHandler", function () {
      document.addEventListener('mouseup', _this.rotateStop);
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "originToXY", function (origin) {
      var _this$rotatable = _this.rotatable,
          width = _this$rotatable.clientWidth,
          height = _this$rotatable.clientHeight;
      return (0, _transformOrigin.parse)({
        width: width,
        height: height
      }, origin);
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "getAnchor", function (origin) {
      var rotation = _this.state.rotation;
      var _this$rotatable2 = _this.rotatable,
          clientWidth = _this$rotatable2.clientWidth,
          clientHeight = _this$rotatable2.clientHeight;

      var _this$rotatable$getBo = _this.rotatable.getBoundingClientRect(),
          top = _this$rotatable$getBo.top,
          left = _this$rotatable$getBo.left;

      var xy = _this.originToXY(origin);

      var _calcAnchor = (0, _anchorUtils.getAnchor)({
        width: clientWidth,
        height: clientHeight
      }, xy, rotation),
          anchorTop = _calcAnchor.top,
          anchorLeft = _calcAnchor.left;

      return {
        top: top + anchorTop,
        left: left + anchorLeft
      };
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "rotateStart", function (origin) {
      return function (e) {
        var isRotating = _this.state.isRotating;

        if (isRotating) {
          return;
        }

        e.preventDefault();

        var anchor = _this.getAnchor(origin);

        var rotation = _this.state.rotation;

        var _this$getAngle = _this.getAngle(anchor, e),
            startAngle = _this$getAngle.angle;

        var diff = {
          x: 0,
          y: 0
        };

        if (origin !== _this.state.origin) {
          var _this$rotatable3 = _this.rotatable,
              width = _this$rotatable3.clientWidth,
              height = _this$rotatable3.clientHeight;
          diff = (0, _anchorUtils.distanceBetween)({
            width: width,
            height: height
          }, rotation, _this.state.origin, origin);
        }

        _this.setState({
          origin: origin,
          isRotating: true,
          startAngle: startAngle,
          anchor: anchor,
          position: {
            left: _this.state.position.left + diff.x,
            top: _this.state.position.top + diff.y
          }
        }, function () {
          document.addEventListener('mousemove', _this.rotate);
        });
      };
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "rotateStop", function (e) {
      var isRotating = _this.state.isRotating;

      if (!isRotating) {
        return;
      }

      e.preventDefault();

      _this.setState({
        isRotating: false,
        angle: _this.state.rotation,
        anchor: null,
        current: null
      }, function () {
        document.removeEventListener('mousemove', _this.rotate);
        document.removeEventListener('mousemove', _this.drag);
      });
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "rotate", function (e) {
      var isRotating = _this.state.isRotating;

      if (!isRotating) {
        return;
      }

      e.preventDefault();
      var _this$state = _this.state,
          startAngle = _this$state.startAngle,
          angle = _this$state.angle,
          anchor = _this$state.anchor;

      var _this$getAngle2 = _this.getAngle(anchor, e),
          current = _this$getAngle2.angle,
          x = _this$getAngle2.x,
          y = _this$getAngle2.y;

      var computedAnchor = {
        x: x,
        y: y
      };
      var diff = current - startAngle;
      var rotation = angle + diff;

      _this.setState({
        rotation: rotation,
        diff: diff,
        current: current,
        computedAnchor: computedAnchor
      });
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "mouseDown", function (e) {
      var handle = _this.handles.find(function (h) {
        return h.el === e.target;
      });

      if (!handle) {
        _this.dragStart(e);
      }
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "dragStart", function (e) {
      var dragPoint = new _pointGeometry["default"](e.pageX, e.pageY);

      _this.setState({
        dragPoint: dragPoint
      }, function () {
        document.addEventListener('mousemove', _this.drag);
      });
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "drag", function (e) {
      e.preventDefault();
      var current = new _pointGeometry["default"](e.pageX, e.pageY);
      var translate = current.sub(_this.state.dragPoint);

      _this.setState({
        translate: translate
      });
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "mouseUp", function () {
      if (!_this.state.translate) {
        return;
      }

      var _this$state2 = _this.state,
          lastPosition = _this$state2.position,
          translate = _this$state2.translate;
      var position = {
        left: lastPosition.left + translate.x,
        top: lastPosition.top + translate.y
      };
      document.removeEventListener('mousemove', _this.drag);

      _this.setState({
        position: position,
        dragPoint: null,
        translate: null
      });
    });
    _this.state = {
      isRotating: false,
      rotation: 0,
      startAngle: 0,
      angle: 0,
      position: {
        left: props.startPosition.left,
        top: props.startPosition.top
      }
    };
    return _this;
  }

  (0, _createClass2["default"])(Rotatable, [{
    key: "componentWillUnmount",
    value: function componentWillUnmount() {
      var _this2 = this;

      document.removeEventListener('mouseup', this.rotateStop);
      document.removeEventListener('mousemove', this.drag);
      document.removeEventListener('mousemove', this.rotate);
      this.handles.forEach(function (h) {
        h.el.removeEventListener('mousedown', h.mousedownHandler);
        h.el.removeEventListener('mouseup', _this2.rotateStop);
      });
    }
  }, {
    key: "componentDidMount",
    value: function componentDidMount() {
      this.addMouseUpHandler();
      this.initHandles();
    }
  }, {
    key: "getAngle",
    value: function getAngle(anchor, e) {
      var x = e.clientX - anchor.left;
      var y = (e.clientY - anchor.top) * -1;
      return {
        angle: (0, _anchorUtils.arctangent)(x, y),
        x: x,
        y: y
      };
    }
  }, {
    key: "render",
    value: function render() {
      var _this3 = this;

      var _this$props = this.props,
          children = _this$props.children,
          classes = _this$props.classes,
          showAnchor = _this$props.showAnchor,
          className = _this$props.className;
      var _this$state3 = this.state,
          rotation = _this$state3.rotation,
          anchor = _this$state3.anchor,
          origin = _this$state3.origin,
          translate = _this$state3.translate,
          position = _this$state3.position;
      var t = translate ? "translate(".concat(translate.x, "px, ").concat(translate.y, "px)") : '';
      var style = {
        left: position.left,
        top: position.top,
        transformOrigin: origin,
        transform: "".concat(t, " rotate(").concat(rotation, "deg)")
      };
      return /*#__PURE__*/_react["default"].createElement("div", {
        className: (0, _classnames["default"])(classes.rotatable, className),
        style: style,
        ref: function ref(r) {
          return _this3.rotatable = r;
        },
        onMouseDown: this.mouseDown,
        onMouseUp: this.mouseUp
      }, anchor && showAnchor && /*#__PURE__*/_react["default"].createElement(Anchor, anchor), children);
    }
  }]);
  return Rotatable;
}(_react["default"].Component);

exports.Rotatable = Rotatable;
(0, _defineProperty2["default"])(Rotatable, "propTypes", {
  classes: _propTypes["default"].object.isRequired,
  children: _propTypes["default"].oneOfType([_propTypes["default"].arrayOf(_propTypes["default"].node), _propTypes["default"].node]).isRequired,
  showAnchor: _propTypes["default"].bool,
  handle: _propTypes["default"].arrayOf(_propTypes["default"].shape({
    "class": _propTypes["default"].string.isRequired,
    origin: _propTypes["default"].string
  })),
  className: _propTypes["default"].string,
  startPosition: _propTypes["default"].shape({
    left: _propTypes["default"].number,
    top: _propTypes["default"].number
  })
});
(0, _defineProperty2["default"])(Rotatable, "defaultProps", {
  showAnchor: false,
  startPosition: {
    left: 0,
    top: 0
  }
});

var _default = (0, _styles.withStyles)({
  rotatable: {
    position: 'relative',
    display: 'inline-block',
    cursor: 'move'
  }
})(Rotatable);

exports["default"] = _default;
//# sourceMappingURL=rotatable.js.map