import os
from typing import Dict, List

import radical.utils as ru

from socm.core import Resource
from socm.utils.states import States


class Enactor(object):
    """
    The Enactor is responsible to execute workflows on resources. The Enactor
    takes as input a list of tuples <workflow,resource> and executes the
    workflows on their selected resources.

    The Enactor offers a set of methods to execute and monitor workflows.

    *Parameters:*

    *workflows*: A list with the workflow IDs that are executing.

    *execution_status*: a hash table table that holds the state, and
                      execution status.

    *logger*: a logging object.
    """

    def __init__(self, sid=None):

        self._worflows = list()  # A list of workflows IDs
        # This will a hash table of workflows. The table will include the
        # following:
        # 'workflowsID': {'state': The state of the workflow based on the WFM,
        #                 'endpoint': Process ID or object to WMF for the specific
        #                             workflow,
        #                 'start_time': Epoch of when the workflow is submitted
        #                               to the WMF,
        #                 'end_time': Epoch of when the workflow finished.}
        self._execution_status = dict()  # This will create a hash table of workflows

        self._uid = ru.generate_id("enactor.%(counter)04d", mode=ru.ID_CUSTOM, ns=sid)

        path = os.getcwd() + "/" + sid
        # print(path)
        name = self._uid

        self._logger = ru.Logger(name=self._uid, path=path, level="DEBUG")
        self._prof = ru.Profiler(name=name, path=path)

    def setup(self, resource: Resource, walltime: int, cores: int, execution_schema: str | None = None) -> None:
        """
        Sets up the enactor to execute workflows.
        """
        raise NotImplementedError("setup is not implemented")


    def enact(self, workflows, resources):
        """
        Method enact receives a set workflows and resources. It is responsible to
        start the execution of the workflow and set a endpoint to the WMF that
        executes the workflow

        *workflows:* A workflows that will execute on a resource
        *resources:* The resource that will be used.
        """
        raise NotImplementedError("enact is not implemented")

    def _monitor(self):
        """
        This method monitors the execution of workflows
        """

        raise NotImplementedError("_monitor is not implemented")

    def get_status(self, workflows: str | List[str] | None = None) -> Dict[str, States]:
        """
        Get the state of a workflow or workflows.

        *Parameter*
        *workflows:* A workflow ID or a list of workflow IDs

        *Returns*
        *status*: A dictionary with the state of each workflow.
        """

        status = dict()
        if workflows is None:
            for workflow in self._execution_status:
                status[workflow] = self._execution_status[workflow]["state"]
        elif isinstance(workflows, list):
            for workflow in workflows:
                status[workflow] = self._execution_status[workflow]["state"]
        else:
            status[workflows] = self._execution_status[workflows]["state"]

        return status

    def update_status_cb(self, workflow, new_state):
        """
        Update the state of a workflow that is executing
        """

        if workflow not in self._execution_status:
            self._logger.warning(
                "Has not enacted on workflow %s yet.",
                workflow,
                self._get_workflow_state(workflow),
            )
        else:
            self._execution_status[workflow]["state"] = new_state

    def _get_workflow_state(self, workflow):
        """
        Get a workflow's update
        """

        return self._execution_status[workflow]["state"]

    def terminate(self):
        """
        Public method to terminate the Enactor
        """
        raise NotImplementedError("terminate is not implemented")
