"use strict";

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

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.alignPoint = alignPoint;
exports["default"] = alignElement;

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

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

var _DocumentUtils = require("../../pro/lib/_util/DocumentUtils");

var _isString = _interopRequireDefault(require("lodash/isString"));

var _UnitConvertor = require("../_util/UnitConvertor");

function isFailX(elFuturePos, elRegion, visibleRect) {
  return elFuturePos.left < visibleRect.left || elFuturePos.left + elRegion.width > visibleRect.right;
}

function isFailY(elFuturePos, elRegion, visibleRect) {
  return elFuturePos.top < visibleRect.top || elFuturePos.top + elRegion.height > visibleRect.bottom;
}

function isCompleteFailX(elFuturePos, elRegion, visibleRect) {
  return elFuturePos.left > visibleRect.right || elFuturePos.left + elRegion.width < visibleRect.left;
}

function isCompleteFailY(elFuturePos, elRegion, visibleRect) {
  return elFuturePos.top > visibleRect.bottom || elFuturePos.top + elRegion.height < visibleRect.top;
}

function getParent(element) {
  var parent = element;

  do {
    parent = parent.parentElement;
  } while (parent && parent.nodeType !== 1 && parent.nodeType !== 9);

  return parent;
}

function getOffsetParentAndStyle(el, defaultView) {
  var _defaultView$getCompu = defaultView.getComputedStyle(el),
      position = _defaultView$getCompu.position;

  if (position !== 'absolute' && position !== 'fixed') {
    if (!(0, _isString["default"])(el.nodeName) || el.nodeName.toLowerCase() !== 'html') {
      var parent = getParent(el);

      if (parent) {
        return {
          parent: parent,
          style: null
        };
      }
    }
  } else {
    var body = defaultView.document.body;

    for (var _parent = getParent(el); _parent && _parent !== body && _parent.nodeType !== 9; _parent = getParent(_parent)) {
      var style = defaultView.getComputedStyle(_parent);

      if (style.position !== 'static') {
        return {
          parent: _parent,
          style: style
        };
      }
    }
  }

  return null;
}

function getVisibleRectForElement(element) {
  var ownerDocument = element.ownerDocument;

  if (ownerDocument) {
    var defaultView = ownerDocument.defaultView;

    if (defaultView) {
      var _body = ownerDocument.body,
          documentElement = ownerDocument.documentElement;
      var offsetParentAndStyle = getOffsetParentAndStyle(element, defaultView);

      while (offsetParentAndStyle) {
        var _offsetParentAndStyle = offsetParentAndStyle,
            parent = _offsetParentAndStyle.parent,
            style = _offsetParentAndStyle.style;

        if (!parent || parent === _body || parent === documentElement) {
          break;
        }

        if ((style || defaultView.getComputedStyle(parent)).overflow !== 'visible') {
          var rect = parent.getBoundingClientRect();

          var _getMousePosition = (0, _DocumentUtils.getMousePosition)(rect.left, rect.top, defaultView, true),
              x = _getMousePosition.x,
              y = _getMousePosition.y;

          return {
            top: y,
            right: rect.right + x - rect.left,
            bottom: rect.bottom + y - rect.top,
            left: x
          };
        }

        offsetParentAndStyle = getOffsetParentAndStyle(parent, defaultView);
      }
    }
  }

  var _getDocument = (0, _DocumentUtils.getDocument)(window),
      body = _getDocument.body;

  return {
    top: 0,
    right: body.clientWidth,
    bottom: body.clientHeight,
    left: 0
  };
}

function getRegion(node) {
  var rect = node.getBoundingClientRect();
  var ownerDocument = node.ownerDocument;
  var defaultView = ownerDocument ? ownerDocument.defaultView : null;
  var position = defaultView ? (0, _DocumentUtils.getMousePosition)(rect.left, rect.top, defaultView, true) : {
    x: rect.left,
    y: rect.top
  };
  return {
    top: position.y,
    left: position.x,
    width: rect.width || node.offsetWidth,
    height: rect.height || node.offsetHeight
  };
}

function isOutOfVisibleRect(target) {
  var visibleRect = getVisibleRectForElement(target);
  var targetRegion = getRegion(target);
  return !visibleRect || targetRegion.left + targetRegion.width <= visibleRect.left || targetRegion.top + targetRegion.height <= visibleRect.top || targetRegion.left >= visibleRect.right || targetRegion.top >= visibleRect.bottom;
}

function flip(points, reg, map) {
  return points.map(function (p) {
    return p.replace(reg, function (m) {
      return map[m];
    });
  });
}

function flipOffset(offset, index) {
  offset[index] = -offset[index];
  return offset;
}

