# Path: ledgerbil/colorable.py
# class Colorable:
# 
#     START_CODE = "\033"
#     END_CODE = f"{START_CODE}[0m"
# 
#     BRIGHT_OFFSET = 60
# 
#     COLORS = {
#         "black": 30,
#         "gray": 30,
#         "grey": 30,
#         "red": 31,
#         "green": 32,
#         "yellow": 33,
#         "blue": 34,
#         "magenta": 35,
#         "purple": 35,
#         "cyan": 36,
#         "white": 37,
#     }
# 
#     ansi_escape = re.compile(r"\x1B\[[0-?]*[ -/]*[@-~]")
# 
#     def __init__(self, color, value, fmt="", bright=False):
# 
#         if color not in self.COLORS:
#             raise UnsupportedColorError(
#                 f"I don't know what to do with this color: {color}"
#             )
# 
#         self.my_color = color
#         self.value = value
#         self.bright = bright
#         self.format_string = fmt
# 
#     def __repr__(self):
#         return (
#             f"Colorable('{self.my_color}', '{self.value}', "
#             f"fmt='{self.format_string}', bright={self.bright})"
#         )
# 
#     def __str__(self):
#         start = self.ansi_sequence(self.COLORS[self.my_color], bright=self.bright)
#         ansi_str = f"{start}{self.value:{self.format_string}}{self.END_CODE}"
#         return ansi_str
# 
#     def __len__(self):
#         return len(self.value)
# 
#     def __eq__(self, other):
#         return str(self) == str(other)
# 
#     def ansi_sequence(self, code, bright=False):
#         offset = 60 if bright else 0
#         color = code + offset
#         return f"{self.START_CODE}[0;{color}m"
# 
#     def plain(self):
#         return self.value
# 
#     @staticmethod
#     def get_plain_string(ansi_string):
#         return Colorable.ansi_escape.sub("", ansi_string)
# 
# Path: ledgerbil/ledgerbilexceptions.py
# ERROR_RETURN_VALUE = 1
# 
# class LdgReconcilerError(LdgException):
#     pass
# 
# Path: ledgerbil/settings_getter.py
# def get_setting(setting, default=None):
#     if settings and hasattr(settings, setting):
#         return getattr(settings, setting)
# 
#     return defaults.get(setting, default)


import ast
import operator as op
import re
import shlex
import sys
from datetime import datetime
from functools import reduce
from .colorable import Colorable
from .ledgerbilexceptions import ERROR_RETURN_VALUE, LdgReconcilerError
from .settings_getter import get_setting

def get_plain_amount(amount, colwidth=1, decimals=2, prefix="$ "):
    amount_formatted = f"{prefix}{get_amount_str(amount, decimals)}"
    return f"{amount_formatted:>{colwidth}}"


def get_colored_amount(
    amount, colwidth=1, decimals=2, prefix="$ ", positive="green", zero="green"
):

    amount_formatted = f"{prefix}{get_amount_str(amount, decimals)}"
    # avoid inconsistent 0 coloring from round/float intrigue
    if amount_formatted == f"{prefix}{0:.{decimals}f}":
        amount = 0

    if amount == 0:
        color = zero
    elif amount < 0:
        color = "red"
    else:
        color = positive

    return str(Colorable(color, amount_formatted, f">{colwidth}"))


def assert_only_one_matching_account(accounts):
    if len(set(accounts)) > 1:
        message = "More than one matching account:\n"
        for account in sorted(accounts):
            message += f"    {account}\n"

# Path: ledgerbil/colorable.py
# class Colorable:
# 
#     START_CODE = "\033"
#     END_CODE = f"{START_CODE}[0m"
# 
#     BRIGHT_OFFSET = 60
# 
#     COLORS = {
#         "black": 30,
#         "gray": 30,
#         "grey": 30,
#         "red": 31,
#         "green": 32,
#         "yellow": 33,
#         "blue": 34,
#         "magenta": 35,
#         "purple": 35,
#         "cyan": 36,
#         "white": 37,
#     }
# 
#     ansi_escape = re.compile(r"\x1B\[[0-?]*[ -/]*[@-~]")
# 
#     def __init__(self, color, value, fmt="", bright=False):
# 
#         if color not in self.COLORS:
#             raise UnsupportedColorError(
#                 f"I don't know what to do with this color: {color}"
#             )
# 
#         self.my_color = color
#         self.value = value
#         self.bright = bright
#         self.format_string = fmt
# 
#     def __repr__(self):
#         return (
#             f"Colorable('{self.my_color}', '{self.value}', "
#             f"fmt='{self.format_string}', bright={self.bright})"
#         )
# 
#     def __str__(self):
#         start = self.ansi_sequence(self.COLORS[self.my_color], bright=self.bright)
#         ansi_str = f"{start}{self.value:{self.format_string}}{self.END_CODE}"
#         return ansi_str
# 
#     def __len__(self):
#         return len(self.value)
# 
#     def __eq__(self, other):
#         return str(self) == str(other)
# 
#     def ansi_sequence(self, code, bright=False):
#         offset = 60 if bright else 0
#         color = code + offset
#         return f"{self.START_CODE}[0;{color}m"
# 
#     def plain(self):
#         return self.value
# 
#     @staticmethod
#     def get_plain_string(ansi_string):
#         return Colorable.ansi_escape.sub("", ansi_string)
# 
# Path: ledgerbil/ledgerbilexceptions.py
# ERROR_RETURN_VALUE = 1
# 
# class LdgReconcilerError(LdgException):
#     pass
# 
# Path: ledgerbil/settings_getter.py
# def get_setting(setting, default=None):
#     if settings and hasattr(settings, setting):
#         return getattr(settings, setting)
# 
#     return defaults.get(setting, default)


# Path: ledgerbil/util.py
import ast
import operator as op
import re
import shlex
import sys
from datetime import datetime
from functools import reduce
from .colorable import Colorable
from .ledgerbilexceptions import ERROR_RETURN_VALUE, LdgReconcilerError
from .settings_getter import get_setting


def get_plain_amount(amount, colwidth=1, decimals=2, prefix="$ "):
    amount_formatted = f"{prefix}{get_amount_str(amount, decimals)}"
    return f"{amount_formatted:>{colwidth}}"


def get_colored_amount(
    amount, colwidth=1, decimals=2, prefix="$ ", positive="green", zero="green"
):

    amount_formatted = f"{prefix}{get_amount_str(amount, decimals)}"
    # avoid inconsistent 0 coloring from round/float intrigue
    if amount_formatted == f"{prefix}{0:.{decimals}f}":
        amount = 0

    if amount == 0:
        color = zero
    elif amount < 0:
        color = "red"
    else:
        color = positive

    return str(Colorable(color, amount_formatted, f">{colwidth}"))


def assert_only_one_matching_account(accounts):
    if len(set(accounts)) > 1:
        message = "More than one matching account:\n"
        for account in sorted(accounts):
            message += f"    {account}\n"

        raise LdgReconcilerError(message[:-1])