var vec2 = require("../../core/utils/vector");

var matrix = require("../../core/utils/matrix");

var _constants = require("../constants");

var mathMin = _constants.mathMin;
var mathMax = _constants.mathMax;

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

/**
 * @class qrenderer.core.BoundingRect
 * 
 * Bounding Rect.
 * 
 * 边界矩形。
 * 
 * @docauthor 大漠穷秋 <damoqiongqiu@126.com>
 */
var v2ApplyTransform = vec2.applyTransform;
var lt = [];
var rb = [];
var lb = [];
var rt = [];

var BoundingRect =
/*#__PURE__*/
function () {
  /**
   * @method constructor BoundingRect
   */
  function BoundingRect(x, y, width, height) {
    _classCallCheck(this, BoundingRect);

    if (width < 0) {
      x = x + width;
      width = -width;
    }

    if (height < 0) {
      y = y + height;
      height = -height;
    }
    /**
     * @property {Number}
     */


    this.x = x;
    /**
     * @property {Number}
     */

    this.y = y;
    /**
     * @property {Number}
     */

    this.width = width;
    /**
     * @property {Number}
     */

    this.height = height;
  }
  /**
   * @param {Object|BoundingRect} rect
   * @param {Number} rect.x
   * @param {Number} rect.y
   * @param {Number} rect.width
   * @param {Number} rect.height
   * @return {BoundingRect}
   */


  _createClass(BoundingRect, [{
    key: "union",

    /**
     * @method union
     * @param {BoundingRect} other
     */
    value: function union(other) {
      var x = mathMin(other.x, this.x);
      var y = mathMin(other.y, this.y);
      this.width = mathMax(other.x + other.width, this.x + this.width) - x;
      this.height = mathMax(other.y + other.height, this.y + this.height) - y;
      this.x = x;
      this.y = y;
    }
    /**
     * @method applyTransform
     * @param {Array<Number>}
     */

  }, {
    key: "applyTransform",
    value: function applyTransform(m) {
      // In case usage like this
      // el.getBoundingRect().applyTransform(el.transform)
      // And element has no transform
      if (!m) {
        return;
      }

      lt[0] = lb[0] = this.x;
      lt[1] = rt[1] = this.y;
      rb[0] = rt[0] = this.x + this.width;
      rb[1] = lb[1] = this.y + this.height;
      v2ApplyTransform(lt, lt, m);
      v2ApplyTransform(rb, rb, m);
      v2ApplyTransform(lb, lb, m);
      v2ApplyTransform(rt, rt, m);
      this.x = mathMin(lt[0], rb[0], lb[0], rt[0]);
      this.y = mathMin(lt[1], rb[1], lb[1], rt[1]);
      var maxX = mathMax(lt[0], rb[0], lb[0], rt[0]);
      var maxY = mathMax(lt[1], rb[1], lb[1], rt[1]);
      this.width = maxX - this.x;
      this.height = maxY - this.y;
    }
    /**
     * @method calculateTransform
     * Calculate matrix of transforming from self to target rect
     * @param  {BoundingRect} b
     * @return {Array<Number>}
     */

  }, {
    key: "calculateTransform",
    value: function calculateTransform(b) {
      var a = this;
      var sx = b.width / a.width;
      var sy = b.height / a.height;
      var m = matrix.create(); // 矩阵右乘

      matrix.translate(m, m, [-a.x, -a.y]);
      matrix.scale(m, m, [sx, sy]);
      matrix.translate(m, m, [b.x, b.y]);
      return m;
    }
    /**
     * @method intersect
     * @param {(BoundingRect|Object)} b
     * @return {boolean}
     */

  }, {
    key: "intersect",
    value: function intersect(b) {
      if (!b) {
        return false;
      }

      if (!(b instanceof BoundingRect)) {
        // Normalize negative width/height.
        b = BoundingRect.create(b);
      }

      var a = this;
      var ax0 = a.x;
      var ax1 = a.x + a.width;
      var ay0 = a.y;
      var ay1 = a.y + a.height;
      var bx0 = b.x;
      var bx1 = b.x + b.width;
      var by0 = b.y;
      var by1 = b.y + b.height;
      return !(ax1 < bx0 || bx1 < ax0 || ay1 < by0 || by1 < ay0);
    }
    /**
     * @method contain
     * @param {*} x 
     * @param {*} y 
     */

  }, {
    key: "contain",
    value: function contain(x, y) {
      var rect = this;
      return x >= rect.x && x <= rect.x + rect.width && y >= rect.y && y <= rect.y + rect.height;
    }
    /**
     * @method clone
     * @return {BoundingRect}
     */

  }, {
    key: "clone",
    value: function clone() {
      return new BoundingRect(this.x, this.y, this.width, this.height);
    }
    /**
     * @method copy
     * Copy from another rect
     * @param other
     */

  }, {
    key: "copy",
    value: function copy(other) {
      this.x = other.x;
      this.y = other.y;
      this.width = other.width;
      this.height = other.height;
    }
    /**
     * @method plain
     */

  }, {
    key: "plain",
    value: function plain() {
      return {
        x: this.x,
        y: this.y,
        width: this.width,
        height: this.height
      };
    }
  }], [{
    key: "create",
    value: function create(rect) {
      return new BoundingRect(rect.x, rect.y, rect.width, rect.height);
    }
  }]);

  return BoundingRect;
}();

var _default = BoundingRect;
module.exports = _default;