"""
Helpers
====================================
Helper classes and functions
"""

import os
import shlex
from subprocess import Popen, run
from enum import Enum
from yachalk import chalk
from rich.console import Console
from rich.table import Table


class ReturnCode(Enum):
    OK = 0


class Executor():
    """
    Class to execute shell commands
    """
    @classmethod
    def success(cls, command: str, env: dict = None) -> bool:
        ret, _ = cls.__run(command, env=env)
        return ret == ReturnCode.OK.value

    @classmethod
    def run(cls, command: str, env: dict = None) -> str:
        _, output = cls.__run(command, env=env)
        return cls.__handle_output(output)

    @classmethod
    def __run(cls, command: str, env: dict = None) -> tuple[int, str]:
        """
        Runs a shell command with the default environment.
        If env is given it is _UPDATED_ to the default environment.
        """
        _env = os.environ.copy()
        if env:
            _env.update(env)
        p = run(shlex.split(command), capture_output=True, env=_env)
        return p.returncode, cls.__handle_output(p.stdout.decode())

    @classmethod
    def __handle_output(cls, output: str) -> str:
        # We remove the last \n
        return output.rstrip('\n')


class Message():
    """
    Class to output colored messages to the console
    """
    @classmethod
    def info(cls, message):
        print(chalk.green_bright.bold(message))

    @classmethod
    def warn(cls, message):
        print(chalk.yellow_bright.bold(message))

    @classmethod
    def error(cls, message):
        print(chalk.red_bright.bold(message))

    @classmethod
    def debug(cls, message):
        print(chalk.blue_bright.bold(message))


class TableOutput():
    """
    Class to output text in table format
    """
    console = Console()

    @classmethod
    def out(cls, data: str | list, sep: str = '#', headers: tuple[str] = None):
        table = Table(
            show_header=(headers is not None),
            show_lines=False,
            show_edge=False
        )
        if headers:
            for header in headers:
                table.add_column(header)

        if isinstance(data, str):
            data = data.split('\n')

        for line in data:
            table.add_row(*line.split(sep))

        cls.console.print(table)


####################
# OLD CODE
####################


# class Interactive():
#     """
#     Execute a command interactively with pseudo terminal
#     found at https://stackoverflow.com/questions/41542960/run-interactive-bash-with-popen-and-a-dedicated-tty-python
#     """

#     def __init__(self, command: str = '/bin/bash', env: dict = None):
#         self.command = command
#         self.env = os.environ.copy()
#         if env:
#             self.env.update(env)
#         self.process = None

#     def run(self):
#         old_tty = termios.tcgetattr(sys.stdin)
#         tty.setraw(sys.stdin.fileno())

#         master, slave = pty.openpty()

#         try:
#             self.process = Popen(
#                 shlex.split(self.command),
#                 preexec_fn=os.setsid,
#                 stdin=slave,
#                 stdout=slave,
#                 stderr=slave,
#                 env=self.env)

#             while True:
#                 r, _, _ = select.select([sys.stdin, master], [], [])
#                 if sys.stdin in r:
#                     d = os.read(sys.stdin.fileno(), 10240)
#                     os.write(master, d)
#                 elif master in r:
#                     o = os.read(master, 10240)
#                     if o:
#                         os.write(sys.stdout.fileno(), o)

#                 if self.process.poll() is not None:
#                     sys.stdout.flush()
#                     break
#                 else:
#                     sleep(0.1)

#         finally:
#             # restore tty settings back
#             termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_tty)