function getAlignOffset(region, align) {
  var V = align.charAt(0);
  var H = align.charAt(1);
  var w = region.width;
  var h = region.height;
  var x = region.left;
  var y = region.top;

  if (V === 'c') {
    y += h / 2;
  } else if (V === 'b') {
    y += h;
  }

  if (H === 'c') {
    x += w / 2;
  } else if (H === 'r') {
    x += w;
  }

  return {
    left: x,
    top: y
  };
}

function getElFuturePos(elRegion, refNodeRegion, points, offset, targetOffset) {
  var p1 = getAlignOffset(refNodeRegion, points[1]);
  var p2 = getAlignOffset(elRegion, points[0]);
  var diff = [p2.left - p1.left, p2.top - p1.top];
  return {
    left: elRegion.left - diff[0] + offset[0] - targetOffset[0],
    top: elRegion.top - diff[1] + offset[1] - targetOffset[1]
  };
}

function adjustForViewport(elFuturePos, elRegion, visibleRect, overflow) {
  var pos = (0, _objectSpread2["default"])({}, elFuturePos);
  var size = {
    width: elRegion.width,
    height: elRegion.height
  };

  if (overflow.adjustX && pos.left < visibleRect.left) {
    pos.left = visibleRect.left;
  } // Left edge inside and right edge outside viewport, try to resize it.


  if (overflow.resizeWidth && pos.left >= visibleRect.left && pos.left + size.width > visibleRect.right) {
    size.width -= pos.left + size.width - visibleRect.right;
  } // Right edge outside viewport, try to move it.


  if (overflow.adjustX && pos.left + size.width > visibleRect.right) {
    // 保证左边界和可视区域左边界对齐
    pos.left = Math.max(visibleRect.right - size.width, visibleRect.left);
  } // Top edge outside viewport, try to move it.


  if (overflow.adjustY && pos.top < visibleRect.top) {
    pos.top = visibleRect.top;
  } // Top edge inside and bottom edge outside viewport, try to resize it.


  if (overflow.resizeHeight && pos.top >= visibleRect.top && pos.top + size.height > visibleRect.bottom) {
    size.height -= pos.top + size.height - visibleRect.bottom;
  } // Bottom edge outside viewport, try to move it.


  if (overflow.adjustY && pos.top + size.height > visibleRect.bottom) {
    // 保证上边界和可视区域上边界对齐
    pos.top = Math.max(visibleRect.bottom - size.height, visibleRect.top);
  }

  return (0, _extends2["default"])(pos, size);
} // function isFixedPosition(node: HTMLElement): boolean {
//   const { offsetParent, ownerDocument } = node;
//   if (
//     ownerDocument &&
//     offsetParent === ownerDocument.body &&
//     ownerDocument.defaultView &&
//     ownerDocument.defaultView.getComputedStyle(node).position !== 'fixed'
//   ) {
//     return false;
//   }
//   if (offsetParent) {
//     return isFixedPosition(offsetParent as HTMLElement);
//   }
//   return true;
// }


