package de.duehl.vocabulary.japanese.data.symbol;

import java.util.ArrayList;
import java.util.List;

import de.duehl.basics.collections.CollectionsHelper;
import de.duehl.basics.text.Text;

/**
 * Diese Klasse stellt die Zeichen der Schrift Hiragana (in UTF-Zeichen) dar.
 *
 * Sie beinhaltet auch Methoden rund darum, um zu fragen, ob eine Zeichenkette ausschließlich
 * aus diesen Zeichen besteht oder wo das erste bzw. letzte dieser Zeichen zu finden ist.
 *
 * @version 1.01     2025-11-30
 * @author Christian Dühl
 */

public enum Hiragana {

    A("あ", "a", KanaSubType.STANDARD),
    I("い", "i", KanaSubType.STANDARD),
    U("う", "u", KanaSubType.STANDARD),
    E("え", "e", KanaSubType.STANDARD),
    O("お", "o", KanaSubType.STANDARD),

    KA("か", "ka", KanaSubType.STANDARD),
    KI("き", "ki", KanaSubType.STANDARD),
    KU("く", "ku", KanaSubType.STANDARD),
    KE("け", "ke", KanaSubType.STANDARD),
    KO("こ", "ko", KanaSubType.STANDARD),

    SA("さ", "sa", KanaSubType.STANDARD),
    SHI("し", "shi", KanaSubType.STANDARD),
    SU("す", "su", KanaSubType.STANDARD),
    SE("せ", "se", KanaSubType.STANDARD),
    SO("そ", "so", KanaSubType.STANDARD),

    TA("た", "ta", KanaSubType.STANDARD),
    CHI("ち", "chi", KanaSubType.STANDARD),
    TSU("つ", "tsu", KanaSubType.STANDARD),
    TE("て", "te", KanaSubType.STANDARD),
    TO("と", "to", KanaSubType.STANDARD),

    NA("な", "na", KanaSubType.STANDARD),
    NI("に", "ni", KanaSubType.STANDARD),
    NU("ぬ", "nu", KanaSubType.STANDARD),
    NE("ね", "ne", KanaSubType.STANDARD),
    NO("の", "no", KanaSubType.STANDARD),

    HA("は", "ha", KanaSubType.STANDARD),
    HI("ひ", "hi", KanaSubType.STANDARD),
    FU("ふ", "fu", KanaSubType.STANDARD),
    HE("へ", "he", KanaSubType.STANDARD),
    HO("ほ", "ho", KanaSubType.STANDARD),

    MA("ま", "ma", KanaSubType.STANDARD),
    MI("み", "mi", KanaSubType.STANDARD),
    MU("む", "mu", KanaSubType.STANDARD),
    ME("め", "me", KanaSubType.STANDARD),
    MO("も", "mo", KanaSubType.STANDARD),

    YA("や", "ya", KanaSubType.STANDARD),
    YU("ゆ", "yu", KanaSubType.STANDARD),
    YO("よ", "yo", KanaSubType.STANDARD),

    SMALL_YA("ゃ", "kleines ya", KanaSubType.SMALL),
    SMALL_YU("ゅ", "kleines yu", KanaSubType.SMALL),
    SMALL_YO("ょ", "kleines yo", KanaSubType.SMALL),

    RA("ら", "ra", KanaSubType.STANDARD),
    RI("り", "ri", KanaSubType.STANDARD),
    RU("る", "ru", KanaSubType.STANDARD),
    RE("れ", "re", KanaSubType.STANDARD),
    RO("ろ", "ro", KanaSubType.STANDARD),

    WA("わ", "wa", KanaSubType.STANDARD),
    WO("を", "wo", KanaSubType.STANDARD),

    N("ん", "n", KanaSubType.STANDARD),

    GA("が", "ga", KanaSubType.WITH_DAKUTEN),
    GI("ぎ", "gi", KanaSubType.WITH_DAKUTEN),
    GU("ぐ", "gu", KanaSubType.WITH_DAKUTEN),
    GE("げ", "ge", KanaSubType.WITH_DAKUTEN),
    GO("ご", "go", KanaSubType.WITH_DAKUTEN),

    ZA("ざ", "za", KanaSubType.WITH_DAKUTEN),
    JI1("じ", "ji", KanaSubType.WITH_DAKUTEN),
    ZU1("ず", "zu", KanaSubType.WITH_DAKUTEN),
    ZE("ぜ", "ze", KanaSubType.WITH_DAKUTEN),
    ZO("ぞ", "zo", KanaSubType.WITH_DAKUTEN),

