import { VegaSlimmer } from '../../../vega-slimmer/vega-slimmer-core';
import { Nullable } from '../../../types/general';
import { ElementBoundBox, ElementPositionBox, ElementScrollDimension, PlacementType, PositionAlignmentType } from '../../../types/ui.type';
import { ElementAppenderShowConfig } from '../../ui/element-appender';
/**
 * calculate position
 */
export declare abstract class BasePositionCalculationStrategy extends VegaSlimmer {
  abstract showConfig: ElementAppenderShowConfig;
  /**
   * Whether the controller should adjust/recompute position at this time.
   *
   * This hook allows strategies to avoid unnecessary work (for example, on scroll) by deciding
   * whether a re-position is required.
   *
   * @returns {boolean} True when the controller should proceed with width/height/position adjustments.
   */
  shouldAdjustPosition(): boolean;
  /**
   * Get the position box.
   *
   * @param {PlacementType[]} placement - previous placement.
   * @param {PositionAlignmentType[]} alignment - previous placement.
   * @returns {ElementPositionBox} A function that takes in a container, element, target, placement, and translocation and
   * returns an ElementPositionBox.
   */
  protected getPositionBox(placement?: PlacementType[], alignment?: PositionAlignmentType[]): ElementPositionBox;
  /**
   * Whether the alignment space is enough
   *
   * @param {ElementScrollDimension} containerBox - The bounding box of the container element.
   * @param {ElementBoundBox} targetBox - The position of the target element.
   * @param {ElementBoundBox} elementBox - The box of the element that we're trying to position.
   * @param {PlacementType} placement - The placement of the element relative to the target.
   * @param {PlacementType} alignment - The alignment of the element relative to the target.
   * @returns {boolean} return true if it has enough space, otherwise false
   */
  protected hasEnoughAlignmentSpace(containerBox: ElementScrollDimension, targetBox: ElementBoundBox, elementBox: ElementBoundBox, placement: PlacementType, alignment: PositionAlignmentType): boolean;
  /**
   * Calculate the left position of the element
   *
   * @param {ElementBoundBox} elementBox - The position box of the element.
   * @param {ElementBoundBox} targetBox - The position box of the target element that is attached to.
   * @param {PlacementType} placement - The placement of the element.
   * @param {PositionAlignmentType} alignment - The alignment of the element
   * @returns {number} The left position of the element.
   */
  protected calculateLeft(elementBox: ElementBoundBox, targetBox: ElementBoundBox, placement: PlacementType, alignment: PositionAlignmentType): number;
  /**
   * Calculate the top position of the element
   *
   * @param {ElementBoundBox} elementBox - The position box of the element.
   * @param {ElementBoundBox} targetBox - The position box of the target element that is attached to.
   * @param {PlacementType} placement - The placement of the element.
   * @param {PositionAlignmentType} alignment - The alignment of the element
   * @returns {number} the top position of the element.
   */
  protected calculateTop(elementBox: ElementBoundBox, targetBox: ElementBoundBox, placement: PlacementType, alignment: PositionAlignmentType): number;
  /**
   * It returns acceptable alignments.
   *
   * @returns {PositionAlignmentType[]} acceptable alignments
   */
  protected getAlignments(): PositionAlignmentType[];
  /**
   * It takes a list of placements and returns the first placement that has enough space to place the
   * element
   *
   * @param {ElementScrollDimension} containerBox - The box of the container element.
   * @param {ElementBoundBox} elementBox - The box of the element to be placed.
   * @param {ElementBoundBox} targetBox - The box of the target element.
   * @param {PlacementType[]} placements - The placements that we want to try.
   * @returns {Nullable<PlacementType>} A function that takes in a containerBox, elementBox, targetBox, placements, and element.
   */
  protected getSuitablePlacement(containerBox: ElementScrollDimension, elementBox: ElementBoundBox, targetBox: ElementBoundBox, placements: PlacementType[]): Nullable<PlacementType>;
  /**
   * "Get the width, height, and top position of an element."
   *
   * The function takes an element as an argument and returns an object with three properties: width,
   * height, and top.
   *
   * Note: If element is hide, we should temporary change it to `block` to get the bounding client rect of element,
   * After do that, this element will change to origin `hide`, if not, it will be contained in the calculate of `document.documentElement.scrollHeight`
   *
   * @returns {ElementBoundBox} An object with the width, height, and top properties of the element.
   */
  private getElementBoundBox;
  /**
   * It takes a placement string or array of placements and returns an array of placements
   * if given placement is single, we should completion the placements with the default {@link Placements}
   * and make given placement as default.
   * if given placement is array, we should use it directly, even it partial of {@link Placements}.
   * if not placement give. we should use {@link Placements}.
   *
   * @returns {PlacementType[]} ordered placements.
   */
  private getPlacements;
  /**
   * It takes a placement, a target box, and a element box, and returns an element box
   *
   * @param {ElementBoundBox} elementBox - The position of the element element.
   * @param {ElementBoundBox} targetBox - The position of the target element.
   * @param {PlacementType} placement - The placement of the element.
   * @param {PositionAlignmentType} alignment - The alignment of the element
   * @returns {ElementPositionBox} An object with top and left properties.
   */
  private calculatePosition;
  /**
   * Keeps the vertical position within the visible viewport
   *
   * @param {number} top - The calculated top position.
   * @param {number} elementHeight - The height of the element.
   * @returns {number} The top position constrained to the viewport.
   */
  private keepVerticallyInView;
  /**
   * Keeps the horizontal position within the visible viewport
   *
   * @param {number} left - The calculated left position.
   * @param {number} elementWidth - The width of the element.
   * @returns {number} The left position constrained to the viewport.
   */
  private keepHorizontallyInView;
  /**
   * Checks if the target element is visible in the viewport
   *
   * @param {ElementBoundBox} targetBox - The bounding box of the target element.
   * @returns {boolean} True if target is visible in viewport.
   */
  private isTargetInView;
  /**
   * Corrects `positionBox` so the element stays within the viewport after translocation.
   * Only runs when the target is visible; skips correction entirely if the target has
   * scrolled out of view so the element simply follows it.
   *
   * @param {ElementPositionBox} positionBox - The final position box to adjust (mutated in place).
   * @param {ElementBoundBox} elementBox - Dimensions of the positioned element.
   * @param {ElementBoundBox} targetBox - Bounding box of the target element.
   * @param {PlacementType} placement - Active placement used to select the correction axis.
   */
  private adjustPositionForViewport;
  /**
   * Nudges `top` so the element stays within the viewport vertically.
   * Only corrects when the overflow is less than `targetHeight` to keep the element
   * visually anchored to its target; larger overflows are handled by `keepVerticallyInView`.
   *
   * @param {number} top - The calculated top position.
   * @param {number} elementHeight - Height of the positioned element.
   * @param {number} targetHeight - Height of the target, used as the max correctable overflow.
   * @returns {number} The adjusted top position.
   */
  private adjustForVerticalOverflow;
  /**
   * Nudges `left` so the element stays within the viewport horizontally.
   * Only corrects when the overflow is less than `targetWidth` to keep the element
   * visually anchored to its target; larger overflows are handled by `keepHorizontallyInView`.
   *
   * @param {number} left - The calculated left position.
   * @param {number} elementWidth - Width of the positioned element.
   * @param {number} targetWidth - Width of the target, used as the max correctable overflow.
   * @returns {number} The adjusted left position.
   */
  private adjustForHorizontalOverflow;
  /**
   * It returns the translocation of the element relative to the target element
   *
   * @param {PlacementType} placement - The suitable placement of the element.
   * @returns {TranslocationType} A translocation object with X and Y properties.
   */
  private getTranslocationBox;
  /**
   * It takes a list of alignments and returns the suitable one that has enough space to fit the element
   *
   * @param {ElementScrollDimension} containerBox - The bounding box of the container element.
   * @param {ElementBoundBox} elementBox - The box of the element that we want to position.
   * @param {ElementBoundBox} targetBox - The box of the element that the element to be positioned is aligned to.
   * @param {PlacementType} placement - The placement of the element relative to the target.
   * @param {PositionAlignmentType[]} alignments - An array of alignments to try.
   * @returns {Nullable<PositionAlignmentType>} the alignment that is suitable for the element.
   */
  private getSuitableAlignment;
  /**
   * If the placement is top or left, then the target's top or left position must be greater than or
   * equal to the element's height or width. If the placement is bottom or right, then the container's
   * height or width minus the target's top or left position minus the target's height or width must be
   * greater than or equal to the element's height or width.
   *
   * @param {ElementScrollDimension} containerBox - The bounding box of the container element.
   * @param {PlacementType} placement - The placement of the element.
   * @param {ElementBoundBox} targetBox - The position of the target element.
   * @param {ElementBoundBox} elementBox - The dimensions of the element to be positioned.
   * @returns {boolean} A boolean value.
   */
  private hasEnoughSpace;
  /**
   * Retrieves and formats the translocation.
   *
   * @returns {Nullable<TranslocationType>} current translocation.
   */
  private getTranslocation;
  abstract getPosition(usePreviousPlacement?: boolean): ElementPositionBox;
  protected abstract getTargetBoundBox(): ElementBoundBox;
  protected abstract getElementScrollDimension(): ElementScrollDimension;
}
