def print_list(message: list, indent: int = 0) -> str:
    # Have a newline so it's on the same line and add a [
    final_message = "\n["
    for count, value in enumerate(message):
        # Add a newline so the contents are seperate
        final_message += "\n"

        # Indent 4 spaces and multiply by the next indent level, because it's the next indent level
        final_message += ('    ' * (indent + 1))

        # The next if statement does two favors:
        # 1. It allows for prettier printing
        # 2. It allows less function calls
        if type(value) is dict:
            # Add an extra { because there isn't an initial {
            final_message += "{" + print_dict(value, indent + 1)[1:]
        else:
            final_message += printer(value)

        if count != len(message) - 1:
            final_message += ','
    # Add a newline so that the closing ] can be aligned correctly
    final_message += "\n"

    # Add correct indenting and the ]
    final_message += ('    ' * indent) + "]"
    return final_message


def print_dict(message: dict, indent: int = 0) -> str:
    # Have a newline so it's on the same line
    final_message = "\n"

    # Add the appropiate amount of spaces, depending on the indent
    final_message += ('    ' * indent)

    # Add a { if it's the first indent, else, it will be handled in the loop
    final_message += '{' if indent == 0 else ''

    # Loop each k, v pair
    for key, value in message.items():
        # Add a newline so no other content is on that line but that line.
        final_message += "\n"

        # Indent 4 spaces and multiply by the next indent level, because it's the next indent level
        final_message += ('    ' * (indent + 1))

        # Print the key, might be different than string because other objects can be hashable
        # The colon just makes it look more JSON-like
        final_message += printer(key) + ": "

        # The if statement does us two favors:
        # 1. It allows even prettier printing
        # 2. Allows less call functions
        if type(value) is dict:
            # Allows even prettier printing, allowing a { on the same line as the :
            # The [1:] is necessary to ignore the '\n' at the beggining
            final_message += '{' + print_dict(value, indent + 1)[1:]
        elif type(value) is list:
            # Allows even prettier printing
            # The [1:] is necessary to ignore the '\n' at the beggining
            final_message += print_list(value, indent + 1)[1:]
        else:
            # Print the data normally if it's not a special type
            final_message += printer(value)

    # Add a newlie at the end, so that the closing } can be aligned properly
    final_message += "\n"

    # Add correct indenting and the final }
    final_message += ('    ' * indent) + "}"
    return final_message


def reset_printer():
    # In case if we need anything to be reset after calls
    pass


def printer(message) -> str:
    type_functions = {
        "dict": print_dict,
        "list": print_list,
        "str": lambda x: x,
        "other": lambda x: str(x)
    }
    return type_functions[type(message).__name__ if type(message).__name__ in type_functions else "other"](message)
