# 
# Author    : Manuel Bernal Llinares
# Project   : trackhub-creator
# Timestamp : 12-09-2017 16:10
# ---
# © 2017 Manuel Bernal Llinares <mbdebian@gmail.com>
# All rights reserved.
# 

"""
This file contains different models for the execution of subprocesses / external processes, e.g. via the command line
"""

import abc
import threading
import subprocess
# App imports
import config_manager
from .exceptions import ParallelRunnerException


# Execution of commands
class CommandLineRunnerFactory:
    @staticmethod
    def get_command_line_runner():
        # TODO - This Factory is creating only local runners in the first iteration
        return CommandLineRunnerAsThread()


class ParallelManager:
    pass


class ParallelRunner(metaclass=abc.ABCMeta, threading.Thread):
    def __init__(self):
        super().__init__()
        self._logger = config_manager \
            .get_app_config_manager() \
            .get_logger_for("{}.{}-{}".format(__name__, type(self).__name__, threading.current_thread().getName()))
        self._stdout = b' '
        self._stderr = b' '
        self._done = False
        self._shutdown = False

    @abc.abstractmethod
    def _run(self):
        ...

    def run(self):
        self._logger.debug("--- START ---".format(threading.current_thread().getName()))
        try:
            self._run()
        finally:
            self._done = True

    def cancel(self):
        self._logger.debug("--- CANCEL ---".format(threading.current_thread().getName()))
        self._shutdown = True
        self._stop()

    def wait(self):
        self._logger.debug("Runner Thread ID '{}' --- WAIT ---".format(threading.current_thread().getName()))
        self.join()

    def get_stdout(self):
        # Never give it back until the runner is done with whatever it is doing
        if not self._done:
            raise ParallelRunnerException("Runner Thread ID '{}' is NOT DONE doing its job, "
                                          "thus 'stdout' is NOT AVAILABLE".format(threading.current_thread().getName()))
        return self._stdout

    def get_stderr(self):
        # Never give it back until the runner is done with whatever it is doing
        if not self._done:
            raise ParallelRunnerException("Runner Thread ID '{}' is NOT DONE doing its job, "
                                          "thus 'stderr' is NOT AVAILABLE".format(threading.current_thread().getName()))
        return self._stderr


class CommandLineRunner(ParallelRunner):
    def __init__(self):
        super().__init__()
        self._logger = config_manager \
            .get_app_config_manager() \
            .get_logger_for("{}.{}".format(__name__, type(self).__name__))
        self.command = None
        self.timeout = None


class CommandLineRunnerAsThread(CommandLineRunner):
    def __init__(self):
        super().__init__()
        self._logger = config_manager \
            .get_app_config_manager() \
            .get_logger_for("{}.{}-{}".format(__name__, type(self).__name__, threading.current_thread().getName()))

    def _run(self):
        pass


class CommandLineRunnerOnHpc(CommandLineRunner):
    def __init__(self):
        super().__init__()
        self._logger = config_manager \
            .get_app_config_manager() \
            .get_logger_for("{}.{}-{}".format(__name__, type(self).__name__, threading.current_thread().getName()))

    def _run(self):
        pass

@@ -1599,38 +1599,16 @@
 .debug(%22
-Runner Thread ID '%7B%7D' 
 --- WAIT

refactor log message