/*(c) Copyright 2015 Pivotal Software, Inc. All Rights Reserved.*/
'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.useBoundingClientRect = undefined;

var _setImmediate2 = require('babel-runtime/core-js/set-immediate');

var _setImmediate3 = _interopRequireDefault(_setImmediate2);

var _extends2 = require('babel-runtime/helpers/extends');

var _extends3 = _interopRequireDefault(_extends2);

var _promise = require('babel-runtime/core-js/promise');

var _promise2 = _interopRequireDefault(_promise);

var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');

var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);

var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');

var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);

var _createClass2 = require('babel-runtime/helpers/createClass');

var _createClass3 = _interopRequireDefault(_createClass2);

var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');

var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);

var _get2 = require('babel-runtime/helpers/get');

var _get3 = _interopRequireDefault(_get2);

var _inherits2 = require('babel-runtime/helpers/inherits');

var _inherits3 = _interopRequireDefault(_inherits2);

var _weakMap = require('babel-runtime/core-js/weak-map');

var _weakMap2 = _interopRequireDefault(_weakMap);

var _raf = require('raf');

var _raf2 = _interopRequireDefault(_raf);

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _reactDom = require('react-dom');

var _reactDom2 = _interopRequireDefault(_reactDom);

var _shallowEqual = require('fbjs/lib/shallowEqual');

var _shallowEqual2 = _interopRequireDefault(_shallowEqual);

var _mixins = require('../mixins');

var _mixins2 = _interopRequireDefault(_mixins);

var _mounted_mixin = require('../mixins/mounted_mixin');

var _mounted_mixin2 = _interopRequireDefault(_mounted_mixin);

var _shallow_compare_mixin = require('../mixins/shallow_compare_mixin');

var _shallow_compare_mixin2 = _interopRequireDefault(_shallow_compare_mixin);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var Component = (0, _mixins2.default)(_react2.default.Component).with(_shallow_compare_mixin2.default);
var rafify = function rafify(callback) {
  return function () {
    for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }

    return (0, _raf2.default)(function () {
      return callback.call.apply(callback, [undefined].concat(args));
    });
  };
};
var privates = new _weakMap2.default();
var properties = ['width', 'height', 'top', 'right', 'bottom', 'left'];

var useBoundingClientRect = exports.useBoundingClientRect = function useBoundingClientRect(Klass) {
  return function (_mixin$with) {
    (0, _inherits3.default)(BoundingClientRect, _mixin$with);

    function BoundingClientRect(props, context) {
      (0, _classCallCheck3.default)(this, BoundingClientRect);

      var _this = (0, _possibleConstructorReturn3.default)(this, (BoundingClientRect.__proto__ || (0, _getPrototypeOf2.default)(BoundingClientRect)).call(this, props, context));

      _this.resize = function () {
        var _ref = privates.get(_this) || {},
            prevBoundingClientRect = _ref.boundingClientRect;

        var boundingClientRect = _this.getBoundingClientRect();
        var isNotEqual = function isNotEqual(property) {
          return boundingClientRect[property] !== prevBoundingClientRect[property];
        };
        if (!prevBoundingClientRect || properties.some(isNotEqual)) {
          _this.mounted() && _this.forceUpdate();
        }
      };

      var resolver = void 0;
      var containerReady = new _promise2.default(function (resolve) {
        return resolver = resolve;
      });
      containerReady.resolve = resolver;
      var state = _this.state;

      _this.state = (0, _extends3.default)({}, state, { container: null, containerReady: containerReady });
      _this.resize = rafify(_this.resize);

      _this.getBoundingClientRect = _this.getBoundingClientRect.bind(_this);
      return _this;
    }

    (0, _createClass3.default)(BoundingClientRect, [{
      key: 'componentDidMount',
      value: function componentDidMount() {
        var _this2 = this;

        (0, _get3.default)(BoundingClientRect.prototype.__proto__ || (0, _getPrototypeOf2.default)(BoundingClientRect.prototype), 'componentDidMount', this).call(this);
        privates.set(this, { resize: this.resize });
        window.addEventListener('resize', this.resize);
        this.setState({ container: _reactDom2.default.findDOMNode(this.component) });
        (0, _setImmediate3.default)(function () {
          return _this2.state.containerReady.resolve(_this2.state.container);
        });
      }
    }, {
      key: 'componentWillUnmount',
      value: function componentWillUnmount() {
        (0, _get3.default)(BoundingClientRect.prototype.__proto__ || (0, _getPrototypeOf2.default)(BoundingClientRect.prototype), 'componentWillUnmount', this).call(this);

        var _ref2 = privates.get(this) || {},
            resize = _ref2.resize;

        window.removeEventListener('resize', resize);
        privates.delete(this);
      }
    }, {
      key: 'componentWillReceiveProps',
      value: function componentWillReceiveProps(nextProps) {
        if (!(0, _shallowEqual2.default)(this.props, nextProps)) this.resize();
      }
    }, {
      key: 'getBoundingClientRect',
      value: function getBoundingClientRect() {
        return this.state.container && this.state.container.getBoundingClientRect() || {};
      }
    }, {
      key: 'render',
      value: function render() {
        var _this3 = this;

        var _ref3 = privates.get(this) || {},
            resize = _ref3.resize;

        var boundingClientRect = this.getBoundingClientRect();
        privates.set(this, { boundingClientRect: boundingClientRect, resize: resize });
        return _react2.default.createElement(Klass, (0, _extends3.default)({}, this.props, this.state, { boundingClientRect: boundingClientRect }, { ref: function ref(_ref4) {
            return _this3.component = _ref4;
          } }));
      }
    }]);
    return BoundingClientRect;
  }((0, _mixins2.default)(Component).with(_mounted_mixin2.default));
};