import sys
import time

# from colorama import Fore, Back, Style
# from colorama import just_fix_windows_console, init

# init(autoreset=True)
# # use Colorama to make Termcolor work on Windows too
# just_fix_windows_console()


class AnsiCodeHelper:
    ansi_codes = {
        'fg_colors': {
            'black': '\033[30m',
            'red': '\033[31m',
            'green': '\033[32m',
            'yellow': '\033[33m',
            'blue': '\033[34m',
            'magenta': '\033[35m',
            'cyan': '\033[36m',
            'white': '\033[37m',
            'bright_black': '\033[1;30m',
            'bright_red': '\033[1;31m',
            'bright_green': '\033[1;32m',
            'bright_yellow': '\033[1;33m',
            'bright_blue': '\033[1;34m',
            'bright_magenta': '\033[1;35m',
            'bright_cyan': '\033[1;36m',
            'bright_white': '\033[1;37m',
            'reset_color': '\033[39m',
        },
        'bg_colors': {
            'black': '\033[40m',
            'red': '\033[41m',
            'green': '\033[42m',
            'yellow': '\033[43m',
            'blue': '\033[44m',
            'magenta': '\033[45m',
            'cyan': '\033[46m',
            'white': '\033[47m',
            'reset_background': '\033[49m',
        },
        'text_format': {
            'bold': '\033[1m',
            'underline': '\033[4m',
            'italic': '\033[3m',
            'inverse': '\033[7m',
            'blink': '\033[5m',
            'hidden': '\033[8m',
            'strike_through': '\033[9m',
            'frame': '\033[51m',
            'encircled': '\033[52m',
            'overlined': '\033[53m',
            'reset_format': '\033[0m',
        },
        'link': {
            'url_start': '\033]8;;',
            'url_end': '\033]8;;\033\\',
        },
        'utility': {
            'escape_sequence_start': '\033]',
            'escape_sequence_end': '\033\\',
            'enable_alternate_screen_buffer': '\033[?1049h',
            'disable_alternate_screen_buffer': '\033[?1049l',
        }
    }

    @staticmethod
    def get_ansi_code(category, name):
        return AnsiCodeHelper.ansi_codes.get(category, {}).get(name, '')


def ansi_link_str(url, link_text="", link_color='bright_green'):
    # Get the ANSI escape sequence for the default color
    # Check if link text is empty
    if link_text == '':
        link_text = url

    # Check if stdout is a terminal
    if sys.stdout.isatty():
        # get ansi codes
        # default_color_code = AnsiCodeHelper.get_ansi_code('fg_colors', link_color)
        # format_reset_code = AnsiCodeHelper.get_ansi_code('text_format', 'reset_format')
        start_sequence = AnsiCodeHelper.get_ansi_code('utility', 'escape_sequence_start')
        end_sequence = AnsiCodeHelper.get_ansi_code('utility', 'escape_sequence_end')
        # create url link sequence
        url_start = AnsiCodeHelper.get_ansi_code('link', 'url_start')
        url_end = AnsiCodeHelper.get_ansi_code('link', 'url_end')
        link_color_code = AnsiCodeHelper.get_ansi_code('fg_colors', link_color)
        reset_format_code = AnsiCodeHelper.get_ansi_code('text_format', 'reset_format')

        formatted_link_text = f"{url_start}{url}{end_sequence}{link_color_code}{link_text}{reset_format_code}{url_end}"

        # log_info(f'formatted_link_text={formatted_link_text}\n\n')

        return formatted_link_text
    else:
        # If stdout is not a terminal, return the default formatted link text
        return link_text


def ansi_color_str(s, fg='white', bg=None):
    if bg is None:
        color_type = 'fg_colors'
        color_code = AnsiCodeHelper.get_ansi_code(color_type, fg)
        reset_color_code = AnsiCodeHelper.get_ansi_code(color_type, 'reset_color')
        return f"{color_code}{s}{reset_color_code}"
    else:
        fg_color_code = AnsiCodeHelper.get_ansi_code('fg_colors', fg)
        bg_color_code = AnsiCodeHelper.get_ansi_code('bg_colors', bg)
        reset_bg_color_code = AnsiCodeHelper.get_ansi_code('bg_colors', 'reset_background')
        reset_fg_color_code = AnsiCodeHelper.get_ansi_code('fg_colors', 'reset_color')
        return f"{bg_color_code}{fg_color_code}{s}{reset_fg_color_code}{reset_bg_color_code}"


def ansi_format_str(s, format_name):
    format_code = AnsiCodeHelper.get_ansi_code('text_format', format_name)
    reset_format_code = AnsiCodeHelper.get_ansi_code('text_format', 'reset_format')
    return f"{format_code}{s}{reset_format_code}"


def ansi_rainbow_str(message, delay=0.1, iterations=10):
    # init_thread(ansi_rainbow_anim, message, delay)
    rainbow_colors = ['red', 'yellow', 'green', 'blue', 'magenta', 'cyan']
    for _ in range(iterations):
        for color in rainbow_colors:
            color_code = AnsiCodeHelper.get_ansi_code('fg_colors', color)
            reset_color_code = AnsiCodeHelper.get_ansi_code('fg_colors', 'reset_color')
            rainbow_str = ansi_color_str(message, color)
            log_info(rainbow_str, end='\r', flush=True)
            time.sleep(delay)
    log_info('\n')


def print_to_ansi_alt_screen_buffer(info):
    # Enable alternate screen buffer
    sys.stdout.write(
        f"{AnsiCodeHelper.get_ansi_code('utility', 'escape_sequence_start')}{AnsiCodeHelper.get_ansi_code('utility', 'enable_alternate_screen_buffer')}")

    # Display additional information on the alternate screen buffer
    log_info(info)

    # Disable alternate screen buffer
    sys.stdout.write(
        f"{AnsiCodeHelper.get_ansi_code('utility', 'escape_sequence_start')}{AnsiCodeHelper.get_ansi_code('utility', 'disable_alternate_screen_buffer')}")