package de.duehl.vocabulary.japanese.logic.symbol.kanji.unknown;

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

import de.duehl.basics.collections.CollectionsHelper;
import de.duehl.basics.text.Text;
import de.duehl.vocabulary.japanese.data.Vocable;
import de.duehl.vocabulary.japanese.data.Vocabulary;
import de.duehl.vocabulary.japanese.data.symbol.Hiragana;
import de.duehl.vocabulary.japanese.data.symbol.Digits;
import de.duehl.vocabulary.japanese.data.symbol.Kanji;
import de.duehl.vocabulary.japanese.data.symbol.Katakana;
import de.duehl.vocabulary.japanese.data.symbol.Punctuation;
import de.duehl.vocabulary.japanese.data.symbol.Romaji;

/**
 * Diese Klasse ermittelt die unbekannten Zeichen aus den Kanji-Darstellungen aller Vokabeln.
 *
 * @version 1.01     2026-05-07
 * @author Christian Dühl
 */

public class UnknownCharactersInKanjiFieldOfVocablesDeterminer {

    /** Die Liste mit den bekannten Vokabularien. */
    private final List<Vocabulary> vocabularies;

    /** Die Liste mit den ermittelten unbekannten Zeichen. */
    private List<String> unknownCharacters;

    /**
     * Konstruktor.
     *
     * @param vocabularies
     *            Die Liste mit den bekannten Vokabularien.
     */
    public UnknownCharactersInKanjiFieldOfVocablesDeterminer(List<Vocabulary> vocabularies) {
        this.vocabularies = vocabularies;
    }

    /** Ermittelt die unbekannten Zeichen aus den Kanji-Darstellungen aller Vokabeln. */
    public void determine() {
        unknownCharacters = new ArrayList<>();

        for (Vocabulary vocabulary : vocabularies) {
            for (Vocable vocable : vocabulary.getVocables()) {
                determine(vocable);
            }
        }

        CollectionsHelper.makeListDisjunct(unknownCharacters);
        Collections.sort(unknownCharacters);
    }

    private void determine(Vocable vocable) {
        String kanji = vocable.getKanji();
        List<String> characters = Text.textToCharactersListForComplexUtf8(kanji);

        for (String character : characters) {
            if (isUnknown(character) && !unknownCharacters.contains(character)) {
                unknownCharacters.add(character);
                /* TODO REMOVE
                String hex = HexFormat.of().formatHex(character.getBytes());
                if (hex.equals("3f")) {
                    System.out.println("3f: " + kanji + " - " + vocable);
                }
                */
            }
        }
    }

    private boolean isUnknown(String character) {
        return !isKnown(character);
    }

    private boolean isKnown(String character) {
        for (String hiragana : Hiragana.getAllHiraganaAsStringList()) {
            if (character.equals(hiragana)) {
                return true;
            }
        }
        for (String katakana : Katakana.getAllKatakanaAsStringList()) {
            if (character.equals(katakana)) {
                return true;
            }
        }
        for (String kanji : Kanji.getAllKanjiAsStringList()) {
            if (character.equals(kanji)) {
                return true;
            }
        }
        for (String punctuation : Punctuation.getAllPunctuationAsStringList()) {
            if (character.equals(punctuation)) {
                return true;
            }
        }
        for (String digit : Digits.getAllDigitsAsStringList()) {
            if (character.equals(digit)) {
                return true;
            }
        }
        for (String romaji : Romaji.getAllRomajiAsStringList()) {
            if (character.equals(romaji)) {
                return true;
            }
        }

        if (Text.MIXED_CHARS.contains(character)) {
            return true;
        }
        if (Text.DIGITS.contains(character)) {
            return true;
        }
        if (Text.PUNCTUATION.contains(character)) {
            return true;
        }
        if (character.equals(" ")) {
            return true;
        }

        return false;
    }

    /** Getter für die Liste mit den ermittelten unbekannten Zeichen. */
   public List<String> getUnknownCharacters() {
        return unknownCharacters;
    }

}
