# https://github.com/Greatdane/Convert-Numbers-to-Japanese/blob/master/Convert-Numbers-to-Japanese.py
# Japanese Number Converter
# - Currently using length functions - possible to use Recursive Functions? Difficult with the many exceptions
# - Works up to 9 figures (999999999)

romaji_dict = {".": "ten", "0": "zero", "1": "ichi", "2": "ni", "3": "san", "4": "yon", "5": "go", "6": "roku", "7": "nana",
                "8": "hachi", "9": "kyuu", "10": "juu", "100": "hyaku", "1000": "sen", "10000": "man", "100000000": "oku",
                "300": "sanbyaku", "600": "roppyaku", "800": "happyaku", "3000": "sanzen", "8000":"hassen", "01000": "issen"}

kanji_dict = {".": "点", "0": "零", "1": "一", "2": "二", "3": "三", "4": "四", "5": "五", "6": "六", "7": "七",
                "8": "八", "9": "九", "10": "十", "100": "百", "1000": "千", "10000": "万", "100000000": "億",
              "300": "三百", "600": "六百", "800": "八百", "3000": "三千", "8000":"八千", "01000": "一千"}

hiragana_dict = {".": "てん", "0": "ゼロ", "1": "いち", "2": "に", "3": "さん", "4": "よん", "5": "ご", "6": "ろく", "7": "なな",
                "8": "はち", "9": "きゅう", "10": "じゅう", "100": "ひゃく", "1000": "せん", "10000": "まん", "100000000": "おく",
                 "300": "さんびゃく", "600": "ろっぴゃく", "800": "はっぴゃく", "3000": "さんぜん", "8000":"はっせん", "01000": "いっせん" }

key_dict = {"kanji" : kanji_dict, "hiragana" : hiragana_dict, "romaji": romaji_dict}

def len_one(convert_num,requested_dict):
    # Returns single digit conversion, 0-9
    return requested_dict[convert_num]

def len_two(convert_num,requested_dict):
    # Returns the conversion, when number is of length two (10-99)
    if convert_num[0] == "0": #if 0 is first, return len_one
        return len_one(convert_num[1],requested_dict)
    if convert_num == "10":
        return requested_dict["10"] # Exception, if number is 10, simple return 10
    if convert_num[0] == "1": # When first number is 1, use ten plus second number
        return requested_dict["10"] + " " + len_one(convert_num[1],requested_dict)
    elif convert_num[1] == "0": # If ending number is zero, give first number plus 10
        return len_one(convert_num[0],requested_dict) + " " + requested_dict["10"]
    else:
        num_list = []
        for x in convert_num:
            num_list.append(requested_dict[x])
        num_list.insert(1, requested_dict["10"])
        # Convert to a string (from a list)
        output = ""
        for y in num_list:
            output += y + " "
        output = output[:len(output) - 1]  # take off the space
        return output

def len_three(convert_num,requested_dict):
    # Returns the conversion, when number is of length three (100-999)
    num_list = []
    if convert_num[0] == "1":
        num_list.append(requested_dict["100"])
    elif convert_num[0] == "3":
        num_list.append(requested_dict["300"])
    elif convert_num[0] == "6":
        num_list.append(requested_dict["600"])
    elif convert_num[0] == "8":
        num_list.append(requested_dict["800"])
    else:
        num_list.append(requested_dict[convert_num[0]])
        num_list.append(requested_dict["100"])
    if convert_num[1:] == "00" and len(convert_num) == 3:
        pass
    else:
        if convert_num[1] == "0":
            num_list.append(requested_dict[convert_num[2]])
        else:
            num_list.append(len_two(convert_num[1:], requested_dict))
    output = ""  
    for y in num_list:
         output += y + " "
    output = output[:len(output) - 1]
    return output

