/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2024-2025. All rights reserved.
 */
package magic.mcp

import magic.core.agent.Agent
import magic.core.tool.Tool
import magic.jsonable.*
import magic.log.LogUtils

import std.console.{Console, ConsoleReader, ConsoleWriter}
import std.collection.{ArrayList}
import magic.tool.AgentAsTool

/**
 * MCP server via the stdio transport
 */
public class StdioMCPServer <: AbsMCPServer {
    let reader: ConsoleReader
    let writer: ConsoleWriter

    public init(tools: Array<Tool>) {
        super(tools)
        this.reader = Console.stdIn
        this.writer = Console.stdOut
    }

    /**
     * Start the server
     */
    public func start(): Unit {
        this.initialize()
        this.loop()
    }

    override protected func send(msg: String): Unit {
        LogUtils.debug("Send: ${msg}")
        writer.writeln(msg)
        writer.flush()
    }

    override protected func recv(): Option<String> {
        let msg = reader.readln()
        LogUtils.debug("Recv: ${msg ?? ''}")
        return msg
    }

    //-----------------------------------------------------------------------------------
    /**
     * Merge all tools of each agent, and start a MCP server for these tools
     */
    public static func startWith(agents: Array<Agent>): Unit {
        let allTools = ArrayList<Tool>()
        for (agent in agents) {
            allTools.appendAll(agent.toolManager.getTools())
            // The agent itself is also a tool
            allTools.append(AgentAsTool(agent))
        }
        let server = StdioMCPServer(allTools.toArray())
        server.start()
    }

    /**
     * Start a MCP server for tools
     */
    public static func startWith(tools: Array<Tool>): Unit {
        let server = StdioMCPServer(tools)
        server.start()
    }
}