// WASM bindings - types are auto-generated by tsify.
//
// This module provides a thin wrapper around the WASM module,
// initializing it and re-exporting types for TypeScript usage.

// Import auto-generated types from WASM package
import type {
  ScreenPosition,
  Size,
  Rect,
  Direction,
  SplitDirection,
  LogicalLayout,
  WindowTree,
  Window,
  LogicalOverlay,
  RenderedOverlay,
  OverlayState,
  OverlayStack,
  ViewportState,
  ViewportUpdate,
  ClientPresence,
  SyncMode,
  PanelState,
  SemanticOrigin,
  ExtensionCategory,
  Interaction,
  InteractionResult,
  LayoutSyncMode,
  OverlaySyncMode,
  PresenceTracker,
} from "../../pkg/reovim_client_model.js";

// Re-export types for convenience
export type {
  ScreenPosition,
  Size,
  Rect,
  Direction,
  SplitDirection,
  LogicalLayout,
  WindowTree,
  Window,
  LogicalOverlay,
  RenderedOverlay,
  OverlayState,
  OverlayStack,
  ViewportState,
  ViewportUpdate,
  ClientPresence,
  SyncMode,
  PanelState,
  SemanticOrigin,
  ExtensionCategory,
  Interaction,
  InteractionResult,
  LayoutSyncMode,
  OverlaySyncMode,
  PresenceTracker,
};

// WASM module singleton
let wasmModule: typeof import("../../pkg/reovim_client_model.js") | null = null;

/**
 * Initialize the WASM module. Must be called before any other functions.
 *
 * This is idempotent - calling it multiple times is safe.
 */
export async function initWasm(): Promise<void> {
  if (wasmModule) return;
  wasmModule = await import("../../pkg/reovim_client_model.js");
  await wasmModule.default(); // Initialize WASM (calls init() start function)
}

/**
 * Check if WASM module is initialized.
 */
export function isWasmReady(): boolean {
  return wasmModule !== null;
}

function ensureWasm(): NonNullable<typeof wasmModule> {
  if (!wasmModule) {
    throw new Error("WASM not initialized. Call initWasm() first.");
  }
  return wasmModule;
}

// ============ Layout Functions ============

/**
 * Interpret a logical layout into a window tree with computed bounds.
 *
 * This is the core layout function that converts server-side logical layout
 * into client-side rendered window positions.
 *
 * @param logical - The logical layout from the server
 * @param width - Screen width in columns
 * @param height - Screen height in rows
 * @returns WindowTree with computed bounds for each window
 */
export function interpretLayout(
  logical: LogicalLayout,
  width: number,
  height: number
): WindowTree {
  return ensureWasm().interpret_layout(logical, width, height);
}

/**
 * Create a single-window logical layout.
 */
export function layoutSingle(
  bufferId: bigint,
  viewportId: bigint
): LogicalLayout {
  return ensureWasm().layout_single(bufferId, viewportId);
}

/**
 * Create a horizontal split layout (windows stacked vertically).
 */
export function layoutHsplit(children: LogicalLayout[]): LogicalLayout {
  return ensureWasm().layout_hsplit(children);
}

/**
 * Create a vertical split layout (windows side by side).
 */
export function layoutVsplit(children: LogicalLayout[]): LogicalLayout {
  return ensureWasm().layout_vsplit(children);
}

/**
 * Check if a logical layout is a single window (leaf).
 */
export function layoutIsLeaf(layout: LogicalLayout): boolean {
  return ensureWasm().layout_is_leaf(layout);
}

/**
 * Get window count from a logical layout.
 */
export function layoutWindowCount(layout: LogicalLayout): number {
  return ensureWasm().layout_window_count(layout);
}

// ============ Geometry Functions ============

/**
 * Check if a point is inside a rectangle.
 *
 * @param rect - The rectangle to check
 * @param x - X coordinate of the point
 * @param y - Y coordinate of the point
 * @returns true if point is inside (exclusive of right/bottom edges)
 */
export function rectContains(rect: Rect, x: number, y: number): boolean {
  return ensureWasm().rect_contains(rect, x, y);
}

// ============ Direction Functions ============

/**
 * Get the opposite direction.
 *
 * Up <-> Down, Left <-> Right
 */
export function directionOpposite(dir: Direction): Direction {
  return ensureWasm().direction_opposite(dir);
}

/**
 * Check if a direction is horizontal (Left or Right).
 */
export function directionIsHorizontal(dir: Direction): boolean {
  return ensureWasm().direction_is_horizontal(dir);
}

/**
 * Check if a direction is vertical (Up or Down).
 */
export function directionIsVertical(dir: Direction): boolean {
  return ensureWasm().direction_is_vertical(dir);
}

// ============ Split Direction Functions ============

/**
 * Check if split direction is horizontal.
 *
 * Horizontal splits stack windows vertically (one above the other).
 */
export function splitIsHorizontal(dir: SplitDirection): boolean {
  return ensureWasm().split_is_horizontal(dir);
}

/**
 * Check if split direction is vertical.
 *
 * Vertical splits place windows side by side.
 */
export function splitIsVertical(dir: SplitDirection): boolean {
  return ensureWasm().split_is_vertical(dir);
}

/**
 * Get the opposite split direction.
 */
export function splitOpposite(dir: SplitDirection): SplitDirection {
  return ensureWasm().split_opposite(dir);
}
