// Generated by bynkc — do not edit by hand.
// context room

import { Ok, Err, Some, None, type Result, type Option, type ValidationError, type Connection, type DurableObjectState, type DurableObjectNamespace, StateRegistry, makeAgent, rehydrationViolation, resolveConnection, connIdOf, type JsonValue, type BoundaryError, type ServiceBinding, callService, boundaryError } from "../../runtime.js";

export interface ServerFrame {
  readonly text: string;
}

export const ServerFrame = {
};

export interface RoomState {
  readonly conns: Record<string, string>;
}

const __RoomRegistry = new StateRegistry();
function __zeroOfRoomState(): RoomState { return { conns: {} }; }

function __rehydrateRoomState(s: RoomState): void {
  for (const __k of Object.keys(s.conns)) { const __r = ((__v) => typeof __v === "string" ? Ok(__v) : Err({ kind: "StructuralMismatch", path: "conns", expected: "string", actual: typeof __v } as BoundaryError))((__k as unknown as JsonValue)); if (__r.tag === "Err") throw rehydrationViolation("Room", __r.error); }
}

export class Room {
  state: DurableObjectState;
  constructor(state: DurableObjectState) {
    this.state = state;
  }

  private async loadState(): Promise<RoomState> {
    const stored = await this.state.storage.get<RoomState>("state");
    if (stored === undefined) return __zeroOfRoomState();
    const __merged = { ...__zeroOfRoomState(), ...stored };
    __rehydrateRoomState(__merged);
    return __merged;
  }

  private async commitState(s: RoomState): Promise<void> {
    await this.state.storage.put("state", s);
  }

  async join(u: string, conn: Connection<ServerFrame>, deps: {}): Promise<void> {
    const __state = { ...(await this.loadState()) };
    const __result = await (async () => {
      const __r0 = await ((__state.conns[String(u)] = connIdOf(conn)), undefined);
      return undefined;
    })();
    await this.commitState(__state);
    return __result;
  }

  async greet(conn: Connection<ServerFrame>, deps: {}): Promise<void> {
    const __state = await this.loadState();
    const __r0 = await (conn).send({ text: "welcome" });
    const __r1 = await (conn).close();
    return undefined;
  }

  async leave(u: string, deps: {}): Promise<void> {
    const __state = { ...(await this.loadState()) };
    const __result = await (async () => {
      const __r0 = await (async () => { const __k = String(u); const __cid = __state.conns[__k]; if (__cid !== undefined) { const __c = resolveConnection<ServerFrame>(this.state, __cid); if (__c.tag === "Some") { await __c.value.close(); } delete __state.conns[__k]; } return undefined; })();
      return undefined;
    })();
    await this.commitState(__state);
    return __result;
  }

  async fetch(request: Request): Promise<Response> {
    const url = new URL(request.url);
    if (url.pathname.startsWith("/_bynk/agent/")) {
      const methodName = url.pathname.slice("/_bynk/agent/".length);
      const { args, deps } = (await request.json()) as { args: unknown[]; deps: unknown };
      const result = await (this as any)[methodName](...args, deps);
      return new Response(JSON.stringify(result), { headers: { "content-type": "application/json" } });
    }
    return new Response("Not Found", { status: 404 });
  }

}

export function __makeRoom(key: string, env?: { ROOM?: DurableObjectNamespace }): Room {
  return makeAgent(__RoomRegistry, env?.ROOM, key, (state) => new Room(state));
}

export function __resetAgents(): void {
  __RoomRegistry.reset();
}

