"use strict";

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

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); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }

var hasResizeObserver = !!window.ResizeObserver;
var mutationObserverFullOptions = {
  childList: true,
  attributes: true,
  subtree: true,
  characterData: true
};
var mutationObserverOptionsForStyleChanges = {
  attributes: true
};

function shallowCompare(obj1, obj2) {
  if (obj1 === obj2) {
    return true;
  } else if (!(obj1 instanceof Object) || !(obj2 instanceof Object)) {
    return false;
  }

  var keys1 = Object.keys(obj1).sort();
  var keys2 = Object.keys(obj2).sort();

  if (keys1.length !== keys2.length) {
    return false;
  }

  return keys1.every(function (key, i) {
    return key === keys2[i] && obj1[key] === obj2[keys2[i]];
  });
}

function getPropertyValueWithoutUnit(styleObj, property) {
  return parseFloat(styleObj[property], 10) || 0;
}

function getSizeAndMargin(element, hasMargin) {
  var clientHeight = element.clientHeight,
      clientWidth = element.clientWidth;

  var _element$getBoundingC = element.getBoundingClientRect(),
      height = _element$getBoundingC.height,
      width = _element$getBoundingC.width;

  var size = {
    height: height,
    width: width,
    clientHeight: clientHeight,
    clientWidth: clientWidth,
    marginTop: 0,
    marginBottom: 0,
    marginLeft: 0,
    marginRight: 0
  };

  if (hasMargin) {
    // this line referred from https://stackoverflow.com/questions/14275304/how-to-get-margin-value-of-a-div-in-plain-javascript
    var computedStyle = window.getComputedStyle(element);
    size.marginTop = getPropertyValueWithoutUnit(computedStyle, "marginTop");
    size.marginBottom = getPropertyValueWithoutUnit(computedStyle, "marginBottom");
    size.marginLeft = getPropertyValueWithoutUnit(computedStyle, "marginLeft");
    size.marginRight = getPropertyValueWithoutUnit(computedStyle, "marginRight");
  }

  return size;
}

var ResizeObserverPolyfill = /*#__PURE__*/function () {
  function ResizeObserverPolyfill(onResize, hasMargin) {
    _classCallCheck(this, ResizeObserverPolyfill);

    // method binds
    this.transitionEndHandler = this.transitionEndHandler.bind(this);
    this.resizeHandler = this._resizeHandler.bind(this); // this.resizeHandler = (...args) => {
    //   requestAnimationFrame(() => {
    //     this._resizeHandler(...args);
    //   });
    // };

    this.onResize = onResize;
    this.hasMargin = hasMargin;
    this.targetNode = null;
    this.size = null;
    this.mutationObserverInstance = new window.MutationObserver(this.resizeHandler);

    if (hasResizeObserver) {
      this.resizeObserverInstance = new window.ResizeObserver(this.resizeHandler);
    }
  }

  _createClass(ResizeObserverPolyfill, [{
    key: "transitionEndHandler",
    value: function transitionEndHandler(event) {
      // TODO: we need to update this condition mouch better
      //  like ['height', 'width'].indexOf(propertyName) >= 0 the specific property
      var propertyName = event.propertyName;

      var includes = function includes(str) {
        return propertyName.indexOf(str) >= 0;
      };

      if (includes("color")) {
        return;
      } // NOTE: border-width and min-width, max-width are includes width
      // NOTE: line-height and min-height, max-height are includes height


      if (["margin", "padding", "width", "height", "flex-basic"].some(includes)) {
        this.resizeHandler();
        return;
      }
    }
  }, {
    key: "_resizeHandler",
    value: function _resizeHandler() {
      if (!this.targetNode) {
        return;
      }

      var currentSize = getSizeAndMargin(this.targetNode, this.hasMargin);

      if (this.size && shallowCompare(currentSize, this.size)) {
        return;
      }

      this.size = currentSize;
      this.onResize(this.size);
    }
  }, {
    key: "observe",
    value: function observe(targetNode, hasMargin) {
      var _this = this;

      this.targetNode = targetNode;

      if (!targetNode) {
        return;
      }

      targetNode.addEventListener("transitionend", this.transitionEndHandler);
      this.hasMargin = hasMargin;

      if (hasResizeObserver) {
        this.resizeObserverInstance.observe(targetNode);

        if (hasMargin) {
          this.mutationObserverInstance.observe(targetNode, mutationObserverOptionsForStyleChanges);
        }
      } else {
        this.mutationObserverInstance.observe(targetNode, mutationObserverFullOptions);
      } // NOTE: just for initialize
      // cancelAnimationFrame(this.interval);
      // this.interval = requestAnimationFrame(() => {


      clearTimeout(this.interval);
      this.interval = setTimeout(function () {
        _this.resizeHandler();
      });
    }
  }, {
    key: "replaceObservationElement",
    value: function replaceObservationElement(targetNode) {
      if (this.targetNode === targetNode) {
        return;
      }

      this.disconnect();
      this.observe(targetNode, this.hasMargin);
    }
  }, {
    key: "disconnect",
    value: function disconnect() {
      this.size = null;
      this.targetNode && this.targetNode.removeEventListener("transitionend", this.transitionEndHandler);
      hasResizeObserver && this.resizeObserverInstance.disconnect();
      this.mutationObserverInstance.disconnect();
    }
  }]);

  return ResizeObserverPolyfill;
}(); //TODO:   HACK:
//    for window.ResizeObserver unsupported browsers we want to calculate dimensions because flex affect element size with siblings


exports["default"] = ResizeObserverPolyfill;