function doAlign(el, refNodeRegion, align, isTargetNotOutOfVisible) {
  var points = align.points;
  var offset = (align.offset || [0, 0]).slice();
  var targetOffset = (align.targetOffset || [0, 0]).slice();
  var overflow = align.overflow || {};
  var source = align.source || el;
  var newOverflowCfg = {};
  var fail = 0;
  var visibleRect = getVisibleRectForElement(el);
  var elRegion = getRegion(source);
  var elFuturePos = getElFuturePos(elRegion, refNodeRegion, points, offset, targetOffset);
  var newElRegion = (0, _extends2["default"])(elRegion, elFuturePos);

  if (visibleRect && (overflow.adjustX || overflow.adjustY) && isTargetNotOutOfVisible) {
    if (overflow.adjustX) {
      if (isFailX(elFuturePos, elRegion, visibleRect)) {
        var newPoints = flip(points, /[lr]/gi, {
          l: 'r',
          r: 'l'
        });
        var newOffset = flipOffset(offset, 0);
        var newTargetOffset = flipOffset(targetOffset, 0);
        var newElFuturePos = getElFuturePos(elRegion, refNodeRegion, newPoints, newOffset, newTargetOffset);

        if (!isCompleteFailX(newElFuturePos, elRegion, visibleRect)) {
          fail = 1;
          points = newPoints;
          offset = newOffset;
          targetOffset = newTargetOffset;
        }
      }
    }

    if (overflow.adjustY) {
      if (isFailY(elFuturePos, elRegion, visibleRect)) {
        var _newPoints = flip(points, /[tb]/gi, {
          t: 'b',
          b: 't'
        });

        var _newOffset = flipOffset(offset, 1);

        var _newTargetOffset = flipOffset(targetOffset, 1);

        var _newElFuturePos = getElFuturePos(elRegion, refNodeRegion, _newPoints, _newOffset, _newTargetOffset);

        if (!isCompleteFailY(_newElFuturePos, elRegion, visibleRect)) {
          fail = 1;
          points = _newPoints;
          offset = _newOffset;
          targetOffset = _newTargetOffset;
        }
      }
    }

    if (fail) {
      elFuturePos = getElFuturePos(elRegion, refNodeRegion, points, offset, targetOffset);
      (0, _extends2["default"])(newElRegion, elFuturePos);
    }

    newOverflowCfg.adjustX = overflow.adjustX && isFailX(elFuturePos, elRegion, visibleRect);
    newOverflowCfg.adjustY = overflow.adjustY && isFailY(elFuturePos, elRegion, visibleRect);

    if (newOverflowCfg.adjustX || newOverflowCfg.adjustY) {
      newElRegion = adjustForViewport(elFuturePos, elRegion, visibleRect, newOverflowCfg);
    }
  }

  var _newElRegion = newElRegion,
      width = _newElRegion.width,
      height = _newElRegion.height;

  if (width !== elRegion.width) {
    source.style.width = width ? (0, _UnitConvertor.pxToRem)(width, true) : '0';
  }

  if (height !== elRegion.height) {
    source.style.height = height ? (0, _UnitConvertor.pxToRem)(height, true) : '0';
  } // const isTargetFixed = isFixedPosition(target);


  var offsetParent = source.offsetParent,
      ownerDocument = source.ownerDocument;

  if (offsetParent) {
    var _offsetParent$getBoun = offsetParent.getBoundingClientRect(),
        left = _offsetParent$getBoun.left,
        top = _offsetParent$getBoun.top;

    newElRegion.left -= left;
    newElRegion.top -= top;
  }

  if (ownerDocument) {
    var _getMousePosition2 = (0, _DocumentUtils.getMousePosition)(0, 0, ownerDocument.defaultView || window, true),
        x = _getMousePosition2.x,
        y = _getMousePosition2.y;

    newElRegion.left -= x;
    newElRegion.top -= y;
  }

  (0, _extends2["default"])(source.style, {
    left: (0, _UnitConvertor.pxToRem)(newElRegion.left, true),
    top: (0, _UnitConvertor.pxToRem)(newElRegion.top, true)
  }); // if (isTargetFixed) {
  //   source.style.position = 'fixed';
  // } else {
  //   source.style.position = '';
  // }

  return {
    points: points,
    offset: offset,
    targetOffset: targetOffset,
    overflow: newOverflowCfg
  };
}

function alignElement(el, refNode, align) {
  var target = align.target || refNode;
  var refNodeRegion = getRegion(target);
  var isTargetNotOutOfVisible = !isOutOfVisibleRect(target);
  return doAlign(el, refNodeRegion, align, isTargetNotOutOfVisible);
}

function alignPoint(el, tgtPoint, align) {
  var left = 0;
  var top = 0;
  var ownerDocument = el.ownerDocument;
  var defaultView = ownerDocument ? ownerDocument.defaultView : null;
  var documentElement = ownerDocument ? ownerDocument.documentElement : null;
  var scrollX = documentElement ? documentElement.scrollLeft : 0;
  var scrollY = documentElement ? documentElement.scrollTop : 0;

  if (tgtPoint.pageX !== undefined) {
    left = tgtPoint.pageX - scrollX;
  } else if (tgtPoint.clientX !== undefined) {
    left = scrollX + tgtPoint.clientX;
  }

  if (tgtPoint.pageY !== undefined) {
    top = tgtPoint.pageY - scrollY;
  } else if (tgtPoint.clientY !== undefined) {
    top = tgtPoint.clientY;
  }

  var position = defaultView ? (0, _DocumentUtils.getMousePosition)(left, top, defaultView, true) : {
    x: left,
    y: top,
    vw: documentElement ? documentElement.clientWidth : 0,
    vh: documentElement ? documentElement.clientHeight : 0
  };
  left = position.x;
  top = position.y;
  var tgtRegion = {
    left: left,
    top: top,
    width: 0,
    height: 0
  };
  var pointInView = left >= 0 && left <= position.vw && top >= 0 && top <= position.vh; // Provide default target point

  var points = [align.points[0], 'cc'];
  return doAlign(el, tgtRegion, (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, align), {}, {
    points: points
  }), pointInView);
}
//# sourceMappingURL=domAlign.js.map
