// src/messages/socket.ts
// Copyright (C) 2026 Rob Colbert <rob.colbert@openplatform.us>
// Licensed under the Apache License, Version 2.0

import {
  StatusMessage,
  ProcessWorkOrderMessage,
  ResponseMessage,
  ThinkingMessage,
  ToolCallMessage,
  WorkOrderCompleteMessage,
  RequestCrashRecoveryMessage,
  CrashRecoveryResponseMessage,
  RequestTerminationMessage,
  WorkspaceModeChangedMessage,
  LogMessage,
} from "./drone.ts";
import { SessionUpdatedMessage } from "./web.ts";
import {
  AbortWorkOrderMessage,
  ReleaseSessionLockMessage,
  RequestSessionLockMessage,
  RequestWorkspaceModeMessage,
  SessionHeartbeatMessage,
  SubmitPromptMessage,
  FileTreeRequestMessage,
  FileTreeResponseMessage,
  FileReadRequestMessage,
  FileReadResponseMessage,
  FileWriteRequestMessage,
  FileWriteResponseMessage,
} from "./ide.ts";
import {
  RequestProcessStatsMessage,
  RequestProcessStatsCallback,
  SubscribeDroneMessage,
  UnsubscribeDroneMessage,
} from "./subprocess.ts";

/*
There are two different kinds of clients that connect to the gadget-code:web
Socket.IO server:

1. The gadget-code:ide (ReactJS front-end)
2. The gadget-drone work order runner (NodeJS headless process)

gadget-code:ide sends Socket.IO messages to gadget-code:web, which then routes
them to the appropriate gadget-drone socket.

gadget-drone sends messages to gadget-code:web intending for them to be routed
to the appropriate gadget-code:ide socket.

This architecture lets the IDE run under User control in any browser anywhere,
and serve as a remote control surface for one or more gadget-drone processes
running work orders on projects in chat sessions.
*/

export interface ClientToServerEvents {
  /*
   * gadget-code:ide => gadget-code:web
   */

  requestSessionLock: RequestSessionLockMessage;
  requestWorkspaceMode: RequestWorkspaceModeMessage;
  submitPrompt: SubmitPromptMessage;
  abortWorkOrder: AbortWorkOrderMessage;
  releaseSessionLock: ReleaseSessionLockMessage;
  sessionHeartbeat: SessionHeartbeatMessage;
  fileTreeRequest: FileTreeRequestMessage;
  fileReadRequest: FileReadRequestMessage;
  fileWriteRequest: FileWriteRequestMessage;

  /*
   * Drone Monitor events (IDE => web => drone)
   */

  requestProcessStats: RequestProcessStatsMessage;
  subscribeDrone: SubscribeDroneMessage;
  unsubscribeDrone: UnsubscribeDroneMessage;

  /*
   * gadget-drone => gadget-code:web
   */

  log: LogMessage;
  status: StatusMessage;
  thinking: ThinkingMessage;
  response: ResponseMessage;
  toolCall: ToolCallMessage;
  workOrderComplete: WorkOrderCompleteMessage;
  requestCrashRecovery: RequestCrashRecoveryMessage;
  requestTermination: RequestTerminationMessage;
  workspaceModeChanged: WorkspaceModeChangedMessage;
  "agent:thinking": AgentThinkingMessage;
  "agent:response": AgentResponseMessage;
  "agent:tool-call": AgentToolCallMessage;
  "agent:tool-result": AgentToolResultMessage;
  "agent:complete": AgentCompleteMessage;
}

export type AgentThinkingMessage = (data: {
  agentId: string;
  thinking: string;
}) => void;

export type AgentResponseMessage = (data: {
  agentId: string;
  chunk: string;
}) => void;

export type AgentToolCallMessage = (data: {
  agentId: string;
  tool: string;
  args: unknown;
}) => void;

export type AgentToolResultMessage = (data: {
  agentId: string;
  tool: string;
  result: unknown;
}) => void;

export type AgentCompleteMessage = (data: {
  agentId: string;
  response?: string;
  subagent?: Record<string, unknown>;
  stats?: Record<string, unknown>;
}) => void;

export interface ServerToClientEvents {
  /*
   * gadget-code:web => gadget-drone
   */

  requestSessionLock: RequestSessionLockMessage;
  requestWorkspaceMode: RequestWorkspaceModeMessage;
  releaseSessionLock: ReleaseSessionLockMessage;
  sessionHeartbeat: SessionHeartbeatMessage;
  abortWorkOrder: AbortWorkOrderMessage;
  processWorkOrder: ProcessWorkOrderMessage;
  crashRecoveryResponse: CrashRecoveryResponseMessage;
  requestTermination: RequestTerminationMessage;
  fileTreeRequest: FileTreeRequestMessage;
  fileReadRequest: FileReadRequestMessage;
  fileWriteRequest: FileWriteRequestMessage;

  /*
   * Drone Monitor events (web => drone)
   * Note: no registrationId param — the drone socket already knows its identity
   */

  requestProcessStats: (
    cb: RequestProcessStatsCallback,
  ) => void;

  /*
   * gadget-code:web => gadget-code:ide
   */

  "drone:log": (data: {
    timestamp: string;
    level: string;
    component: string;
    message: string;
    metadata?: unknown;
  }) => void;

  "drone:status": (data: {
    timestamp: string;
    message: string;
  }) => void;

  log: LogMessage;
  status: StatusMessage;
  thinking: ThinkingMessage;
  response: ResponseMessage;
  toolCall: ToolCallMessage;
  workOrderComplete: WorkOrderCompleteMessage;
  workspaceModeChanged: WorkspaceModeChangedMessage;
  sessionUpdated: SessionUpdatedMessage;
  tabLockDenied: (data: { message: string }) => void;
  fileTreeResponse: FileTreeResponseMessage;
  fileReadResponse: FileReadResponseMessage;
  fileWriteResponse: FileWriteResponseMessage;
  "agent:thinking": AgentThinkingMessage;
  "agent:response": AgentResponseMessage;
  "agent:tool-call": AgentToolCallMessage;
  "agent:tool-result": AgentToolResultMessage;
  "agent:complete": AgentCompleteMessage;
}

export interface SocketData {
  /* no data defined */
}
