function _check_private_redeclaration(obj, privateCollection) {
    if (privateCollection.has(obj)) {
        throw new TypeError("Cannot initialize the same private elements twice on an object");
    }
}
function _class_apply_descriptor_get(receiver, descriptor) {
    if (descriptor.get) {
        return descriptor.get.call(receiver);
    }
    return descriptor.value;
}
function _class_apply_descriptor_set(receiver, descriptor, value) {
    if (descriptor.set) {
        descriptor.set.call(receiver, value);
    } else {
        if (!descriptor.writable) {
            throw new TypeError("attempted to set read only private field");
        }
        descriptor.value = value;
    }
}
function _class_extract_field_descriptor(receiver, privateMap, action) {
    if (!privateMap.has(receiver)) {
        throw new TypeError("attempted to " + action + " private field on non-instance");
    }
    return privateMap.get(receiver);
}
function _class_private_field_get(receiver, privateMap) {
    var descriptor = _class_extract_field_descriptor(receiver, privateMap, "get");
    return _class_apply_descriptor_get(receiver, descriptor);
}
function _class_private_field_init(obj, privateMap, value) {
    _check_private_redeclaration(obj, privateMap);
    privateMap.set(obj, value);
}
function _class_private_field_set(receiver, privateMap, value) {
    var descriptor = _class_extract_field_descriptor(receiver, privateMap, "set");
    _class_apply_descriptor_set(receiver, descriptor, value);
    return value;
}
import { Cursor } from './cursor.mjs';
var /**
   * The menu container element the positioning will be applied to.
   *
   * @type {HTMLElement}
   */ _container = /*#__PURE__*/ new WeakMap(), /**
   * For positioning the submenu, the parent element is used to calculate offsets to ensure that submenu
   * is positioned right next to the parent menu.
   *
   * @type {HTMLElement}
   */ _parentContainer = /*#__PURE__*/ new WeakMap(), /**
   * The instance of the Cursor class.
   *
   * @type {Cursor}
   */ _cursor = /*#__PURE__*/ new WeakMap(), /**
   * Enabling the option allows changing the position calculation so that the menus (or submenus)
   * are always placed within the visible viewport of the browser.
   *
   * @type {boolean}
   */ _keepInViewport = /*#__PURE__*/ new WeakMap(), /**
   * Allows apply the position offset for directions.
   *
   * @type {{above: number, below: number, left: number, right: number}}
   */ _offset = /*#__PURE__*/ new WeakMap();
