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
