// Minimum portal height (chromium limitation)
const MIN_HEIGHT = 100;
/**
 * Returns a drop down menu's position relative to the toolbar's current location and the
 * MenuToggle that was pressed. The dimensions returned are relative to the toolbar's
 * current monitor.
 * @param menuId The shell ID (e.g. filemenu)
 * @param menuContentHeight The height of menu contents.
 */
export const calculatePosition = async (menuId, menuContentHeight) => {
    var _a, _b;
    // Rather than use window.innerHeight, we use the height of the document because Electron at times fails
    // to resize windows across monitors with different DPI scaling.  We've worked around this by calling setShape()
    // to avoid a white bar at the bottom of the window, but the window DOM height is still the old height.
    const toolbarHeight = document.getElementsByClassName("finsemble-toolbar")[0].offsetHeight;
    // The monitor's available height and width is found in the window.screen object (just like Electron, less the space
    // taken up by the operating system toolbar)
    const { availHeight } = window.screen;
    // Non-standard. Specifies the y-coordinate of the first pixel that is not allocated to permanent or semipermanent user interface features.
    // https://developer.mozilla.org/en-US/docs/Web/API/Screen/availTop
    const availTop = (_b = (_a = window.screen) === null || _a === void 0 ? void 0 : _a.availTop) !== null && _b !== void 0 ? _b : 0;
    const toolbarX = window.screenLeft;
    const toolbarY = window.screenTop;
    const spaceBelowToolbar = availHeight + availTop - toolbarY - toolbarHeight;
    /*
    Get a reference to the MenuToggle's element using querySelector to avoid having to pass
    React ref all the way down here.
    */
    const selector = `#${menuId}-menu-toggle`;
    const menuToggle = document.querySelector(selector);
    if (!menuToggle) {
        console.error(`calculatePosition() can't find selector "${selector}"`);
    }
    // Get the "x" coordinate of our toggle button *within* the toolbar
    // If for whatever reason the menuToggle can't be found, then default to an x coordinate of zero
    const { x: menuToggleX } = menuToggle ? menuToggle.getBoundingClientRect() : { x: 0 };
    let left = toolbarX + menuToggleX;
    let top = toolbarY + toolbarHeight;
    const toolbarMidpoint = toolbarY + toolbarHeight / 2;
    const screenMidpoint = availHeight / 2;
    /*
    Check if we have enough space for the menu between
    the toolbar and bottom edge of the screen. If not,
    then reposition the menu to appear above toolbar.
    */
    if (menuContentHeight) {
        const menuHeight = Math.max(menuContentHeight, MIN_HEIGHT);
        if (menuHeight > spaceBelowToolbar && toolbarMidpoint > screenMidpoint) {
            top = toolbarY - menuHeight;
        }
    }
    return {
        top,
        left,
    };
};
/**
 * Calculates the height and position that a window should take based on the height necessary to display
 * the window's DOM contents without scrollbars, but not beyond the scope of the monitor itself.
 *
 * @param childWindow Window The window to calculate
 * @param menuId string The id of the menu, used for a CSS selector
 * @param [maxHeight] Maximum height for the window
 * @param [fixedHeight] Optional fixed height
 */
export const calculateDimensions = async (childWindow, menuId, fixedHeight = 0, maxHeight = Infinity, minHeight) => {
    /* Content height is essentially the offsetHeight of the window's <html> element.
    This seems more reliable than summing the heights of all body children.
    */
    const contentHeight = childWindow.document.documentElement.offsetHeight;
    /**
     * Calculate the actual menu height, constrained by maximum and minimum sizes.
     * Zero, null or undefined are invalid maximum heights.
     *
     * Chromium imposes a 100 pixel minimum on window height.
     */
    const CHROMIUM_MIN_HEIGHT = minHeight !== null && minHeight !== void 0 ? minHeight : 0;
    const minimumContentHeight = Math.max(contentHeight, CHROMIUM_MIN_HEIGHT);
    const height = fixedHeight ? fixedHeight : Math.min(minimumContentHeight, maxHeight);
    const { left, top } = await calculatePosition(menuId, height);
    // Final step, make sure the menu isn't larger than the screen itself
    const { availHeight } = window.screen;
    const finalHeight = Math.min(height, availHeight);
    return {
        top,
        left,
        height: finalHeight,
    };
};
/**
 * Copy CSS elements from parent to child window. Portals operate in a new window which doesn't automatically
 * have access to the CSS from the main window, so we need to clone those elements into the menu's window
 * when it is created.
 * @param childWindow Child window reference
 */
export const injectCSS = (childWindow) => {
    const { children } = document.head;
    const styleElements = [];
    for (const item in children) {
        /**
            webpack's style-loader creates <style> tags but some versions will create <link> tags if CSS source maps are
            enabled (sourceMap), or if `injectType: linkTag` is configured.
        */
        if (children[item].tagName === "STYLE" || children[item].tagName === "LINK") {
            const newElement = children[item].cloneNode(true);
            styleElements.push(newElement);
        }
    }
    styleElements.forEach((item) => {
        childWindow.document.head.append(item);
    });
};
//# sourceMappingURL=menuHelpers.js.map