/**
 * DataPort Runtime — Connection 배열을 DataPortBus 브리지로 풀어주는 함수.
 *
 * 사용 시점:
 *   화면 렌더러가 Screen(혹은 Template) 을 마운트할 때 setupConnections 를
 *   호출하고, 반환된 cleanup 함수를 언마운트 시 호출한다.
 *
 * 동작:
 *   각 Connection 에 대해
 *     1. from 컴포넌트의 output 채널을 구독
 *     2. 값이 들어오면 to 컴포넌트의 input 채널로 publish
 *   즉 화면 수준 Connection 선언을 런타임 브리지로 풀어준다.
 *
 * 컴포넌트 쪽 책임:
 *   - 각 v2-* 컴포넌트는 자기 outputs 포트에 값이 생기면 DataPortBus 에 publish
 *   - inputs 포트는 subscribe 해서 값이 오면 처리
 *   이 파일은 그 둘을 중간에서 연결만 한다.
 */
import type { Connection } from "@/types/invyone-component";
import { DataPortBus } from "./DataPortBus";

/**
 * Connection[] 을 DataPortBus 브리지로 변환.
 *
 * @param connections  화면/템플릿에 선언된 포트 연결 목록
 * @param bus          연결을 걸 대상 DataPortBus 인스턴스
 * @returns cleanup 함수. 화면 언마운트 시 반드시 호출 (메모리 누수 방지).
 */
export function setupConnections(
  connections: Connection[] | undefined,
  bus: DataPortBus,
): () => void {
  if (!connections || connections.length === 0) {
    return () => {};
  }

  const unsubs: Array<() => void> = [];

  for (const conn of connections) {
    const fromChannel = DataPortBus.channelOf(
      conn.from.componentId,
      conn.from.port,
    );
    const toChannel = DataPortBus.channelOf(
      conn.to.componentId,
      conn.to.port,
    );

    const unsub = bus.subscribe(fromChannel, (value) => {
      bus.publish(toChannel, value);
    });
    unsubs.push(unsub);
  }

  return () => {
    unsubs.forEach((u) => u());
  };
}
