import argparse
import sys

from importlib import import_module
from os import listdir, path
from os.path import isfile, join

from classes.TW_Cli_Command import TW_Cli_Command, TW_Cli_Args
from classes.TW_Utility import TW_Utility

#args = parser.parse_args()
class TW_Cli:
    def __init__(self, parser:argparse.ArgumentParser):
        self.commandsInstances = {}
        self.parser = parser
    
    def __importCommands(self, fileName:str):
        className = fileName.replace('.py', '')
        module_name = f"commands.{className}"

        try:
            module = import_module(module_name)
            cls = getattr(module, className)
            instantiatedClass = cls()
        except:
            instantiatedClass = None

        return instantiatedClass
    
    def __loadCommands(self):
        folderPath = path.abspath(path.join(path.dirname(__file__), '..', 'commands'))
        commandsFiles = [f for f in listdir(folderPath) if isfile(join(folderPath, f))]

        for fileName in commandsFiles:
            instantiatedClass = self.__importCommands(fileName)
            if instantiatedClass is not None:                    
                self.commandsInstances[instantiatedClass.name] = instantiatedClass


    def __addArguments(self):
        self.parser.add_argument("--command_name", required=True)
        argsToParse = {}

        for com in self.commandsInstances.values():
            for arg in com.args:
                argsToParse[arg.name + '___' + com.name] = arg

        distinctArgs = list({key.split("___")[0] for key, value in argsToParse.items()})

        for name in distinctArgs:
            self.parser.add_argument("--" + name, required=False)

    def parseAndExecute(self):
        self.__loadCommands()
        self.__addArguments()

        parsedArgs = self.parser.parse_args()
        if not hasattr(parsedArgs, 'command_name'):
            sys.stderr.write("Command Name argument is mandatory")
            return

        if self.commandsInstances[getattr(parsedArgs, 'command_name')] is None:
            sys.stderr.write("No commands founds with name " + parsedArgs['command_name'])
            return
        
        missingArgs = {}
        selectedCommand = self.commandsInstances[getattr(parsedArgs, 'command_name')]

        for arg in selectedCommand.args:
            if arg.nullable == False and (hasattr(parsedArgs, arg.name) == False or getattr(parsedArgs, arg.name) is None):
                missingMsg = f"{arg.name} is mandatory"
                missingArgs[arg.name] = missingMsg

                sys.stderr.write(missingMsg)
            elif arg.nullable == True and arg.defaultValue is not None and (hasattr(parsedArgs, arg.name) == False or getattr(parsedArgs, arg.name) is None):
                setattr(parsedArgs, arg.name, arg.defaultValue)

        if len(missingArgs.values()) > 0:
            return
        
        self.commandsInstances[getattr(parsedArgs, 'command_name')].execute(parsedArgs)

        