def len_four(convert_num,requested_dict, stand_alone):
    # Returns the conversion, when number is of length four (1000-9999)
    num_list = []
    # First, check for zeros (and get deal with them)
    if convert_num == "0000":
        return ""
    while convert_num[0] == "0":
        convert_num = convert_num[1:]
    if len(convert_num) == 1:
        return len_one(convert_num,requested_dict)
    elif len(convert_num) == 2:
        return len_two(convert_num,requested_dict)
    elif len(convert_num) == 3:
        return len_three(convert_num,requested_dict)
    # If no zeros, do the calculation
    else:
        # Have to handle 1000, depending on if its a standalone 1000-9999 or included in a larger number
        if convert_num[0] == "1" and stand_alone:
            num_list.append(requested_dict["1000"])
        elif convert_num[0] == "1":
            num_list.append(requested_dict["01000"])
        elif convert_num[0] == "3":
            num_list.append(requested_dict["3000"])
        elif convert_num[0] == "8":
            num_list.append(requested_dict["8000"])
        else:
            num_list.append(requested_dict[convert_num[0]])
            num_list.append(requested_dict["1000"])
        if convert_num[1:] == "000" and len(convert_num) == 4:
            pass
        else:
            if convert_num[1] == "0":
                num_list.append(len_two(convert_num[2:],requested_dict))
            else:
                num_list.append(len_three(convert_num[1:],requested_dict))
        output = ""
        for y in num_list:
             output += y + " "
        output = output[:len(output) - 1]
        return output


def len_x(convert_num,requested_dict):
    #Returns everything else.. (up to 9 digits)
    num_list = []
    if len(convert_num[0:-4]) == 1:
        num_list.append(requested_dict[convert_num[0:-4]])
        num_list.append(requested_dict["10000"])
    elif len(convert_num[0:-4]) == 2:
        num_list.append(len_two(convert_num[0:2],requested_dict))
        num_list.append(requested_dict["10000"])
    elif len(convert_num[0:-4]) == 3:
        num_list.append(len_three(convert_num[0:3],requested_dict))
        num_list.append(requested_dict["10000"])
    elif len(convert_num[0:-4]) == 4:
        num_list.append(len_four(convert_num[0:4],requested_dict, False))
        num_list.append(requested_dict["10000"])
    elif len(convert_num[0:-4]) == 5:
        num_list.append(requested_dict[convert_num[0]])
        num_list.append(requested_dict["100000000"])
        num_list.append(len_four(convert_num[1:5],requested_dict, False))
        if convert_num[1:5] == "0000":
            pass
        else:
            num_list.append(requested_dict["10000"])
    else:
        assert False, "Not yet implemented, please choose a lower number."
    num_list.append(len_four(convert_num[-4:],requested_dict, False))
    output = ""
    for y in num_list:
         output += y + " "
    output = output[:len(output) - 1]       
    return output

def remove_spaces(convert_result):
    # Remove spaces in Hirigana and Kanji results
    correction = ""
    for x in convert_result:
        if x == " ":
            pass
        else:
         correction += x
    return correction

def do_convert(convert_num,requested_dict):
    #Check lengths and convert accordingly
    if len(convert_num) == 1:
        return(len_one(convert_num,requested_dict))
    elif len(convert_num) == 2:
        return(len_two(convert_num,requested_dict))
    elif len(convert_num) == 3:
        return(len_three(convert_num,requested_dict))
    elif len(convert_num) == 4:
        return(len_four(convert_num,requested_dict, True))
    else:
        return(len_x(convert_num,requested_dict))

def split_Point(split_num,dict_choice):
    # Used if a decmial point is in the string.
    split_num = split_num.split(".")
    split_num_a = split_num[0]
    split_num_b = split_num[1]
    split_num_b_end = " "
    for x in split_num_b:
        split_num_b_end += len_one(x,key_dict[dict_choice]) + " "
    # To account for small exception of small tsu when ending in jyuu in hiragana/romaji
    if split_num_a[-1] == "0" and split_num_a[-2] != "0" and dict_choice == "hiragana":
        small_Tsu = Convert(split_num_a,dict_choice)
        small_Tsu = small_Tsu[0:-1] + "っ"
        return small_Tsu + key_dict[dict_choice]["."] + split_num_b_end
    if split_num_a[-1] == "0" and split_num_a[-2] != "0" and dict_choice == "romaji":
        small_Tsu = Convert(split_num_a,dict_choice)
        small_Tsu = small_Tsu[0:-1] + "t"
        return small_Tsu + key_dict[dict_choice]["."] + split_num_b_end

    return Convert(split_num_a,dict_choice) + " " + key_dict[dict_choice]["."] + split_num_b_end


