/**
 * @file mcp_client.h
 * @brief MCP Client implementation
 * 
 * This file implements the client-side functionality for the Model Context Protocol.
 * Follows the 2024-11-05 basic protocol specification.
 */

#ifndef MCP_CLIENT_H
#define MCP_CLIENT_H

#include "mcp_message.h"
#include "mcp_tool.h"

// Include the HTTP library
#include "httplib.h"

#include <string>
#include <map>
#include <vector>
#include <memory>
#include <mutex>
#include <functional>

namespace mcp {

/**
 * @class client
 * @brief Client for connecting to MCP servers
 * 
 * The client class provides functionality to connect to MCP servers,
 * initialize the connection, and send/receive JSON-RPC messages.
 */
class client {
public:
    /**
     * @brief Constructor
     * @param host The server host (e.g., "localhost", "example.com")
     * @param port The server port
     */
    client(const std::string& host, int port = 8080, const json& capabilities = json::object());
    
    /**
     * @brief Destructor
     */
    ~client();
    
    /**
     * @brief Initialize the connection with the server
     * @param client_name The name of the client
     * @param client_version The version of the client
     * @return True if initialization was successful
     */
    bool initialize(const std::string& client_name, const std::string& client_version);
    
    /**
     * @brief Set authentication token
     * @param token The authentication token
     */
    void set_auth_token(const std::string& token);
    
    /**
     * @brief Set a request header that will be sent with all requests
     * @param key Header name
     * @param value Header value
     */
    void set_header(const std::string& key, const std::string& value);
    
    /**
     * @brief Set timeout for requests
     * @param timeout_seconds Timeout in seconds
     */
    void set_timeout(int timeout_seconds);

    /**
     * @brief Set client capabilities
     * @param capabilities The capabilities of the client
     */
    void set_capabilities(const json& capabilities);
    
    /**
     * @brief Send a request and wait for a response
     * @param method The method to call
     * @param params The parameters to pass
     * @return The response
     * @throws mcp_exception on error
     */
    response send_request(const std::string& method, const json& params = json::object());
    
    /**
     * @brief Send a notification (no response expected)
     * @param method The method to call
     * @param params The parameters to pass
     * @throws mcp_exception on error
     */
    void send_notification(const std::string& method, const json& params = json::object());
    
    /**
     * @brief Get server capabilities
     * @return The server capabilities
     * @throws mcp_exception on error
     */
    json get_server_capabilities();
    
    /**
     * @brief Call a tool
     * @param tool_name The name of the tool to call
     * @param parameters The parameters to pass to the tool
     * @return The result of the tool call
     * @throws mcp_exception on error
     */
    json call_tool(const std::string& tool_name, const json& parameters = json::object());
    
    /**
     * @brief Get available tools
     * @return List of available tools
     * @throws mcp_exception on error
     */
    std::vector<tool> get_tools();
    
    /**
     * @brief Get resource metadata
     * @param resource_path The path to the resource
     * @return The resource metadata
     * @throws mcp_exception on error
     */
    json get_resource_metadata(const std::string& resource_path);

    /**
     * @brief Get client capabilities
     * @return The client capabilities
     */
    json get_capabilities();
    
    /**
     * @brief Access a resource
     * @param resource_path The path to the resource
     * @param params Additional parameters for the resource
     * @return The resource data
     * @throws mcp_exception on error
     */
    json access_resource(const std::string& resource_path, const json& params = json::object());

private:
    std::string host_;
    int port_;
    std::string auth_token_;
    int timeout_seconds_ = 30;
    json capabilities_;

    std::map<std::string, std::string> default_headers_;
    json server_capabilities_;

    
    // HTTP client
    std::unique_ptr<httplib::Client> http_client_;
    
    // Mutex for thread safety
    mutable std::mutex mutex_;
    
    // Initialize the client
    void init_client();
    
    // Send a JSON-RPC request and get the response
    json send_jsonrpc(const request& req);
};

} // namespace mcp

#endif // MCP_CLIENT_H