import gettext as gettext_lib
from otree.common import FULL_DECIMAL_PLACES
from otree import settings
import re


# these symbols are a fallback if we don't have an explicit rule
# for the currency/language combination.
# (most common situation is where the language is English)

CURRENCY_SYMBOLS = {
    'AED': 'AED',
    'ARS': '$',
    'AUD': '$',
    'BRL': 'R$',
    'CAD': '$',
    'CHF': 'CHF',
    # need to use yuan character here, that's what gets shown
    # on form inputs. but if you run a study in english, it will
    # still show 元, which is not ideal. but that is rare.
    'CNY': '元',
    'CZK': 'Kč',
    'DKK': 'kr',
    'EGP': 'ج.م.‏',
    'EUR': '€',
    'GBP': '£',
    'HKD': 'HK$',
    'HUF': 'Ft',
    'ILS': '₪',
    'INR': '₹',
    'JPY': '円',
    'KRW': '원',
    'MXN': '$',
    'MYR': 'RM',
    'NOK': 'kr',
    'PLN': 'zł',
    'RUB': '₽',
    'SEK': 'kr',
    'SGD': 'SGD',
    'THB': 'THB',
    'TRY': '₺',
    'TWD': '$',
    'USD': '$',
    'ZAR': 'R',
}


def get_currency_format(lc: str, LO: str, CUR: str) -> str:

    '''because of all the if statements, this has very low code coverage
    but it's ok'''

    ##############################
    # Languages with complex rules
    ##############################

    if lc == 'en':
        if CUR in ['USD', 'CAD', 'AUD']:
            return '$#'
        if CUR == 'GBP':
            return '£#'
        if CUR == 'EUR':
            return '€#'
        if CUR == 'INR':
            return '₹ #'
        if CUR == 'SGD':
            return '$#'
        # override for CNY/JPY/KRW, otherwise it would be written as 원10
        # need to use the chinese character because that's already what's used in
        # form inputs
        if CUR == 'CNY':
            return '#元'
        if CUR == 'JPY':
            return '#円'
        if CUR == 'KRW':
            return '#원'
        if CUR == 'ZAR':
            return 'R#'
        return '¤#'

    if lc == 'zh':
        if CUR == 'CNY':
            return '#元'
        if CUR == 'HKD':
            return 'HK$#'
        if CUR == 'TWD':
            return '$#'
        if CUR == 'SGD':
            return 'SGD#'
        return '¤#'

    if lc == 'de':
        if CUR == 'EUR':
            if LO == 'AT':
                return '€ #'
            return '# €'
        if CUR == 'CHF':
            return 'CHF #'
        return '¤ #'

    if lc == 'es':
        if CUR == 'ARS':
            return '$ #'
        if CUR == 'EUR':
            return '# €'
        if CUR == 'MXN':
            return '$#'
        return '# ¤'

    if lc == 'nl':
        if LO == 'BE':
            if CUR == 'EUR':
                return '# €'
            return '# ¤'
        # default NL
        if CUR == 'EUR':
            return '€ #'
        return '¤ #'

    if lc == 'pt':
        if CUR == 'BRL':
            return 'R$#'
        if CUR == 'EUR':
            return '# €'
        return '¤#'

    if lc == 'ar':
        if CUR == 'AED':
            return 'د.إ.‏ #'
        return '¤ #'

    #############################
    # Languages with simple rules
    #############################

    if lc == 'cs':
        if CUR == 'CZK':
            return '# Kč'
        return '# ¤'
    if lc == 'da':
        if CUR == 'DKK':
            return '# kr.'
        return '# ¤'
    if lc == 'fi':
        if CUR == 'EUR':
            return '# €'
        return '# ¤'
    if lc == 'fr':
        if CUR == 'EUR':
            return '# €'
        return '# ¤'
    if lc == 'he':
        if CUR == 'ILS':
            return '# ₪'
        return '# ¤'
    if lc == 'hu':
        if CUR == 'HUF':
            return '# Ft'
        return '# ¤'
    if lc == 'it':
        if CUR == 'EUR':
            return '# €'
        return '# ¤'
    if lc == 'ja':
        if CUR == 'JPY':
            return '#円'
        return '¤#'
    if lc == 'ko':
        if CUR == 'KRW':
            return '#원'
        return '¤#'
    if lc == 'ms':
        if CUR == 'MYR':
            return 'RM#'
        return '¤#'
    if lc == 'nb':
        if CUR == 'NOK':
            return 'kr #'
        return '¤ #'
    if lc == 'pl':
        if CUR == 'PLN':
            return '# zł'
        return '# ¤'
    if lc == 'ru':
        if CUR == 'RUB':
            return '# ₽'
        return '# ¤'
    if lc == 'sv':
        if CUR == 'SEK':
            return '# kr'
        return '# ¤'
    if lc == 'th':
        if CUR == 'THB':
            return '฿#'
        return '¤#'
    if lc == 'tr':
        if CUR == 'TRY':
            return '# ₺'
        return '# ¤'
    if lc == 'hi':
        if CUR == 'INR':
            return '₺#'
        return '¤#'

    # fallback if it's another language, etc.
    return '# ¤'


def format_number(number, *, places):
    """we don't use locale.setlocale because e.g.
    only english locale is installed on heroku

    This is a complex function because it's is used by many different things.
    - currency
    - formatting any number (random floats, etc)
    - forms
    - to0, to1, to2

    """
    # we use FULL_DECIMAL_PLACES as the arg because it's more explict than None.
    if places is FULL_DECIMAL_PLACES:
        places = None
    str_number = str(number)
    if '.' in str_number:
        lhs, rhs = str_number.split('.')
    else:
        lhs = str_number
        if places is None:
            return lhs
        rhs = ''
    if places is not None:
        rhs = rhs.ljust(places, '0')
    if places == 0:
        return lhs
    # rhs[:None] just takes the whole thing, which is the desired behavior
    # with floats.
    return lhs + settings.DECIMAL_SEPARATOR + rhs[:places]


def extract_otreetemplate(fileobj, keywords, comment_tags, options):
    """Deprecated"""
    for lineno, line in enumerate(fileobj, start=1):
        for msg in re.findall(r"""\{\{\s?trans ['"](.*)['"]\s?\}\}""", line.decode()):
            yield (lineno, 'trans', msg, [])


def extract_otreetemplate_internal(fileobj, keywords, comment_tags, options):
    """babel custom extractor for |gettext in otree templates"""
    for lineno, line in enumerate(fileobj, start=1):
        for msg in re.findall(
            r"""\{\{\s?['"](.*)['"]\|gettext\s?\}\}""", line.decode()
        ):
            # not sure exactly what the 2nd arg is for
            yield (lineno, 'gettext', msg, [])


def core_gettext(msg):
    return gettext_lib.dgettext('django', msg)


"""
Don't use core-ngettext because pybabel doesn't recognize that it is for
plurals 
"""
