import os
import sys
import shutil

from subprocess import PIPE, run
import subprocess
import logging

from typing import List, Any

logger = logging.getLogger('diffusion.utils.experiment')
logger.setLevel(logging.DEBUG)

# annot. FileLogger class, for thread-safe logging to specified path
class FileLogger(object):

    def __init__(self, log_path, proc_id = None):

        # create a logger
        flogger = logging.getLogger('file_logging-%s' % str(proc_id))
        flogger.propagate = False
        flogger.setLevel(logging.DEBUG)

        # create a file handler
        fh = logging.FileHandler(log_path, mode='w')
        fh.setLevel(logging.DEBUG)

        # set formatter
        formatter = logging.Formatter("%(asctime)s %(levelname)s: %(message)s", datefmt = "%Y-%m-%d %H:%M:%S") 
        fh.setFormatter(formatter)

        # add handler to logger
        flogger.addHandler(fh)
        self.logger = flogger
    
    def __del__(self):
        self.logger.handlers = []


# annot. Running shell command and realtime logging
def run_proc(command, shell: Any = False, file_logger = None, proc_name = None, log_to_main = False):
    """
    Run a shell command and log the output to a file

    Parameters
    ----------
    command : str
        The command to run
    shell : boolean, optional
        Whether to run the command in a shell, by default False
    log_path : str, optional
        The path to the log file, by default None
    proc_name : str, optional
        The name of the process, by default None
    proc_id : int, optional
        The id of the process, by default None
    """
    if proc_name is None:
        proc_name = ''
    else:
        proc_name += ' '

    if file_logger is not None:
        file_logger.logger.debug('######################## Hello can you see me? I am in subprocess. #############################')
        file_logger.logger.info('\n\n##########################################################################################')
        file_logger.logger.info('Subprocess %s output:' % proc_name)

    process = subprocess.Popen(
        command,
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
        shell=shell,
        encoding='utf-8'
    )

    while True:
        realtime_output = process.stdout.readline()

        if realtime_output == '' and process.poll() is not None:
            break

        if realtime_output:
            if log_to_main:
                logger.info("%soutput: %s" % (proc_name , realtime_output.strip()))
            if file_logger is not None:
                file_logger.logger.info(realtime_output.strip())
    
    return