import os
import sys

# the '@classmethod' can be used to define a method that belongs to the class rather than an instance of the class.
# In this case, the method can be called without creating an instance of the class.
# such as ColorPrinter.print_success('Success!')

class ColorPrinter:
    """Color printing utility class"""

    # Check if ANSI colors are supported
    @classmethod
    def _supports_color(cls):
        # Check if color is explicitly disabled
        if os.environ.get('NO_COLOR'):
            return False
        # Check if the terminal supports color
        if os.name == 'nt':
            # Windows: Always try to enable color for modern terminals
            # Try to enable ANSI virtual terminal processing
            try:
                import ctypes
                kernel32 = ctypes.windll.kernel32
                handle = kernel32.GetStdHandle(-11)
                mode = ctypes.c_ulong()
                kernel32.GetConsoleMode(handle, ctypes.byref(mode))
                ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
                kernel32.SetConsoleMode(handle, mode.value | ENABLE_VIRTUAL_TERMINAL_PROCESSING)
            except:
                pass
            # Check for common color-supporting terminal environments
            if os.environ.get('WT_SESSION') or os.environ.get('TERM_PROGRAM'):
                return True
            # Also enable for known terminal emulators
            term = os.environ.get('TERM', '')
            if 'color' in term.lower() or term.startswith('xterm') or term.startswith('screen'):
                return True
            return False
        return hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()

    COLORS = {     # \033 or \x1b is the escape character for ANSI color codes.
                   # the 0m is the reset code to restore the default color.
                   # the '[' is the start of the color code 
        'red': '\033[91m',
        'green': '\033[92m',
        'yellow': '\033[93m',
        'blue': '\033[94m',
        'magenta': '\033[95m',
        'cyan': '\033[96m',
        'white': '\033[97m',
        'reset': '\033[0m'
    }

    @classmethod    # while used the @classmethod ,the cls is the class itself rather than an instance of the class.
    def print(cls, message, color='white'):
        if cls._supports_color():
            color_code = cls.COLORS.get(color, cls.COLORS['white'])
            reset_code = cls.COLORS['reset']
            console_message = f"{color_code}{message}{reset_code}"
            print(console_message)
        else:
            # In terminals that don't support color, print message directly
            print(message)

    @classmethod
    def print_any(cls, *objects, sep=' ', end='\n', color=None):
        text = sep.join(str(obj) for obj in objects)
        if color and cls._supports_color():
            color_code = cls.COLORS.get(color, cls.COLORS['white'])
            reset_code = cls.COLORS['reset']
            console_message = f"{color_code}{text}{reset_code}"
            print(console_message, end=end)
        else:
            print(text, end=end)

    @classmethod
    def print_success(cls, message):
        cls.print(message, 'green')

    @classmethod
    def print_error(cls, message):
        cls.print(message, 'red')

    @classmethod
    def print_warning(cls, message):
        cls.print(message, 'yellow')

    @classmethod
    def print_info(cls, *objects, sep=' '):
        message = sep.join(str(obj) for obj in objects)
        cls.print(message, 'blue')

    @classmethod
    def print_data(cls, message):
        cls.print(message, 'magenta')

    @classmethod
    def print_progress(cls, message):
        cls.print(message, 'cyan')
