import asyncio

from a2a.types import TaskStatusUpdateEvent, Task
from a2a_acl.protocol_extension.send_acl_message import spawn_send_acl_message, send_acl_message
from a2a_acl.utils.strings import neutralize_str
from a2a_acl.utils.url import build_url

import context
from a2a.server.events import EventQueue

from a2a_acl.agent.acl_agent import ACLAgentExecutor
from a2a_acl.content_codecs.common import natural_language_id

from a2a_acl.protocol_extension.acl_message import ACLMessage
from a2a_acl.a2a_utils.send_message import sync_reply, extract_text_from_message, extract_text_from_task_artifact

from a2a_acl.interface import asi_parser
from a2a_acl.interface.interface import ACLAgentCard

from a2a_agentspeak.content_codecs.common import atom_codec_id, python_agentspeak_codec_id

my_card = asi_parser.read_file("reference_agent.asi").add_codecs([natural_language_id])


def ref_status_update_callback(t:Task, u:TaskStatusUpdateEvent, m:str):
    print("Task:" + t.id)
    print("Received an update: " + str(u.status.state))
    if u.status.message is not None:
        if len(u.status.message.parts)>0 :
            print("Message: ", u.status.message.parts[0].root.text)

def ask_validation(t: str):
    print("Proposed requirement: " + t)
    print("Do you accept this proposal ?")
    res = input("[Y/N/Q]\n")
    match res:
        case "Y" | "y":
            print("Accepted. (" + res + ")")
            return ("tell","valid")
        case "Q" | "q":
            print("Quit. (" + res + ")")
            return ("achieve","quit")
        case _:
            print("Rejected. (" + res + ")")
            return ("tell","invalid")




class ReferenceAgentExecutor(ACLAgentExecutor):
    """An agent that receives validation requests and
    which delegates the decision to a human user."""

    def __init__(self, card: ACLAgentCard, url):
        super().__init__(agentcard=card, my_url=url)
        print(
            "Warning: launching a pure python A2A agent, unable to check .asi interface against python body."
        )
        self.reference_spec = context.spec

    async def execute_achieve(
        self,
        m: ACLMessage,
        output_event_queue: EventQueue,
    ):
        print("Received a request to launch the generation.")
        await self.init_interaction(self.reference_spec, self.my_url)

    async def execute_tell(
        self,
        m: ACLMessage,
        output_event_queue: EventQueue,
    ):
        self.reference_spec = m.content
        await sync_reply(output_event_queue, "ack")
        print("Received an update of the specification to manage.")

    def callback_req_to_validate (self, t:Task):
        r = extract_text_from_task_artifact(t)
        print("Artifact added with requirement to validate" + r)
        (illoc,res) = ask_validation(r)
        spawn_send_acl_message(build_url(context.the_host, context.manager_port), illocution=illoc, sender=self.my_url, content=res, codec=atom_codec_id, artifact_update_callback=self.callback_final_result)

    def callback_final_result (self, t:Task):
        r = extract_text_from_task_artifact(t)
        print("Artifact received: " + r)



    async def init_interaction(self, spec:str, self_url):
        await send_acl_message(
            build_url(context.the_host, context.manager_port),
            "tell",
            "spec(" + neutralize_str(spec) + ")",
            self_url,
            python_agentspeak_codec_id,
            message_callback=(
                lambda m: print("Message event: " + extract_text_from_message(m))
            ),
            artifact_update_callback=self.callback_req_to_validate,
            status_update_callback=lambda t, u, m: print("Received an update: " + str(u)),
        )
        print("[tell/spec message sent to the manager agent.]")

        await asyncio.sleep(1)

        await send_acl_message(
            build_url(context.the_host, context.manager_port),
            "achieve",
            "request",
            self_url,
            atom_codec_id,
            message_callback=(
                lambda m: print("Message event: " + extract_text_from_message(m))
            ),
            artifact_update_callback=self.callback_req_to_validate,
            status_update_callback=ref_status_update_callback,
        )
        print("[Achieve message sent to the manager agent.]")
