import { __assign } from "tslib";
export var MARGIN = 15;
function getScrollTop() {
    return document.documentElement.scrollTop || document.body.scrollTop || 0;
}
function getScrollLeft() {
    return document.documentElement.scrollLeft || document.body.scrollLeft || 0;
}
function parseDirection(direction) {
    var defaultAlign = "center";
    var directionArray = direction
        .replace(/([a-z])([A-Z])/g, "$1 $2")
        .split(" ");
    var realDirection = directionArray[0];
    var alignMode = directionArray.length > 1 ? directionArray[1].toLowerCase() : defaultAlign;
    return [realDirection, alignMode];
}
function checkLeftRightWidthSufficient(tip, target) {
    var targetRect = target.getBoundingClientRect();
    var deadSpace = Math.min(targetRect.left, document.documentElement.clientWidth - targetRect.right);
    return (tip.offsetWidth + target.offsetWidth + deadSpace <
        document.documentElement.clientWidth);
}
function getDirection(currentDirection, tip, target) {
    if (!target) {
        return currentDirection;
    }
    var targetRect = target.getBoundingClientRect();
    var heightOfTipWithArrow = tip.offsetHeight;
    var spaceBelowTarget = window.innerHeight - targetRect.bottom;
    var spaceAboveTarget = targetRect.top;
    var hasSpaceBelow = spaceBelowTarget >= heightOfTipWithArrow;
    var hasSpaceAbove = spaceAboveTarget >= heightOfTipWithArrow;
    switch (currentDirection) {
        case "left":
            if (!checkLeftRightWidthSufficient(tip, target)) {
                return getDirection("top", tip, target);
            }
            if (targetRect.left < tip.offsetWidth) {
                return "right";
            }
            return "left";
        case "right":
            if (!checkLeftRightWidthSufficient(tip, target)) {
                return getDirection("top", tip, target);
            }
            if (document.documentElement.clientWidth - targetRect.right <
                tip.offsetWidth) {
                return "left";
            }
            return "right";
        case "top":
            if (!hasSpaceAbove) {
                if (checkLeftRightWidthSufficient(tip, target)) {
                    return getDirection("left", tip, target);
                }
                return "bottom";
            }
            return "top";
        case "bottom":
        default:
            if (!hasSpaceBelow) {
                if (checkLeftRightWidthSufficient(tip, target)) {
                    return getDirection("right", tip, target);
                }
                if (hasSpaceAbove) {
                    return "top";
                }
            }
            return "bottom";
    }
}
function getTopBottomPosition(tip, target, direction, alignMode) {
    var left = -10000000;
    var top = -10000000;
    if (tip && target) {
        var scrollLeft = getScrollLeft();
        var targetRect = target.getBoundingClientRect();
        var targetLeft = targetRect.left + scrollLeft;
        var halfTargetWidth = Math.round(target.offsetWidth / 2);
        var tipWidth = tip.offsetWidth;
        if (alignMode === "left") {
            left = targetLeft;
        }
        else if (alignMode === "right") {
            var rightEdge = targetLeft + target.offsetWidth;
            left = Math.max(rightEdge - tipWidth, scrollLeft);
        }
        else {
            var centeredLeft = targetLeft + halfTargetWidth - Math.round(tipWidth / 2);
            left = Math.max(centeredLeft, scrollLeft);
        }
        var rightOfTip = left + tipWidth;
        var rightOfScreen = scrollLeft + document.documentElement.clientWidth;
        var rightOverhang = rightOfTip - rightOfScreen;
        if (rightOverhang > 0) {
            left -= rightOverhang;
        }
        if (direction === "top") {
            top = targetRect.top + getScrollTop() - tip.offsetHeight - MARGIN;
        }
        else {
            top = targetRect.bottom + getScrollTop() + MARGIN;
        }
    }
    return {
        left: left,
        top: top
    };
}
function getLeftRightPosition(tip, target, direction, alignMode) {
    var left = -10000000;
    var top = -10000000;
    if (tip && target) {
        var scrollTop = getScrollTop();
        var scrollLeft = getScrollLeft();
        var targetRect = target.getBoundingClientRect();
        var targetTop = targetRect.top + scrollTop;
        var halfTargetHeight = Math.round(target.offsetHeight / 2);
        if (alignMode === "top") {
            top = targetTop;
        }
        else if (alignMode === "bottom") {
            top = targetRect.bottom + scrollTop - tip.offsetHeight;
        }
        else {
            top = Math.max(targetTop + halfTargetHeight - Math.round(tip.offsetHeight / 2), scrollTop);
        }
        var bottomOverhang = top - scrollTop + tip.offsetHeight - window.innerHeight;
        var bottomOverhandCenter = top - scrollTop + tip.offsetHeight / 2 - window.innerHeight;
        if (bottomOverhang > 0) {
            top =
                bottomOverhandCenter > 0
                    ? target.offsetTop - tip.offsetHeight + target.offsetHeight
                    : target.offsetTop - tip.offsetHeight / 2 + target.offsetHeight;
        }
        if (top === 0) {
            top = target.offsetTop;
        }
        if (direction === "right") {
            left = targetRect.right + scrollLeft + MARGIN;
        }
        else {
            left = targetRect.left - tip.offsetWidth + scrollLeft - MARGIN;
        }
    }
    return {
        left: left,
        top: top
    };
}
export default function getPositions(direction, tip, target) {
    var realDirection = parseDirection(direction)[0];
    var alignMode = parseDirection(direction)[1];
    if (realDirection && tip && target) {
        realDirection = getDirection(realDirection, tip, target);
    }
    var position = realDirection === "top" || realDirection === "bottom"
        ? getTopBottomPosition(tip, target, realDirection, alignMode)
        : getLeftRightPosition(tip, target, realDirection, alignMode);
    return __assign({}, position);
}
