"""
Orchestration of the agent workflow with single and multi-agent versions.
"""

from abc import ABC, abstractmethod

from elemental_agents.core.memory.long_memory import LongMemory
from elemental_agents.core.taskqueue.queue import TaskQueue
from elemental_agents.utils.config import ConfigModel


class Orchestrator(ABC):
    """
    Main logic for orchestrating the agents in the system. The orchestrator
    takes a planner, an agent, and a verifier as input and runs them in sequence.
    This logic leads to decomposing the task into sub-tasks, executing the sub-tasks
    with the agent, and verifying the final result with the verifier.
    """

    def __init__(self) -> None:
        """
        Initialize the orchestrator with the taskqueue. Agent(s) and other components
        are defined in the child classes. The taskqueue is used to store the tasks
        generated by the planner and completed by the agent.
        """

        self._taskqueue = TaskQueue()
        self._config = ConfigModel()

        if self._config.use_long_memory:

            self._memory = LongMemory(
                embeddings_engine=self._config.long_memory_embeddings_engine,
                max_results=self._config.long_memory_items,
                threshold=self._config.long_memory_threshold,
            )

    @abstractmethod
    def run(self, instruction: str, input_session: str) -> str:
        """
        Run the orchestrator with the specified instruction. The orchestrator
        generates a plan using the planner, creates a task queue with the plan,
        completes the tasks in the task queue using the agent, and verifies the
        final result using the verifier.

        :param instruction: The instruction to run the orchestrator with.
        :param input_session: The input session for the orchestrator.
        :return: The final result from the verifier.
        """
