//
//  Roman2Kana.swift
//  Keyboard
//
//  Created by ensan on 2020/09/24.
//  Copyright © 2020 ensan. All rights reserved.
//

import Foundation
import SwiftUtils

enum Roman2Kana {
    static let unstableSuffixes: Set<[Character]> = hiraganaChanges.keys.flatMapSet { characters in
        characters.indices.map { i in
            Array(characters[...i])
        }
    }
    static let katakanaChanges: [String: String] = Dictionary(uniqueKeysWithValues: hiraganaChanges.map { (String($0.key), String($0.value).toKatakana()) })
    static let hiraganaChanges: [[Character]: [Character]] = Dictionary(uniqueKeysWithValues: [
        "a": "あ",
        "xa": "ぁ",
        "la": "ぁ",
        "i": "い",
        "xi": "ぃ",
        "li": "ぃ",
        "u": "う",
        "wu": "う",
        "vu": "ゔ",
        "xu": "ぅ",
        "lu": "ぅ",
        "e": "え",
        "xe": "ぇ",
        "le": "ぇ",
        "o": "お",
        "xo": "ぉ",
        "lo": "ぉ",
        "ka": "か",
        "ca": "か",
        "ga": "が",
        "xka": "ゕ",
        "lka": "ゕ",
        "ki": "き",
        "gi": "ぎ",
        "ku": "く",
        "cu": "く",
        "gu": "ぐ",
        "ke": "け",
        "ge": "げ",
        "xke": "ゖ",
        "lke": "ゖ",
        "ko": "こ",
        "co": "こ",
        "go": "ご",
        "sa": "さ",
        "za": "ざ",
        "si": "し",
        "ci": "し",
        "shi": "し",
        "zi": "じ",
        "ji": "じ",
        "su": "す",
        "zu": "ず",
        "se": "せ",
        "ce": "せ",
        "ze": "ぜ",
        "so": "そ",
        "zo": "ぞ",
        "ta": "た",
        "da": "だ",
        "ti": "ち",
        "chi": "ち",
        "di": "ぢ",
        "tu": "つ",
        "tsu": "つ",
        "xtu": "っ",
        "ltu": "っ",
        "xtsu": "っ",
        "ltsu": "っ",
        "du": "づ",
        "te": "て",
        "de": "で",
        "to": "と",
        "do": "ど",
        "na": "な",
        "ni": "に",
        "nu": "ぬ",
        "ne": "ね",
        "no": "の",
        "ha": "は",
        "ba": "ば",
        "pa": "ぱ",
        "hi": "ひ",
        "bi": "び",
        "pi": "ぴ",
        "hu": "ふ",
        "fu": "ふ",
        "bu": "ぶ",
        "pu": "ぷ",
        "he": "へ",
        "be": "べ",
        "pe": "ぺ",
        "ho": "ほ",
        "bo": "ぼ",
        "po": "ぽ",
        "ma": "ま",
        "mi": "み",
        "mu": "む",
        "me": "め",
        "mo": "も",
        "ya": "や",
        "xya": "ゃ",
        "lya": "ゃ",
        "yu": "ゆ",
        "xyu": "ゅ",
        "lyu": "ゅ",
        "yo": "よ",
        "xyo": "ょ",
        "lyo": "ょ",
        "ra": "ら",
        "ri": "り",
        "ru": "る",
        "re": "れ",
        "ro": "ろ",
        "wa": "わ",
        "xwa": "ゎ",
        "lwa": "ゎ",
        "wyi": "ゐ",
        "wye": "ゑ",
        "wo": "を",
        "nn": "ん",
        "ye": "いぇ",
        "va": "ゔぁ",
        "vi": "ゔぃ",
        "ve": "ゔぇ",
        "vo": "ゔぉ",
        "kya": "きゃ",
        "kyu": "きゅ",
        "kye": "きぇ",
        "kyo": "きょ",
        "gya": "ぎゃ",
        "gyu": "ぎゅ",
        "gye": "ぎぇ",
        "gyo": "ぎょ",
        "qa": "くぁ",
        "kwa": "くぁ",
        "qwa": "くぁ",
        "qi": "くぃ",
        "kwi": "くぃ",
        "qwi": "くぃ",
        "qu": "くぅ",
        "kwu": "くぅ",
        "qwu": "くぅ",
        "qe": "くぇ",
        "kwe": "くぇ",
        "qwe": "くぇ",
        "qo": "くぉ",
        "kwo": "くぉ",
        "qwo": "くぉ",
        "gwa": "ぐぁ",
        "gwi": "ぐぃ",
        "gwu": "ぐぅ",
        "gwe": "ぐぇ",
        "gwo": "ぐぉ",
        "sha": "しゃ",
        "sya": "しゃ",
        "shu": "しゅ",
        "syu": "しゅ",
        "she": "しぇ",
        "sye": "しぇ",
        "sho": "しょ",
        "syo": "しょ",
        "ja": "じゃ",
        "zya": "じゃ",
        "jya": "じゃ",
        "jyi": "じぃ",
        "ju": "じゅ",
        "zyu": "じゅ",
        "jyu": "じゅ",
        "je": "じぇ",
        "zye": "じぇ",
        "jye": "じぇ",
        "jo": "じょ",
        "zyo": "じょ",
        "jyo": "じょ",
        "swa": "すぁ",
        "swi": "すぃ",
        "swu": "すぅ",
        "swe": "すぇ",
        "swo": "すぉ",
        "cha": "ちゃ",
        "cya": "ちゃ",
        "tya": "ちゃ",
        "tyi": "ちぃ",
        "cyi": "ちぃ",
        "chu": "ちゅ",
        "cyu": "ちゅ",
        "tyu": "ちゅ",
        "che": "ちぇ",
        "cye": "ちぇ",
        "tye": "ちぇ",
        "cho": "ちょ",
        "cyo": "ちょ",
        "tyo": "ちょ",
        "tsa": "つぁ",
        "tsi": "つぃ",
        "tse": "つぇ",
        "tso": "つぉ",
        "tha": "てゃ",
        "thi": "てぃ",
        "thu": "てゅ",
        "the": "てぇ",
        "tho": "てょ",
        "twa": "とぁ",
        "twi": "とぃ",
        "twu": "とぅ",
        "twe": "とぇ",
        "two": "とぉ",
        "dya": "ぢゃ",
        "dyi": "ぢぃ",
        "dyu": "ぢゅ",
        "dye": "ぢぇ",
        "dyo": "ぢょ",
        "dha": "でゃ",
        "dhi": "でぃ",
        "dhu": "でゅ",
        "dhe": "でぇ",
        "dho": "でょ",
        "dwa": "どぁ",
        "dwi": "どぃ",
        "dwu": "どぅ",
        "dwe": "どぇ",
        "dwo": "どぉ",
        "nya": "にゃ",
        "nyi": "にぃ",
        "nyu": "にゅ",
        "nye": "にぇ",
        "nyo": "にょ",
        "hya": "ひゃ",
        "hyi": "ひぃ",
        "hyu": "ひゅ",
        "hye": "ひぇ",
        "hyo": "ひょ",
        "bya": "びゃ",
        "byi": "びぃ",
        "byu": "びゅ",
        "bye": "びぇ",
        "byo": "びょ",
        "pya": "ぴゃ",
        "pyi": "ぴぃ",
        "pyu": "ぴゅ",
        "pye": "ぴぇ",
        "pyo": "ぴょ",
        "fa": "ふぁ",
        "hwa": "ふぁ",
        "fwa": "ふぁ",
        "fi": "ふぃ",
        "hwi": "ふぃ",
        "fwi": "ふぃ",
        "fwu": "ふぅ",
        "fe": "ふぇ",
        "hwe": "ふぇ",
        "fwe": "ふぇ",
        "fo": "ふぉ",
        "hwo": "ふぉ",
        "fwo": "ふぉ",
        "fya": "ふゃ",
        "fyu": "ふゅ",
        "fyo": "ふょ",
        "mya": "みゃ",
        "myi": "みぃ",
        "myu": "みゅ",
        "mye": "みぇ",
        "myo": "みょ",
        "rya": "りゃ",
        "ryi": "りぃ",
        "ryu": "りゅ",
        "rye": "りぇ",
        "ryo": "りょ",
        "wi": "うぃ",
        "we": "うぇ",
        "wha": "うぁ",
        "whi": "うぃ",
        "whu": "う",
        "whe": "うぇ",
        "who": "うぉ",
        "xn": "ん",
        "zh": "←",
        "zj": "↓",
        "zk": "↑",
        "zl": "→"
    ].map {(Array($0.key), Array($0.value))})

    static func toHiragana(currentText: [Character], added: Character) -> [Character] {
        let last_3 = currentText.suffix(3)
        if let kana = Roman2Kana.hiraganaChanges[last_3 + [added]] {
            return currentText.prefix(currentText.count - last_3.count) + kana
        }
        let last_2 = currentText.suffix(2)
        if let kana = Roman2Kana.hiraganaChanges[last_2 + [added]] {
            return currentText.prefix(currentText.count - last_2.count) + kana
        }
        let last_1 = currentText.suffix(1)
        if let kana = Roman2Kana.hiraganaChanges[last_1 + [added]] {
            return currentText.prefix(currentText.count - last_1.count) + kana
        }
        if last_1 == [added] && String(added).onlyRomanAlphabet {
            return currentText.prefix(currentText.count - last_1.count) + ["っ", added]
        }
        if last_1 == ["n"] && added != "y"{
            return currentText.prefix(currentText.count - last_1.count) + ["ん", added]
        }

        if let kana = Roman2Kana.hiraganaChanges[[added]] {
            return currentText + kana
        }
        return currentText + [added]
    }
}
