'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var enums = require('../enums.js');
var getViewportRect = require('./getViewportRect.js');
var getDocumentRect = require('./getDocumentRect.js');
var listScrollParents = require('./listScrollParents.js');
var getOffsetParent = require('./getOffsetParent.js');
var getDocumentElement = require('./getDocumentElement.js');
var getComputedStyle = require('./getComputedStyle.js');
var instanceOf = require('./instanceOf.js');
var getBoundingClientRect = require('./getBoundingClientRect.js');
var getParentNode = require('./getParentNode.js');
var contains = require('./contains.js');
var getNodeName = require('./getNodeName.js');
var rectToClientRect = require('../utils/rectToClientRect.js');
var math = require('../utils/math.js');

function getInnerBoundingClientRect(element, strategy) {
  var rect = getBoundingClientRect.default(element, false, strategy === 'fixed');
  rect.top = rect.top + element.clientTop;
  rect.left = rect.left + element.clientLeft;
  rect.bottom = rect.top + element.clientHeight;
  rect.right = rect.left + element.clientWidth;
  rect.width = element.clientWidth;
  rect.height = element.clientHeight;
  rect.x = rect.left;
  rect.y = rect.top;
  return rect;
}

function getClientRectFromMixedType(element, clippingParent, strategy) {
  return clippingParent === enums.viewport ? rectToClientRect.default(getViewportRect.default(element, strategy)) : instanceOf.isElement(clippingParent) ? getInnerBoundingClientRect(clippingParent, strategy) : rectToClientRect.default(getDocumentRect.default(getDocumentElement.default(element)));
} // A "clipping parent" is an overflowable container with the characteristic of
// clipping (or hiding) overflowing elements with a position different from
// `initial`


function getClippingParents(element) {
  var clippingParents = listScrollParents.default(getParentNode.default(element));
  var canEscapeClipping = ['absolute', 'fixed'].indexOf(getComputedStyle.default(element).position) >= 0;
  var clipperElement = canEscapeClipping && instanceOf.isHTMLElement(element) ? getOffsetParent.default(element) : element;

  if (!instanceOf.isElement(clipperElement)) {
    return [];
  } // $FlowFixMe[incompatible-return]: https://github.com/facebook/flow/issues/1414


  return clippingParents.filter(function (clippingParent) {
    return instanceOf.isElement(clippingParent) && contains.default(clippingParent, clipperElement) && getNodeName.default(clippingParent) !== 'body';
  });
} // Gets the maximum area that the element is visible in due to any number of
// clipping parents


function getClippingRect(element, boundary, rootBoundary, strategy) {
  var mainClippingParents = boundary === 'clippingParents' ? getClippingParents(element) : [].concat(boundary);
  var clippingParents = [].concat(mainClippingParents, [rootBoundary]);
  var firstClippingParent = clippingParents[0];
  var clippingRect = clippingParents.reduce(function (accRect, clippingParent) {
    var rect = getClientRectFromMixedType(element, clippingParent, strategy);
    accRect.top = math.max(rect.top, accRect.top);
    accRect.right = math.min(rect.right, accRect.right);
    accRect.bottom = math.min(rect.bottom, accRect.bottom);
    accRect.left = math.max(rect.left, accRect.left);
    return accRect;
  }, getClientRectFromMixedType(element, firstClippingParent, strategy));
  clippingRect.width = clippingRect.right - clippingRect.left;
  clippingRect.height = clippingRect.bottom - clippingRect.top;
  clippingRect.x = clippingRect.left;
  clippingRect.y = clippingRect.top;
  return clippingRect;
}

exports.default = getClippingRect;
//# sourceMappingURL=getClippingRect.js.map