    DA("だ", "da", KanaSubType.WITH_DAKUTEN),
    JI2("ぢ", "ji", KanaSubType.WITH_DAKUTEN),
    ZU2("づ", "zu", KanaSubType.WITH_DAKUTEN),
    DE("で", "de", KanaSubType.WITH_DAKUTEN),
    DO("ど", "do", KanaSubType.WITH_DAKUTEN),

    BA("ば", "ba", KanaSubType.WITH_DAKUTEN),
    BI("び", "bi", KanaSubType.WITH_DAKUTEN),
    BU("ぶ", "bu", KanaSubType.WITH_DAKUTEN),
    BE("べ", "be", KanaSubType.WITH_DAKUTEN),
    BO("ぼ", "bo", KanaSubType.WITH_DAKUTEN),

    PA("ぱ", "pa", KanaSubType.WITH_HANDAKUTEN),
    PI("ぴ", "pi", KanaSubType.WITH_HANDAKUTEN),
    PU("ぷ", "pu", KanaSubType.WITH_HANDAKUTEN),
    PE("ぺ", "pe", KanaSubType.WITH_HANDAKUTEN),
    PO("ぽ", "po", KanaSubType.WITH_HANDAKUTEN),

    KYA("きゃ", "kya", KanaSubType.COMPOUND),
    KYU("きゅ", "kyu", KanaSubType.COMPOUND),
    KYO("きょ", "kyo", KanaSubType.COMPOUND),

    SHA("しゃ", "sha", KanaSubType.COMPOUND),
    SHU("しゅ", "shu", KanaSubType.COMPOUND),
    SHO("しょ", "sho", KanaSubType.COMPOUND),

    CHA("ちゃ", "cha", KanaSubType.COMPOUND),
    CHU("ちゅ", "chu", KanaSubType.COMPOUND),
    CHO("ちょ", "cho", KanaSubType.COMPOUND),

    NYA("にゃ", "nya", KanaSubType.COMPOUND),
    NYU("にゅ", "nyu", KanaSubType.COMPOUND),
    NYO("にょ", "nyo", KanaSubType.COMPOUND),

    HYA("ひゃ", "hya", KanaSubType.COMPOUND),
    HYU("ひゅ", "hyu", KanaSubType.COMPOUND),
    HYO("ひょ", "hyo", KanaSubType.COMPOUND),

    MYA("みゃ", "mya", KanaSubType.COMPOUND),
    MYU("みゅ", "myu", KanaSubType.COMPOUND),
    MYO("みょ", "myo", KanaSubType.COMPOUND),

    RYA("りゃ", "rya", KanaSubType.COMPOUND),
    RYU("りゅ", "ryu", KanaSubType.COMPOUND),
    RYO("りょ", "ryo", KanaSubType.COMPOUND),

    GYA("ぎゃ", "gya", KanaSubType.COMPOUND_WITH_DAKUTEN),
    GYU("ぎゅ", "gyu", KanaSubType.COMPOUND_WITH_DAKUTEN),
    GYO("ぎょ", "gyo", KanaSubType.COMPOUND_WITH_DAKUTEN),

    JA1("じゃ", "ja", KanaSubType.COMPOUND_WITH_DAKUTEN),
    JU1("じゅ", "ju", KanaSubType.COMPOUND_WITH_DAKUTEN),
    JO1("じょ", "jo", KanaSubType.COMPOUND_WITH_DAKUTEN),

    JA2("ぢゃ", "ja", KanaSubType.COMPOUND_WITH_DAKUTEN),
    JU2("ぢゅ", "ju", KanaSubType.COMPOUND_WITH_DAKUTEN),
    JO2("ぢょ", "jo", KanaSubType.COMPOUND_WITH_DAKUTEN),

    BYA("びゃ", "bya", KanaSubType.COMPOUND_WITH_DAKUTEN),
    BYU("びゅ", "byu", KanaSubType.COMPOUND_WITH_DAKUTEN),
    BYO("びょ", "byo", KanaSubType.COMPOUND_WITH_DAKUTEN),

    PYA("ぴゃ", "pya", KanaSubType.COMPOUND_WITH_HANDAKUTEN),
    PYU("ぴゅ", "pyu", KanaSubType.COMPOUND_WITH_HANDAKUTEN),
    PYO("ぴょ", "pyo", KanaSubType.COMPOUND_WITH_HANDAKUTEN),

