import { getDOMRect } from '../../lib/dom/getDOMRect.js';
import { getOwnerGlobalObject } from '../../lib/globalObject.js';
function getPositionObject(position) {
    var x = position.split(' ');
    return {
        direction: x[0],
        align: x[1],
    };
}
function getElementAbsoluteRect(element) {
    var globalObject = getOwnerGlobalObject(element);
    var rect = _getElementRelativeRect(element);
    return convertRectToAbsolute(rect, globalObject);
}
function isAbsoluteRectFullyVisible(coordinates, popupRect, globalObject) {
    var windowRelativeRect = _getWindowRelativeRect(globalObject);
    var windowAbsoluteRect = convertRectToAbsolute(windowRelativeRect, globalObject);
    var absoluteRect = {
        top: coordinates.top,
        left: coordinates.left,
        height: popupRect.height,
        width: popupRect.width,
    };
    return _rectContainsRect(windowAbsoluteRect, absoluteRect);
}
/** Может стать полностью видимым после прокрутки в область видимости */
function canBecomeFullyVisible(positionName, coordinates, globalObject) {
    var position = getPositionObject(positionName);
    if (position.direction === 'top') {
        var availableScrollDistances = convertRectToAbsolute(_getWindowRelativeRect(globalObject), globalObject);
        return coordinates.top + availableScrollDistances.top >= 0;
    }
    if (position.direction === 'left') {
        var availableScrollDistances = convertRectToAbsolute(_getWindowRelativeRect(globalObject), globalObject);
        return coordinates.left + availableScrollDistances.left >= 0;
    }
    // NOTE: в случаях bottom/right браузер всегда расширяет размер документа
    return true;
}
function _getElementRelativeRect(element) {
    var rect = getDOMRect(element);
    return {
        top: rect.top,
        left: rect.left,
        width: rect.right - rect.left,
        height: rect.bottom - rect.top,
    };
}
function _getWindowRelativeRect(globalObject) {
    return {
        top: 0,
        left: 0,
        width: _getViewProperty(function (x) { return x.clientWidth; }, globalObject) || globalObject.innerWidth || 0,
        height: _getViewProperty(function (x) { return x.clientHeight; }, globalObject) || globalObject.innerHeight || 0,
    };
}
function convertRectToAbsolute(rect, globalObject) {
    var offset = _getAbsoluteOffset(globalObject);
    return {
        top: rect.top + offset.top,
        left: rect.left + offset.left,
        width: rect.width,
        height: rect.height,
    };
}
function _getAbsoluteOffset(globalObject) {
    var scrollTop = globalObject.pageYOffset || _getViewProperty(function (x) { return x.scrollTop; }, globalObject);
    var scrollLeft = globalObject.pageXOffset || _getViewProperty(function (x) { return x.scrollLeft; }, globalObject);
    var clientTop = _getViewProperty(function (x) { return x.clientTop; }, globalObject);
    var clientLeft = _getViewProperty(function (x) { return x.clientLeft; }, globalObject);
    var top = scrollTop - clientTop;
    var left = scrollLeft - clientLeft;
    return {
        top: top,
        left: left,
    };
}
function _rectContainsRect(outerRect, innerRect) {
    return (innerRect.top > outerRect.top &&
        innerRect.top + innerRect.height < outerRect.top + outerRect.height &&
        innerRect.left > outerRect.left &&
        innerRect.left + innerRect.width < outerRect.left + outerRect.width);
}
/** Прямоугольник вьюпорта в координатах документа (абсолютных) */
function getViewportAbsoluteRect(globalObject) {
    return convertRectToAbsolute(_getWindowRelativeRect(globalObject), globalObject);
}
/** Какие стороны попапа (с заданными координатами) выходят за пределы вьюпорта */
function getOverflowEdges(coordinates, popupRect, globalObject) {
    var viewport = getViewportAbsoluteRect(globalObject);
    var popup = {
        top: coordinates.top,
        left: coordinates.left,
        width: popupRect.width,
        height: popupRect.height,
    };
    return {
        top: popup.top < viewport.top,
        bottom: popup.top + popup.height > viewport.top + viewport.height,
        left: popup.left < viewport.left,
        right: popup.left + popup.width > viewport.left + viewport.width,
    };
}
/** Количество сторон, по которым попап выходит за вьюпорт (0–4) */
function getOverflowCount(overflow) {
    return [overflow.top, overflow.bottom, overflow.left, overflow.right].filter(Boolean).length;
}
/** Предпочтительное направление по вертикали при переполнении */
function getPreferredDirection(overflow, defaultPosition) {
    if (overflow.bottom) {
        return 'top';
    }
    if (overflow.top) {
        return 'bottom';
    }
    return getPositionObject(defaultPosition).direction;
}
/**
 * Упорядоченный список кандидатов для fallback-позиции: при горизонтальном переполнении
 * сначала позиции с нужным align (в т.ч. из pinnablePositions), затем по direction и positions.
 */
