import argparse
import sys

INDENT = '    '
BOLD = '\033[1m'
FORMAT_END = '\033[0m' 

TEMPLATE = f"""
{BOLD}usage{FORMAT_END}: <<usage>>

{BOLD}DESCRIPTION{FORMAT_END}

{INDENT}<<description>>

{BOLD}REQUIRED PARAMETERS{FORMAT_END}
<<required>>
{BOLD}OPTIONAL PARAMETERS{FORMAT_END}
<<optional>>"""


def format_parameters(params: list) -> str:
    msg = 'No parameters.'
    if params:
        msg = ''
        for i in range(len(params)):
            msg += '\n'
            param = params[i]
            options_string = BOLD + ', '.join(param.option_strings) + FORMAT_END
            is_flag = type(param) in [argparse._StoreTrueAction, argparse._StoreFalseAction, argparse._HelpAction]
            options_string += '' if is_flag else ' [arg]'
            help_string = param.help or 'No help message.'
            msg += f'{BOLD}{options_string}{FORMAT_END}\n\n'
            msg += f'{help_string}\n'
            if param.default and '--help' not in param.option_strings:
                msg += f'{BOLD}Default:{FORMAT_END} {param.default}\n'

    # Indent all lines
    msg = '\n'.join([f'{INDENT}{s}' for s in msg.split('\n')])
    return msg


def format_help(parser) -> str:
    msg = TEMPLATE

    # Format description
    description_str = parser.description or 'No description.'

    # Format usage
    usage_str = parser.usage
    if not usage_str:
        usage_str = f'python {sys.argv[0]}'
        if len(parser._action_groups) > 0 and len(parser._action_groups[0]._group_actions) > 0:
            usage_str += ' [commands]'
        if len(parser._action_groups) > 1 and len(parser._action_groups[1]._group_actions) > 0:
            usage_str += ' [parameters]'
        
    # TODO: handle commands

    # Format parameters
    required_params, optional_params = [], []
    if len(parser._action_groups) > 1:
        required_params = [e for e in parser._action_groups[1]._group_actions if e.required]
        optional_params = [e for e in parser._action_groups[1]._group_actions if not e.required]
    required_params_str = format_parameters(required_params)
    optional_params_str = format_parameters(optional_params)

    msg = msg.replace('<<description>>', description_str)
    msg = msg.replace('<<usage>>', usage_str)
    msg = msg.replace('<<required>>', required_params_str)
    msg = msg.replace('<<optional>>', optional_params_str)
    return msg
