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

import std.collection.HashMap
import magic.core.agent.*
import magic.prompt.Template
import magic.jsonable.Jsonable

/**
 * Agents defined by @agent will inherit this type.
 * This class provides more easy-to-use methods.
 */
public abstract class UserDefinedAgent <: AbsAgent {

    public func chat(variables: HashMap<String, ToString>): String {
        return chat(
            AgentRequest(__USER_PROMPT_FUNC__().format(variables))
        ).content
    }

    public func chat(variables: Array<(String, ToString)>): String {
        return chat(
            AgentRequest(__USER_PROMPT_FUNC__().format(variables))
        ).content
    }

    //-----------------------------------------------------------------

    public func asyncChat(variables: HashMap<String, ToString>): AsyncAgentResponse {
        return asyncChat(
            AgentRequest(__USER_PROMPT_FUNC__().format(variables))
        )
    }

    public func asyncChat(variables: Array<(String, ToString)>): AsyncAgentResponse {
        return asyncChat(
            AgentRequest(__USER_PROMPT_FUNC__().format(variables))
        )
    }

    //-----------------------------------------------------------------
    public func chatGet<T>(variables: HashMap<String, ToString>): Option<T> where T<: Jsonable<T>{
        return chatGet<T>(
            AgentRequest(__USER_PROMPT_FUNC__().format(variables))
        )
    }

    public func chatGet<T>(variables: Array<(String, ToString)>): Option<T> where T<: Jsonable<T>{
        return chatGet<T>(
            AgentRequest(__USER_PROMPT_FUNC__().format(variables))
        )
    }

    //------------------------------------------------------
    // The following properties will be generated by `@agent`
    // prop name: String
    // prop description: Option<String>
    // mut prop temperature: Option<Float64>
    // mut prop systemPrompt: String
    // prop toolManager: ToolManager
    // mut prop model: ChatModel
    // mut prop executor: AgentExecutor
    // mut prop retriever: Option<Retriever>
    // mut prop memory: Option<Memory>

    private var _interceptor: Option<Interceptor> = None

    override public mut prop interceptor: Option<Interceptor> {
        get() { _interceptor }
        set(v) { _interceptor = v }
    }

    /*
     * This method will be override by @user defined in @agent
     */
    open protected func __USER_PROMPT_FUNC__(): String {
        throw UnsupportedException("Agent does not define user prompt template")
    }

    /*
     * This method will be used in the future.
     */
    open public func __CUSTOMIZED_EXECUTION_FUNC__(request: AgentRequest): Option<String> {
        return None
    }
}