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

import { IAiEnvironment } from "./config/env.ts";
import { AiTool } from "./tools/tool.ts";

export type ToolMap = Map<string, AiTool>;
export type ToolSet = Set<AiTool>;

/**
 * No. I don't want to create an "MCP" server. I just want an in-process
 * toolbox that the agents can use in their daily work. That's not too much to
 * ask, dammit.
 */
export class AiToolbox {
  private _env: IAiEnvironment;
  get env(): IAiEnvironment {
    return this._env;
  }

  private tools: ToolMap = new Map<string, AiTool>();
  private modeSets: Map<string, ToolSet> = new Map<string, Set<AiTool>>();

  constructor(env: IAiEnvironment) {
    this._env = env;
  }

  /**
   * Registers an AiTool instance for use by the platform. If no ChatSessionMode
   * modes are specified, you are registering a system tool - such as the chat
   * session auto-naming tool - which are not called by agents (they are called)
   * by the platform itself, deterministically.
   * @param tool the tool being registered for use by the platform
   * @param modes the optional name(s) of the mode for which the tool is being
   * registered
   */
  register(tool: AiTool, modes?: string[]): void {
    if (this.tools.has(tool.name)) {
      throw new Error(`tool already registered: ${tool.name}`);
    }
    this.tools.set(tool.name, tool);

    if (!modes) {
      return; // system tools aren't listed in the modes for agent use
    }

    for (const mode of modes) {
      let set = this.modeSets.get(mode);
      if (!set) {
        set = new Set<AiTool>();
        this.modeSets.set(mode, set);
      }
      set.add(tool);
    }
  }

  /**
   * Retrieve a tool instance from the toolbox by name, ignoring mode(s). This
   * is how the system fetches system tools for use.
   * @param name the name of the tool to be retrieved
   * @returns the tool, or undefined if the tool is not registered
   */
  getTool(name: string): AiTool | undefined {
    return this.tools.get(name);
  }

  /**
   * Retrieves the set of tools registered for use in a given ChatSessionMode.
   * @param mode the ChatSessionMode for which a set of tools is being requested
   * @returns the set of tools, or undefined if there is not set for the mode
   * @todo the mode parameter should be the ChatSessionMode enum
   */
  getModeSet(mode: string): ToolSet | undefined {
    return this.modeSets.get(mode);
  }
}