/**
 * Helper class for positioning the menu and submenus in the correct place relative to the
 * cursor position (DOM element or mouse coordinates).
 *
 * @private
 * @class Positioner
 */ export class Positioner {
    /**
   * Sets offset position for specified directions (`above`, `below`, `left` or `right`).
   *
   * @param {'above' | 'below' | 'left' | 'right'} direction A direction name.
   * @param {number} [offset=0] Offset value.
   * @returns {Positioner}
   */ setOffset(direction, offset = 0) {
        _class_private_field_get(this, _offset)[direction] = offset;
        return this;
    }
    /**
   * Sets the menu element to work with. The element can be owned by the main menu or the submenu.
   *
   * @param {HTMLElement} container The menu container element.
   * @returns {Positioner}
   */ setElement(container) {
        _class_private_field_set(this, _container, container);
        return this;
    }
    /**
   * Sets the parent menu element to work with.
   *
   * @param {HTMLElement} container The parent menu container element.
   * @returns {Positioner}
   */ setParentElement(container) {
        _class_private_field_set(this, _parentContainer, container);
        return this;
    }
    /**
   * Updates the menu position.
   *
   * @param {object|MouseEvent} coords The literal object with `top`, `left`, `width` and `height` props or a
   * mouse event object.
   */ updatePosition(coords) {
        _class_private_field_set(this, _cursor, new Cursor(coords, _class_private_field_get(this, _container).ownerDocument.defaultView));
        if (_class_private_field_get(this, _keepInViewport)) {
            if (_class_private_field_get(this, _cursor).fitsBelow(_class_private_field_get(this, _container))) {
                this.setPositionBelowCursor();
            } else if (_class_private_field_get(this, _cursor).fitsAbove(_class_private_field_get(this, _container))) {
                this.setPositionAboveCursor();
            } else {
                this.setPositionBelowCursor();
            }
            this.updateHorizontalPosition();
        } else {
            this.setPositionBelowCursor();
            this.setPositionOnRightOfCursor();
        }
    }
    /**
   * Updates the menu horizontal position.
   */ updateHorizontalPosition() {
        if (_class_private_field_get(this, _container).dir === 'rtl') {
            if (_class_private_field_get(this, _cursor).fitsOnLeft(_class_private_field_get(this, _container))) {
                this.setPositionOnLeftOfCursor();
            } else {
                this.setPositionOnRightOfCursor();
            }
        } else if (_class_private_field_get(this, _cursor).fitsOnRight(_class_private_field_get(this, _container))) {
            this.setPositionOnRightOfCursor();
        } else {
            this.setPositionOnLeftOfCursor();
        }
    }
    /**
   * Sets the menu position above the cursor object.
   */ setPositionAboveCursor() {
        let top = _class_private_field_get(this, _offset).above + _class_private_field_get(this, _cursor).top - _class_private_field_get(this, _container).offsetHeight;
        if (_class_private_field_get(this, _parentContainer)) {
            const rootWindow = _class_private_field_get(this, _parentContainer).ownerDocument.defaultView;
            const style = rootWindow.getComputedStyle(_class_private_field_get(this, _parentContainer).querySelector('.ht_master'));
            const paddingTop = Number.parseInt(style.paddingTop, 10);
            const borderTop = Number.parseInt(style.borderTop, 10);
            top = _class_private_field_get(this, _cursor).top + _class_private_field_get(this, _cursor).cellHeight - _class_private_field_get(this, _container).scrollHeight + paddingTop + borderTop;
        }
        _class_private_field_get(this, _container).style.top = `${top}px`;
    }
    /**
   * Sets the menu position below the cursor object.
   */ setPositionBelowCursor() {
        let top = _class_private_field_get(this, _offset).below + _class_private_field_get(this, _cursor).top + 1;
        if (_class_private_field_get(this, _parentContainer)) {
            const rootWindow = _class_private_field_get(this, _parentContainer).ownerDocument.defaultView;
            const style = rootWindow.getComputedStyle(_class_private_field_get(this, _parentContainer).querySelector('.ht_master'));
            const paddingTop = Number.parseInt(style.paddingTop, 10);
            const borderTop = Number.parseInt(style.borderTop, 10);
            top = _class_private_field_get(this, _cursor).top - paddingTop - borderTop;
        }
        _class_private_field_get(this, _container).style.top = `${top}px`;
    }
    /**
   * Sets the menu position on the right of the cursor object.
   */ setPositionOnRightOfCursor() {
        let left = _class_private_field_get(this, _cursor).left;
        if (_class_private_field_get(this, _parentContainer)) {
            const rootWindow = _class_private_field_get(this, _parentContainer).ownerDocument.defaultView;
            const borderRightWidth = Number.parseInt(rootWindow.getComputedStyle(_class_private_field_get(this, _parentContainer).querySelector('.htCore')).borderRightWidth, 10);
            left += _class_private_field_get(this, _cursor).cellWidth + borderRightWidth;
        } else {
            left += _class_private_field_get(this, _offset).right;
        }
        _class_private_field_get(this, _container).style.left = `${left}px`;
    }
    /**
   * Sets the menu position on the left of the cursor object.
   */ setPositionOnLeftOfCursor() {
        let left = _class_private_field_get(this, _offset).left + _class_private_field_get(this, _cursor).left - _class_private_field_get(this, _container).offsetWidth;
        if (_class_private_field_get(this, _parentContainer)) {
            const rootWindow = _class_private_field_get(this, _parentContainer).ownerDocument.defaultView;
            const borderLeftWidth = Number.parseInt(rootWindow.getComputedStyle(_class_private_field_get(this, _parentContainer).querySelector('.htCore')).borderLeftWidth, 10);
            left -= borderLeftWidth;
        }
        _class_private_field_get(this, _container).style.left = `${left}px`;
    }
    constructor(keepInViewport){
        _class_private_field_init(this, _container, {
            writable: true,
            value: void 0
        });
        _class_private_field_init(this, _parentContainer, {
            writable: true,
            value: void 0
        });
        _class_private_field_init(this, _cursor, {
            writable: true,
            value: void 0
        });
        _class_private_field_init(this, _keepInViewport, {
            writable: true,
            value: void 0
        });
        _class_private_field_init(this, _offset, {
            writable: true,
            value: void 0
        });
        _class_private_field_set(this, _keepInViewport, false);
        _class_private_field_set(this, _offset, {
            above: 0,
            below: 0,
            left: 0,
            right: 0
        });
        _class_private_field_set(this, _keepInViewport, keepInViewport);
    }
}