def do_kanji_convert(convert_num):
    # Converts kanji to arabic number

    if convert_num == "零":
        return 0

    # First, needs to check for MAN 万 and OKU 億 kanji, as need to handle differently, splitting up the numbers at these intervals.
    # key tells us whether we need to add or multiply the numbers, then we create a list of numbers in an order we need to add/multiply
    key = []
    numberList = []
    y = ""
    for x in convert_num:
        if x == "万" or x == "億":
            numberList.append(y)
            key.append("times")
            numberList.append(x)
            key.append("plus")
            y = ""
        else:
            y += x
    if y != "":
        numberList.append(y)

    numberListConverted = []
    baseNumber = ["一", "二", "三", "四", "五", "六", "七", "八", "九"]
    linkNumber = ["十", "百", "千", "万", "億"]

    # Converts the kanji number list to arabic numbers, using the 'base number' and 'link number' list above. For a link number, we would need to
    # link with a base number
    for noX in numberList:
        count = len(noX)
        result = 0
        skip = 1
        for x in reversed(noX):
            addTo = 0
            skip -= 1
            count = count - 1
            if skip == 1:
                continue
            if x in baseNumber:
                for y, z in kanji_dict.items():
                    if z == x:
                        result += int(y)
            elif x in linkNumber:
                if noX[count - 1] in baseNumber and count > 0:
                    for y, z in kanji_dict.items():
                        if z == noX[count - 1]:
                            tempNo = int(y)
                            for y, z in kanji_dict.items():
                                if z == x:
                                    addTo += tempNo * int(y)
                                    result += addTo
                                    skip = 2
                else:
                    for y, z in kanji_dict.items():
                        if z == x:
                            result += int(y)
        numberListConverted.append(int(result))

    result = numberListConverted[0]
    y = 0

    # Iterate over the converted list, and either multiply/add as instructed in key list
    for x in range(1,len(numberListConverted)):
        if key[y] == "plus":
            try:
                if key[y+1] == "times":
                    result = result + numberListConverted[x] * numberListConverted[x+1]
                    y += 1
                else:
                    result += numberListConverted[x]
            except IndexError:
                result += numberListConverted[-1]
                break
        else:
            result = result * numberListConverted[x]
        y += 1

    return result

def Convert(convert_num, dict_choice='hiragana'):
    # Input formatting
    convert_num = str(convert_num)
    convert_num = convert_num.replace(',','')
    dict_choice = dict_choice.lower()

    # If all is selected as dict_choice, return as a list
    if dict_choice == "all":
        result_list = []
        for x in "kanji", "hiragana", "romaji":
            result_list.append(Convert(convert_num,x))
        return result_list

    dictionary = key_dict[dict_choice]
    
    # Exit if length is greater than current limit
    if len(convert_num) > 9:
        return("Number length too long, choose less than 10 digits")

    # Remove any leading zeroes
    while convert_num[0] == "0" and len(convert_num) > 1:
        convert_num = convert_num[1:]

    # Check for decimal places
    if "." in convert_num:
        result = split_Point(convert_num,dict_choice)
    else:
        result = do_convert(convert_num, dictionary)

    # Remove spaces and return result
    if key_dict[dict_choice] == romaji_dict:
        pass
    else:
        result = remove_spaces(result)
    return result

def ConvertKanji(convert_num):
    if convert_num[0] in kanji_dict.values():
        # Check to see if 点 (point) is in the input, and handle by splitting at 点, before and after is handled separately
        if "点" in convert_num:
            point = convert_num.find("点")
            endNumber = ""
            for x in convert_num[point+1:]:
                endNumber += list(kanji_dict.keys())[list(kanji_dict.values()).index(x)]
            return(str(do_kanji_convert(convert_num[0:point])) + "." + endNumber)
        else:
            return(str(do_kanji_convert(convert_num)))