function getOrderedFallbackCandidates(positions, overflow, preferredDirection, preferredAlignOrder, pinnablePositions) {
    var seen = new Set();
    var add = function (p) {
        if (!seen.has(p)) {
            seen.add(p);
            return true;
        }
        return false;
    };
    var candidates = [];
    var hasHorizontalOverflow = overflow.left || overflow.right;
    if (hasHorizontalOverflow) {
        var preferredAlign = preferredAlignOrder[0];
        for (var _i = 0, _a = ['bottom', 'top']; _i < _a.length; _i++) {
            var dir = _a[_i];
            var p = "".concat(dir, " ").concat(preferredAlign);
            if (pinnablePositions.includes(p) && add(p)) {
                candidates.push(p);
            }
        }
        for (var _b = 0, preferredAlignOrder_1 = preferredAlignOrder; _b < preferredAlignOrder_1.length; _b++) {
            var align = preferredAlignOrder_1[_b];
            for (var _c = 0, positions_1 = positions; _c < positions_1.length; _c++) {
                var p = positions_1[_c];
                if (getPositionObject(p).align === align && add(p)) {
                    candidates.push(p);
                }
            }
        }
    }
    for (var _d = 0, preferredAlignOrder_2 = preferredAlignOrder; _d < preferredAlignOrder_2.length; _d++) {
        var align = preferredAlignOrder_2[_d];
        for (var _e = 0, positions_2 = positions; _e < positions_2.length; _e++) {
            var p = positions_2[_e];
            var pos = getPositionObject(p);
            if (pos.direction === preferredDirection && pos.align === align && add(p)) {
                candidates.push(p);
            }
        }
    }
    for (var _f = 0, positions_3 = positions; _f < positions_3.length; _f++) {
        var p = positions_3[_f];
        if (getPositionObject(p).direction === preferredDirection && add(p)) {
            candidates.push(p);
        }
    }
    for (var _g = 0, positions_4 = positions; _g < positions_4.length; _g++) {
        var p = positions_4[_g];
        if (add(p)) {
            candidates.push(p);
        }
    }
    return candidates;
}
function _getViewProperty(getProperty, globalObject) {
    var _a, _b;
    var views = [(_a = globalObject.document) === null || _a === void 0 ? void 0 : _a.documentElement, (_b = globalObject.document) === null || _b === void 0 ? void 0 : _b.body];
    return views.map(function (x) { return x && getProperty(x); }).find(Boolean) || 0;
}
export var PopupHelper = {
    getPositionObject: getPositionObject,
    getElementAbsoluteRect: getElementAbsoluteRect,
    isFullyVisible: isAbsoluteRectFullyVisible,
    canBecomeFullyVisible: canBecomeFullyVisible,
    getViewportAbsoluteRect: getViewportAbsoluteRect,
    getOverflowEdges: getOverflowEdges,
    getOverflowCount: getOverflowCount,
    getPreferredDirection: getPreferredDirection,
    getOrderedFallbackCandidates: getOrderedFallbackCandidates,
};
//# sourceMappingURL=PopupHelper.js.map