    LEHNWORT_WI("ゔぃ", "wi", KanaSubType.FOR_FOREIGN_WORDS),
    LEHNWORT_FA("ふぁ", "fa", KanaSubType.FOR_FOREIGN_WORDS),
    LEHNWORT_TI("てぃ", "ti", KanaSubType.FOR_FOREIGN_WORDS),
    LEHNWORT_DU("どぅ", "du", KanaSubType.FOR_FOREIGN_WORDS),
    LEHNWORT_WE("うぇ", "we", KanaSubType.FOR_FOREIGN_WORDS),
    LEHNWORT_FO("ふぉ", "fo", KanaSubType.FOR_FOREIGN_WORDS),

    SMALL_TSU("っ", "kleines tsu", KanaSubType.SMALL),
    ;

    /** Das Zeichen in UTF-8 Darstellung. */
    private final String character;

    /** Die Hepburn-Darstellung in lateinischen Buchstaben. */
    private final String hepburn;

    /** Die Unterart des Hiragana-Zeichens. */
    private final KanaSubType subType;

    /**
     * Konstruktor.
     *
     * @param character
     *            Das Zeichen in UTF-8 Darstellung.
     * @param hepburn
     *            Die Hepburn-Darstellung in lateinischen Buchstaben.
     * @param subType
     *            Die Unterart des Katakana-Zeichens.
     */
    private Hiragana(String character, String hepburn, KanaSubType subType) {
        this.character = character;
        this.hepburn = hepburn;
        this.subType = subType;
    }

    /** Getter für das Zeichen in UTF-8 Darstellung. */
    public String getCharacter() {
        return character;
    }

    /** Getter für die Hepburn-Darstellung in lateinischen Buchstaben. */
    public String getHepburn() {
        return hepburn;
    }

    /** Getter für die Unterart des Hiragana-Zeichens. */
    public KanaSubType getSubType() {
        return subType;
    }

    /** Gibt das Hiragana-Zeichen als Kana-Objekt zurück. */
    public Kana toKana() {
        Kana kana = new Kana(character, hepburn);
        return kana;
    }

    /** Gibt eine Liste mit den Zeichen der Schrift Hiragana (in UTF-Zeichen) zurück. */
    public static List<String> getAllHiraganaAsStringList() {
        List<String> hiraganaList = new ArrayList<>();

        for (Hiragana hiragana : Hiragana.values()) {
            hiraganaList.add(hiragana.getCharacter());
        }

        return hiraganaList;
    }

    /** Gibt an, ob in dem Text ein Hiragana-Zeichen vorkommt. */
    public static boolean containsHiragana(String text) {
        return Text.contains(text, getAllHiraganaAsStringList());
    }

    /** Gibt an, ob der Text ausschließlich aus Hiragana-Zeichen besteht. */
    public static boolean containsOnlyHiragana(String text) {
        if (text.isEmpty()) {
            return false;
        }
        else {
            List<String> hiragana = getAllHiraganaAsStringList();
            for (String textCharacter : Text.textToCharactersList(text)) {
                if (!hiragana.contains(textCharacter)) {
                    return false;
                }
            }

            return true;
        }
    }

    /**
     * Gibt den Index des ersten Hiragana-Zeichen im Text zurück. Gibt es kein solches, wird -1
     * zurückgegeben.
     */
    public static int firstIndexOfHiragana(String text) {
        List<String> hiragana = getAllHiraganaAsStringList();
        List<String> textCharacters = Text.textToCharactersList(text);

        for (int index = 0; index < textCharacters.size(); ++index) {
            String textCharacter = textCharacters.get(index);
            if (hiragana.contains(textCharacter )) {
                return index;
            }
        }

        return -1;
    }

    /**
     * Gibt den Index des letzten Hiragana-Zeichen im Text zurück. Gibt es kein solches, wird -1
     * zurückgegeben.
     */
    public static int lastIndexOfHiragana(String text) {
        List<String> hiragana = getAllHiraganaAsStringList();
        List<String> textCharacters = Text.textToCharactersList(text);

        for (int index = textCharacters.size() - 1; index >= 0; --index) {
            String textCharacter = textCharacters.get(index);
            if (hiragana.contains(textCharacter )) {
                return index;
            }
        }

        return -1;
    }

    /**
     * Gibt eine Liste mit allen Hiragana zurück, die die gewünschten Unterarten haben.
     *
     * @param kanaSubTypes
     *            Die gewünschten Unterarten.
     * @return Die Liste mit allen Hiragana zurück, die die gewünschten Unterarten haben.
     */
    public static List<Hiragana> getKanasWithSubtypes(KanaSubType ... kanaSubTypes) {
        return getKanasWithSubtypes(CollectionsHelper.arrayToList(kanaSubTypes));
    }

