/**
 * Port Types
 *
 * Defines types for node connection ports/handles.
 * Ports are per-node-instance configurable connection points.
 */

// --- Port Position Types ---

/**
 * Side of a node where a port can be placed.
 */
export type PortSide = 'top' | 'right' | 'bottom' | 'left';

/**
 * Type of port connection behavior.
 * - 'input': Can only receive connections
 * - 'output': Can only send connections
 * - 'bidirectional': Can both send and receive connections
 */
export type PortType = 'input' | 'output' | 'bidirectional';

// --- Port Definition ---

/**
 * Definition of a single port on a node.
 * Stored in node's ui_properties.ports array.
 */
export interface PortDefinition {
	/** Unique identifier within the node (e.g., 'input-1', 'output-data') */
	id: string;

	/** Connection behavior */
	type: PortType;

	/** Which side of the node the port is on */
	side: PortSide;

	/**
	 * Position along the side (0-1).
	 * 0 = start of side, 0.5 = center, 1 = end.
	 * For left/right: 0 = top, 1 = bottom.
	 * For top/bottom: 0 = left, 1 = right.
	 */
	position: number;

	/** Optional display label */
	label?: string;

	/** Optional color override (CSS color string) */
	color?: string;

	/**
	 * Maximum number of connections allowed.
	 * undefined = unlimited
	 */
	maxConnections?: number;
}

// --- Node Ports Configuration ---

/**
 * Configuration for all ports on a node.
 * Stored in node's ui_properties.ports.
 */
export interface NodePortsConfig {
	/** Array of port definitions */
	ports: PortDefinition[];
}

// --- Port Connection State ---

/**
 * Represents a connection to a specific port.
 * Used in edge attributes to specify which ports are connected.
 */
export interface PortConnection {
	/** The node ID */
	nodeId: string;

	/** The port ID on that node */
	portId: string;
}

/**
 * Extended edge attributes with port information.
 * These are stored alongside existing edge attributes.
 */
export interface PortEdgeAttributes {
	/** Source port information (if using ports) */
	sourcePort?: string;

	/** Target port information (if using ports) */
	targetPort?: string;
}

// --- Port Position Calculation ---

/**
 * Calculated world-space position of a port.
 */
export interface PortPosition {
	/** X coordinate in world space */
	x: number;

	/** Y coordinate in world space */
	y: number;
}

/**
 * Calculate the world-space position of a port on a node.
 *
 * @param nodeX Node's x position
 * @param nodeY Node's y position
 * @param nodeWidth Node's width
 * @param nodeHeight Node's height
 * @param port The port definition
 * @returns World-space coordinates of the port
 */
export function calculatePortPosition(
	nodeX: number,
	nodeY: number,
	nodeWidth: number,
	nodeHeight: number,
	port: PortDefinition
): PortPosition {
	switch (port.side) {
		case 'left':
			return {
				x: nodeX,
				y: nodeY + nodeHeight * port.position,
			};
		case 'right':
			return {
				x: nodeX + nodeWidth,
				y: nodeY + nodeHeight * port.position,
			};
		case 'top':
			return {
				x: nodeX + nodeWidth * port.position,
				y: nodeY,
			};
		case 'bottom':
			return {
				x: nodeX + nodeWidth * port.position,
				y: nodeY + nodeHeight,
			};
	}
}

// --- Default Port Configuration ---

/**
 * Default port for nodes without explicit port configuration.
 * A single bidirectional port centered on the right side.
 */
export const DEFAULT_PORT: PortDefinition = {
	id: 'default',
	type: 'bidirectional',
	side: 'right',
	position: 0.5,
};

/**
 * Get the ports configuration for a node.
 * Returns default port if no explicit configuration exists.
 *
 * @param ports Optional ports array from node's ui_properties
 * @returns Array of port definitions
 */
export function getNodePorts(ports?: PortDefinition[]): PortDefinition[] {
	if (ports && ports.length > 0) {
		return ports;
	}
	return [DEFAULT_PORT];
}

// --- Port Validation ---

/**
 * Check if a port can accept a new connection.
 *
 * @param port The port definition
 * @param currentConnections Number of existing connections to this port
 * @param isSource Whether this port would be the source of the connection
 * @returns true if the connection is allowed
 */
export function canPortAcceptConnection(
	port: PortDefinition,
	currentConnections: number,
	isSource: boolean
): boolean {
	// Check type compatibility
	if (isSource && port.type === 'input') {
		return false; // Input ports can't be sources
	}
	if (!isSource && port.type === 'output') {
		return false; // Output ports can't be targets
	}

	// Check connection limit
	if (port.maxConnections !== undefined && currentConnections >= port.maxConnections) {
		return false;
	}

	return true;
}

/**
 * Check if two ports can be connected.
 *
 * @param sourcePort The source port
 * @param targetPort The target port
 * @returns true if the connection is valid
 */
export function arePortsCompatible(
	sourcePort: PortDefinition,
	targetPort: PortDefinition
): boolean {
	// Source must allow outgoing connections
	if (sourcePort.type === 'input') {
		return false;
	}

	// Target must allow incoming connections
	if (targetPort.type === 'output') {
		return false;
	}

	return true;
}
