import { TComponentState } from "../../../lib/Component";
import { DragContext, DragDiff } from "../../../services/drag";
import { BlockState } from "../../../store/block/Block";
import { GroupState, TGroup, TGroupId } from "../../../store/group/Group";
import { TMeasureTextOptions } from "../../../utils/functions/text";
import { TRect } from "../../../utils/types/shapes";
import { GraphComponent } from "../GraphComponent";
import { TGraphLayerContext } from "../layers/graphLayer/GraphLayer";
import { BlockGroups } from "./BlockGroups";
export type TGroupStyle = {
    background: string;
    border: string;
    borderWidth: number;
    selectedBackground: string;
    selectedBorder: string;
    /** Background color when group is highlighted (block is being dragged over it) */
    highlightedBackground: string;
    /** Border color when group is highlighted */
    highlightedBorder: string;
};
export type TGroupGeometry = {
    padding: [number, number, number, number];
};
export type TGroupProps = {
    id: TGroupId;
    onDragUpdate: (groupId: string, diff: {
        deltaX: number;
        deltaY: number;
    }) => void;
    style?: Partial<TGroupStyle>;
    geometry?: Partial<TGroupGeometry>;
    draggable?: boolean;
};
type TGroupState<T extends TGroup = TGroup> = TComponentState & T & {
    rect: TRect;
};
export declare class Group<T extends TGroup = TGroup> extends GraphComponent<TGroupProps, TGroupState<T>, TGraphLayerContext> {
    static define(config: {
        style?: Partial<TGroupStyle>;
        geometry?: Partial<TGroupGeometry>;
    }): typeof Group;
    get zIndex(): number;
    context: TGraphLayerContext;
    protected blocks: BlockState[];
    protected groupState: GroupState<T>;
    cursor: string;
    protected style: TGroupStyle;
    protected geometry: TGroupGeometry;
    /** Whether the group is highlighted (block is being dragged over it) */
    protected highlighted: boolean;
    /** Whether the group is currently being dragged */
    protected isDragging: boolean;
    protected dragStartRect: {
        x: number;
        y: number;
    } | null;
    protected lastSnappedPos: {
        x: number;
        y: number;
    } | null;
    constructor(props: TGroupProps, parent: BlockGroups);
    protected handleClick: (event: MouseEvent) => void;
    /**
     * Set the highlighted state of the group
     */
    setHighlighted(highlighted: boolean): void;
    /**
     * Check if the group is currently highlighted (block is being dragged over it).
     *
     * This method is useful for custom group components that override the `render()` method
     * and need to apply different styling when the group is highlighted during transfer mode.
     *
     * @returns `true` if the group is highlighted, `false` otherwise
     *
     * @example
     * ```typescript
     * class CustomGroup extends Group {
     *   protected override render() {
     *     const ctx = this.context.ctx;
     *     const rect = this.getRect();
     *
     *     // Apply different styles based on state
     *     if (this.isHighlighted()) {
     *       ctx.strokeStyle = 'rgba(100, 200, 100, 1)';
     *       ctx.lineWidth = 3;
     *     } else if (this.state.selected) {
     *       ctx.strokeStyle = 'rgba(100, 100, 100, 1)';
     *       ctx.lineWidth = 2;
     *     } else {
     *       ctx.strokeStyle = 'rgba(100, 100, 100, 0.4)';
     *       ctx.lineWidth = 1;
     *     }
     *
     *     ctx.beginPath();
     *     ctx.roundRect(rect.x, rect.y, rect.width, rect.height, 8);
     *     ctx.stroke();
     *   }
     * }
     * ```
     */
    isHighlighted(): boolean;
    getEntityId(): string;
    /**
     * Check if group can be dragged based on props.draggable and canDrag setting
     */
    isDraggable(): boolean;
    /**
     * Override to apply snapping or other position transforms during drag.
     * Called with the raw (pre-snap) target position computed from the drag start + cumulative diff.
     * The default implementation returns the position unchanged (no snapping).
     *
     * @example
     * ```typescript
     * protected override snapPosition(x: number, y: number) {
     *   const grid = 16;
     *   return { x: Math.round(x / grid) * grid, y: Math.round(y / grid) * grid };
     * }
     * ```
     */
    protected snapPosition(x: number, y: number): {
        x: number;
        y: number;
    };
    /**
     * Handle drag start - stores the initial rect position and sets isDragging flag.
     * Subclasses that override this method should call super.handleDragStart() to preserve this behavior.
     */
    handleDragStart(_context: DragContext): void;
    /**
     * Handle drag update - moves the group rect and notifies via onDragUpdate.
     * Uses the cumulative diff from drag start so that snapPosition always operates
     * on the absolute target position (avoids error accumulation from per-frame deltas).
     * onDragUpdate is called only when the position actually changes.
     */
    handleDrag(diff: DragDiff, _context: DragContext): void;
    /**
     * Handle drag end - clears isDragging flag and drag tracking state.
     * Subclasses that override this method should call super.handleDragEnd() to preserve this behavior.
     */
    handleDragEnd(_context: DragContext): void;
    protected getRect(rect?: TRect): {
        x: number;
        y: number;
        width: number;
        height: number;
    };
    protected subscribeToGroup(): void;
    protected unmount(): void;
    protected updateHitBox(rect: TRect): void;
    protected layoutText(text: string, textParams?: TMeasureTextOptions): {
        measures: import("../../../utils/functions/text").TWrapText;
        lines: any[];
        lineHeight: number;
    };
    protected renderBody(ctx: CanvasRenderingContext2D, rect?: {
        x: number;
        y: number;
        width: number;
        height: number;
    }): void;
    protected render(): void;
}
export {};
