"use strict";

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

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.toRadians = exports.toPoint = exports.toDegrees = exports.normalizeAngle = exports.getXAndY = exports.getTop = exports.getLeft = exports.getAngleAndHypotenuse = exports.getAnchor = exports.distanceBetween = exports.arctangent = void 0;

var _trigonometryCalculator = require("trigonometry-calculator");

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

var _debug = _interopRequireDefault(require("debug"));

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

var log = (0, _debug["default"])('@pie-lib:tools:anchor-utils');

var toDegrees = function toDegrees(radians) {
  return radians * (180 / Math.PI);
};

exports.toDegrees = toDegrees;

var toRadians = function toRadians(degrees) {
  return degrees * (Math.PI / 180);
};

exports.toRadians = toRadians;

var normalizeAngle = function normalizeAngle(a) {
  if (a > 360) {
    return a % 360;
  } else if (a < 0) {
    return 360 + a % 360;
  }

  return a;
};

exports.normalizeAngle = normalizeAngle;

var toPoint = function toPoint(rect, edge) {
  var out = (0, _transformOrigin.parse)(rect, edge);
  return new _pointGeometry["default"](out.x, out.y);
};
/**
 * Get the distance between to anchor points in a rect.
 * @param {{width: number, height: number}} rect - the rect
 * @param {number} degrees - the degrees
 * @param {string} from - from anchor
 * @param {string} to - to anchor
 * @returns {Point} point - the distance as a Point
 */


exports.toPoint = toPoint;

var distanceBetween = function distanceBetween(rect, degrees, from, to) {
  var center = new _pointGeometry["default"](rect.width / 2, rect.height / 2);
  var radians = toRadians(degrees);
  var fromCenter = center.rotateAround(radians, toPoint(rect, from));
  var toCenter = center.rotateAround(radians, toPoint(rect, to));
  var diff = fromCenter.sub(toCenter);
  return diff;
};
/**
 * For a corner string, a point and a rect, return a relative x,y from that point to a corner.
 * Note that the y value descends as it goes down (unlike for a screen's y value), so this is only really useful for math functions.
 * @example
 * ```
 * getXAndY('top-left', {width: 100, height: 100}, 10, 10) //=> {x:10, y: -90}
 * ```
 * @param {*} corner
 * @param {*} rect
 * @param {*} point
 */


exports.distanceBetween = distanceBetween;

var getXAndY = function getXAndY(corner, rect, point) {
  if (corner === 'top-left') {
    var x = point.x * -1;
    var y = point.y;
    return {
      x: x,
      y: y
    };
  } else if (corner === 'bottom-left') {
    var _x = point.x * -1;

    var _y = point.y - rect.height;

    return {
      x: _x,
      y: _y
    };
  } else if (corner === 'top-right') {
    var _x2 = rect.width - point.x;

    var _y2 = point.y;
    return {
      x: _x2,
      y: _y2
    };
  } else if (corner === 'bottom-right') {
    var _x3 = rect.width - point.x;

    var _y3 = point.y - rect.height;

    return {
      x: _x3,
      y: _y3
    };
  }
};

exports.getXAndY = getXAndY;

var arctangent = function arctangent(x, y) {
  return toDegrees(Math.atan2(x, y));
};

exports.arctangent = arctangent;

var getAngleAndHypotenuse = function getAngleAndHypotenuse(corner, rect, point) {
  var _getXAndY = getXAndY(corner, rect, point),
      x = _getXAndY.x,
      y = _getXAndY.y;

  var degrees = arctangent(x, y);
  var hypotenuse = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
  return {
    x: x,
    y: y,
    degrees: degrees,
    hypotenuse: hypotenuse
  };
};

exports.getAngleAndHypotenuse = getAngleAndHypotenuse;

var getPosition = function getPosition(side, rect, point, angle, calcAngle) {
  if (angle === 0) {
    return side === 'left' ? point.x : point.y;
  }

  var points = anglePoints(angle);
  var key = points[side];

  var _getAngleAndHypotenus = getAngleAndHypotenuse(key, rect, point),
      degrees = _getAngleAndHypotenus.degrees,
      hypotenuse = _getAngleAndHypotenus.hypotenuse;

  var ra = calcAngle(degrees);

  if (ra === 0) {
    return hypotenuse;
  }

  var t = {
    angles: {
      0: ra,
      1: 90
    },
    sides: {
      1: hypotenuse
    }
  };
  var out = (0, _trigonometryCalculator.trigCalculator)(t);
  return out.sides[2];
};

var getTop = function getTop(rect, point, angle) {
  return getPosition('top', rect, point, angle, function (degrees) {
    return Math.abs(angle + degrees);
  });
};

exports.getTop = getTop;

var getLeft = function getLeft(rect, point, angle) {
  return getPosition('left', rect, point, angle, function (degrees) {
    return Math.abs(angle + degrees + 90);
  });
};
/**
 * Calculate the position of an anchor within a bounding rect, if the source rect has been rotated by an angle.
 * It does this by finding the appropriate corner of the src rect, that touches the bounding rect, calculates
 * the hypotenuse (h) of that anchor to that point. Then using that plus the rotation it calculates
 * the sides of the triangle and returns the length of the side that touches the bounding rect.
 * @param {{width: number, height: number}} rect - the rect which contains the point
 * @param {{x:number, y: number}} point - the point within the rect
 * @param {number} angle - the angle in degrees that the rect has rotated.
 * @returns {{left: number, top: number}} position
 */


exports.getLeft = getLeft;

var getAnchor = function getAnchor(rect, point, angle) {
  log('[getAnchor] rect: ', rect, 'point:', point, 'angle: ', angle);

  if (point.x > rect.width) {
    throw new Error("x: ".concat(point.x, " cannot be greater than width: ").concat(rect.width));
  }

  if (point.y > rect.height) {
    throw new Error("y: ".concat(point.y, " cannot be greater than height: ").concat(rect.height));
  }

  var a = normalizeAngle(angle);
  var top = getTop(rect, point, a);
  var left = getLeft(rect, point, a);
  log('[getAnchor] top: ', top, 'left: ', left);
  return {
    top: top,
    left: left
  };
};

exports.getAnchor = getAnchor;

var anglePoints = function anglePoints(angle) {
  if (angle <= 90) {
    return {
      top: 'top-left',
      left: 'bottom-left'
    };
  } else if (angle > 90 && angle <= 180) {
    return {
      top: 'bottom-left',
      left: 'bottom-right'
    };
  } else if (angle > 180 && angle <= 270) {
    return {
      top: 'bottom-right',
      left: 'top-right'
    };
  } else if (angle > 270 && angle < 360) {
    return {
      top: 'top-right',
      left: 'top-left'
    };
  }
};
//# sourceMappingURL=anchor-utils.js.map