    /**
     * Gibt eine Liste mit allen Hiragana zurück, die die gewünschten Unterarten haben.
     *
     * @param kanaSubTypes
     *            Die gewünschten Unterarten.
     * @return Die Liste mit allen Hiragana zurück, die die gewünschten Unterarten haben.
     */
    public static List<Hiragana> getKanasWithSubtypes(List<KanaSubType> kanaSubTypes) {
        List<Hiragana> list = new ArrayList<>();

        for (Hiragana hiragana : values()) {
            KanaSubType actualSubType = hiragana.getSubType();
            if (kanaSubTypes.contains(actualSubType)) {
                list.add(hiragana);
            }
        }

        return list;
    }

    /** Gibt die Anzahl der bekannten Hiragana zurück. */
    public static int getNumberOfKnownHiragana() {
        return values().length;
    }

    /** Gibt die Anzahl der bekannten Hiragana in Standard-Form zurück. */
    public static int getNumberOfKnownStandardHiragana() {
        List<Hiragana> getKanasWithSubtypes = getKanasWithSubtypes(KanaSubType.STANDARD);
        return getKanasWithSubtypes.size();
    }

    /** Gibt die Hiragana der A-Reihe zurück. */
    public static List<Hiragana> getAHiragana() {
        return CollectionsHelper.buildListFrom(A, I, U, E, O);
    }

    /** Gibt die Hiragana der KA-Reihe zurück. */
    public static List<Hiragana> getKaHiragana() {
        return CollectionsHelper.buildListFrom(KA, KI, KU, KE, KO);
    }

    /** Gibt die Hiragana der GA-Reihe zurück. */
    public static List<Hiragana> getGaHiragana() {
        return CollectionsHelper.buildListFrom(GA, GI, GU, GE, GO);
    }

    /** Gibt die Hiragana der SA-Reihe zurück. */
    public static List<Hiragana> getSaHiragana() {
        return CollectionsHelper.buildListFrom(SA, SHI, SU, SE, SO);
    }

    /** Gibt die Hiragana der ZA-Reihe zurück. */
    public static List<Hiragana> getZaHiragana() {
        return CollectionsHelper.buildListFrom(ZA, JI1, ZU1, ZE, ZO);
    }

    /** Gibt die Hiragana der TA-Reihe zurück. */
    public static List<Hiragana> getTaHiragana() {
        return CollectionsHelper.buildListFrom(TA, CHI, TSU, TE, TO);
    }

    /** Gibt die Hiragana der DA-Reihe zurück. */
    public static List<Hiragana> getDaHiragana() {
        return CollectionsHelper.buildListFrom(DA, JI2, ZU2, DE, DO);
    }

    /** Gibt die Hiragana der NA-Reihe zurück. */
    public static List<Hiragana> getNaHiragana() {
        return CollectionsHelper.buildListFrom(NA, NI, NU, NE, NO);
    }

    /** Gibt die Hiragana der HA-Reihe zurück. */
    public static List<Hiragana> getHaHiragana() {
        return CollectionsHelper.buildListFrom(HA, HI, FU, HE, HO);
    }

    /** Gibt die Hiragana der BA-Reihe zurück. */
    public static List<Hiragana> getBaHiragana() {
        return CollectionsHelper.buildListFrom(BA, BI, BU, BE, BO);
    }

    /** Gibt die Hiragana der PA-Reihe zurück. */
    public static List<Hiragana> getPaHiragana() {
        return CollectionsHelper.buildListFrom(PA, PI, PU, PE, PO);
    }

    /** Gibt die Hiragana der MA-Reihe zurück. */
    public static List<Hiragana> getMaHiragana() {
        return CollectionsHelper.buildListFrom(MA, MI, MU, ME, MO);
    }

    /** Gibt die Hiragana der YA-Reihe zurück. */
    public static List<Hiragana> getYaHiragana() {
        return CollectionsHelper.buildListFrom(YA, YU, YO);
    }

    /** Gibt die Hiragana der RA-Reihe zurück. */
    public static List<Hiragana> getRaHiragana() {
        return CollectionsHelper.buildListFrom(RA, RI, RU, RE, RO);
    }

    /** Gibt die Hiragana die auf i enden zurück. */
    public static List<Hiragana> getHiraganaEndingWithI() {
        return CollectionsHelper.buildListFrom(I, KI, SHI, CHI, NU, HI, MI, RI, GI, JI1, JI2, BI, PI);
    }

    /** Gibt die Hiragana die auf e enden zurück. */
    public static List<Hiragana> getHiraganaEndingWithE() {
        return CollectionsHelper.buildListFrom(E, KE, SE, TE, NE, HE, ME, RE, GE, ZE, DE, BE, PE);
    }

}
