import type { DragState } from "../../../services/drag/types";
import { TBlock } from "../blocks/Block";
import { BlockGroups, BlockGroupsProps } from "./BlockGroups";
import { Group } from "./Group";
/**
 * Callback called when block transfer starts (Shift pressed during drag)
 * @param blockIds - IDs of blocks being transferred
 * @param sourceGroupIds - Set of source group IDs (groups blocks came from)
 */
export type OnTransferStart = (blockIds: TBlock["id"][], sourceGroupIds: Set<string>) => void;
/**
 * Callback called when block transfer ends (mouse released or Shift released)
 * @param blockIds - IDs of blocks that were transferred
 * @param targetGroupId - Target group ID (null if removed from group)
 */
export type OnTransferEnd = (blockIds: TBlock["id"][], targetGroupId: string | null) => void;
/**
 * Object representing a change in block's group membership
 */
export type TBlockGroupsTransferGroupChange = {
    blockId: TBlock["id"];
    sourceGroup?: string | null;
    targetGroup?: string | null;
};
/**
 * Callback called when blocks' groups change
 * @param changes - Array of changes to apply
 */
export type OnBlockGroupChange = (changes: TBlockGroupsTransferGroupChange[]) => void;
export type BlockGroupsTransferLayerProps = BlockGroupsProps & {
    /**
     * Enable/disable block transfer between groups with Shift+drag.
     * Default: true
     */
    transferEnabled?: boolean;
    /**
     * Called when block transfer starts (Shift pressed during drag)
     */
    onTransferStart?: OnTransferStart;
    /**
     * Called when block transfer ends (mouse released or Shift released)
     */
    onTransferEnd?: OnTransferEnd;
    /**
     * Called when a block's group changes
     */
    onBlockGroupChange?: OnBlockGroupChange;
    /**
     * If true, blocks will move when the group is dragged
     */
    updateBlocksOnDrag?: boolean;
};
type TransferState = {
    isTransferring: boolean;
    /** All blocks being transferred */
    blocks: TBlock[];
    /** Source group IDs for each block (null if block was not in a group) */
    sourceGroupIds: Set<string>;
    /** Current target group ID */
    targetGroupId: string | null;
    /** Currently highlighted group ID */
    highlightedGroupId: string | null;
};
/**
 * BlockGroups layer with block-to-group transfer functionality.
 *
 * ## Features
 * - Hold Shift during drag to activate transfer mode
 * - Release Shift to deactivate transfer mode and return to normal drag
 * - Groups highlight when blocks are dragged over them
 * - Multi-block transfer: all selected blocks are transferred together
 * - Source groups lock their size during transfer
 * - Callbacks for state synchronization with external stores (Redux, MobX, etc.)
 *
 * ## Basic Usage
 * ```typescript
 * const layer = graph.addLayer(BlockGroupsTransferLayer, {
 *   transferEnabled: true,
 *   draggable: true,
 * });
 * ```
 *
 * ## With Automatic Grouping
 * ```typescript
 * const GroupsLayer = BlockGroupsTransferLayer.withBlockGrouping({
 *   groupingFn: (blocks) => groupBy(blocks, (b) => b.$state.value.group),
 *   mapToGroups: (groupId, { rect }) => ({ id: groupId, rect }),
 * });
 *
 * graph.addLayer(GroupsLayer, {
 *   transferEnabled: true,
 *   updateBlocksOnDrag: true, // Blocks move with the group
 * });
 * ```
 *
 * ## With Redux Integration
 * ```typescript
 * graph.addLayer(GroupsLayer, {
 *   onTransferStart: (blockIds, sourceGroupIds) => {
 *     console.log('Transfer started:', blockIds);
 *   },
 *   onBlockGroupChange: (changes) => {
 *     // Sync with Redux
 *     changes.forEach(({ blockId, targetGroup }) => {
 *       store.dispatch(updateBlockGroup({ blockId, groupId: targetGroup }));
 *     });
 *   },
 *   onTransferEnd: (blockIds, targetGroupId) => {
 *     console.log('Transfer completed:', blockIds, 'to group:', targetGroupId);
 *   },
 * });
 * ```
 *
 * Uses DragService.$state.currentEvent.shiftKey to track Shift state in real-time.
 */
export declare class BlockGroupsTransferLayer<P extends BlockGroupsTransferLayerProps = BlockGroupsTransferLayerProps> extends BlockGroups<P> {
    /** Current transfer state */
    protected transferState: TransferState;
    /** Cleanup function for the drag state subscription */
    protected disposeSubscription: (() => void) | null;
    protected get isTransferEnabled(): boolean;
    protected afterInit(): void;
    /**
     * Subscribe to DragService state changes
     */
    protected subscribeToDragState(): void;
    /**
     * Handle drag state changes - react to Shift key in real-time
     */
    protected handleDragStateChange(dragState: DragState, isShiftPressed: boolean): void;
    /**
     * Activate transfer mode for currently dragged blocks
     */
    protected activateTransfer(dragState: DragState): void;
    /**
     * Deactivate transfer mode - apply transfer and unlock groups
     * Called when Shift is released during drag
     */
    protected deactivateTransfer(): void;
    /**
     * Lock all groups' sizes
     */
    protected lockAllGroups(): void;
    /**
     * Unlock all groups' sizes
     */
    protected unlockAllGroups(): void;
    protected createIdleState(): TransferState;
    /**
     * Update highlighting based on cursor position
     */
    protected updateHighlight(point: [number, number]): void;
    /**
     * End transfer on drag end (mouseup) - apply transfer if in transfer mode
     */
    protected endTransfer(): void;
    /**
     * Cancel the transfer operation without applying changes.
     *
     * This method can be called to abort an ongoing transfer without moving blocks to a new group.
     * It will unhighlight groups, unlock sizes, and reset the transfer state.
     *
     * @example
     * ```typescript
     * // Cancel transfer on Escape key
     * document.addEventListener('keydown', (e) => {
     *   if (e.key === 'Escape' && layer.isTransferring()) {
     *     layer.cancelTransfer();
     *   }
     * });
     * ```
     */
    cancelTransfer(): void;
    /**
     * Find a group at the given point
     */
    protected findGroupAtPoint(point: [number, number]): Group | null;
    /**
     * Set highlight state for a group directly on the component
     */
    protected setGroupHighlight(groupId: string, highlighted: boolean): void;
    /**
     * Apply the group change to the block
     */
    protected applyGroupChange(changes: TBlockGroupsTransferGroupChange[]): void;
    /**
     * Check if a block transfer is currently in progress.
     *
     * @returns `true` if transfer mode is active (Shift is pressed during drag), `false` otherwise
     *
     * @example
     * ```typescript
     * if (layer.isTransferring()) {
     *   console.log('Transferring', layer.getTransferringBlocksCount(), 'blocks');
     * }
     * ```
     */
    isTransferring(): boolean;
    /**
     * Get the number of blocks being transferred in the current operation.
     *
     * @returns Number of blocks currently being transferred, or 0 if no transfer is in progress
     *
     * @example
     * ```typescript
     * const count = layer.getTransferringBlocksCount();
     * console.log(`Transferring ${count} block${count !== 1 ? 's' : ''}`);
     * ```
     */
    getTransferringBlocksCount(): number;
    protected unmountLayer(): void;
}
export {};
