package de.duehl.vocabulary.japanese.ui.dialog.table.kanji;

import java.awt.Color;
import java.util.List;

import javax.swing.table.AbstractTableModel;

import de.duehl.basics.datetime.date.ImmutualDate;
import de.duehl.basics.text.Text;
import de.duehl.vocabulary.japanese.common.color.VocableColors;
import de.duehl.vocabulary.japanese.common.data.InternalAdditionalKanjiData;
import de.duehl.vocabulary.japanese.common.persistence.Options;
import de.duehl.vocabulary.japanese.data.FumikoDataStructures;
import de.duehl.vocabulary.japanese.data.symbol.Kanji;
import de.duehl.vocabulary.japanese.logic.symbol.kanji.internal.InternalKanjiDataRequester;
import de.duehl.vocabulary.japanese.ui.dialog.table.TableHelper;

/**
 * Diese Klasse ist ein eigenes Tabellenmodell für die Ansicht der (bislang eingepflegten) Kanji.
 * Es hält die Daten der Tabelle in Form einer Liste von Kanji-Objekten vor und weiß diese
 * anzuzeigen.
 *
 * @version 1.01     2026-01-01
 * @author Christian Dühl
 */

public class KanjiTableModel extends AbstractTableModel {

    private static final int NUMBER_OF_COLUMNS_WITHOUT_HANDWRITTEN_NUMBER = 17;

    private static final long serialVersionUID = 1L;


    /** Die Liste mit den Kanji der Tabelle. */
    private final List<Kanji> kanjiList;

    /** Die Programmoptionen. */
    private final Options options;

    /** Das Objekt das zu einem Kanji die internen, benutzerabhängigen Daten abrufen kann. */
    private final InternalKanjiDataRequester requester;

    /**
     * Gibt an, ob die Nummer des Kanji in meinen handschriftlichen Heften im Dialog zur
     * Darstellung der Details eines Kanji angezeigt werden soll.
     */
    private final boolean showKanjiNumberInMyHandwrittenKanjiNotebooks;

    /**
     * Konstruktor.
     *
     * @param kanjiList
     *            Die Liste mit den Kanji der Tabelle.
     * @param dataStructures
     *            Die Datenstrukturen des Vokabeltrainers.
     */
    public KanjiTableModel(List<Kanji> kanjiList,
            FumikoDataStructures dataStructures) {
        super();

        this.kanjiList = kanjiList;
        this.options = dataStructures.getOptions();
        this.requester = dataStructures.getInternalKanjiDataRequester();

        showKanjiNumberInMyHandwrittenKanjiNotebooks =
                options.isShowKanjiNumberInMyHandwrittenKanjiNotebooks();
    }

    /** Ermittelt die Zeilenzahl. */
    @Override
    public int getRowCount() {
        return kanjiList.size();
    }

    /** Ermittelt die Spaltenzahl. */
    @Override
    public int getColumnCount() {
        int columnCount = NUMBER_OF_COLUMNS_WITHOUT_HANDWRITTEN_NUMBER;
        if (showKanjiNumberInMyHandwrittenKanjiNotebooks) {
            ++columnCount;
        }
        return columnCount;
    }

    /**
     * Gibt an, ob die Zelle bearbeitbar ist. Dies muss für die Buttons der Fall sein.
     *
     * @param rowIndex
     *            Zeilenindex (die erste hat die 0)
     * @param columnIndex
     *            Spaltenindex (die erste hat die 0)
     */
    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        if (showKanjiNumberInMyHandwrittenKanjiNotebooks) {
            return columnIndex == 10 || columnIndex == 17;
        }
        else {
            return columnIndex == 9 || columnIndex == 16;
        }
    }

    /**
     * Ermittelt den Tabelleninhalt der angegebenen Zelle.
     *
     * Die Tabelle enthält die folgenden Spalten:
     *     - Die laufende Nummer.
     *     - Das Kanji in UTF-8 Darstellung.
     *     - Die deutsche Beschreibung.
     *     - Das Wort in Kanji und Hiragana in der häufigsten Bedeutung.
     *     - Das Wort in Hiragana in der häufigsten Bedeutung.
     *     - Die Nummer des Kanji im Buch "Kanji und Kana" von Wolfgang Hadamitzky.
     *     - Die Seite auf der das Kanji im Buch "Kanji und Kana" von W. Hadamitzky zu finden ist.
     *     - Optional: Nummer in meinem Kanji-Heft.
     *     - Die Liste der sinojapanischen ON-Lesungen des Kanji (groß geschrieben).
     *     - Die Liste der rein japanischen kun-Lesungen des Kanji (klein geschrieben).
     *     - Button zum Betrachten der aller Vokabeln, in denen das Kanji vorkommt.
     * Außerdem die folgenden Spalten aus den internen Kanji-Daten:
     *     - Das Datum an dem das Kanji das erste Mal gesehen wurde.
     *     - Die Anzahl, wie oft das Kanji getestet wurde.
     *     - Die Anzahl, wie oft das Kanji erfolgreich getestet wurde.
     *     - Das Datum des letzten Tests.
     *     - Das Datum des letzten erfolgreichen Tests.
     *     - Das Abschneiden bei den letzten Tests.
     *     - Button zum Betrachten der Kanji mit allen internen Daten
     *
     * @param rowIndex
     *            Zeilenindex (die erste hat die 0)
     * @param columnIndex
     *            Spaltenindex (die erste hat die 0)
     */
    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        Kanji kanji = kanjiList.get(rowIndex);
        InternalAdditionalKanjiData data = requester.getInternalDataForKanji(kanji);
        switch (columnIndex) {
            case 0:
                return rowIndex + 1;
            case 1:
                return kanji.getCharacter();
            case 2:
                return Text.joinWithCommaAndBlank(kanji.getGermanMeanings());
            case 3:
                return kanji.getNormalKanjiHiraganaWord();
            case 4:
                return kanji.getNormalHiraganaWord();
            case 5:
                return kanji.getNumberInKanjiAndKanaBook();
            case 6:
                return kanji.getPageNumberInKanjiAndKanaBook();
            case 7:
                if (showKanjiNumberInMyHandwrittenKanjiNotebooks) {
                    return kanji.getNumberInMyHandwrittenKanjiNotebooks();
                }
                else {
                    return Text.join(", ", kanji.getOnLesungen());
                }
            case 8:
                if (showKanjiNumberInMyHandwrittenKanjiNotebooks) {
                    return Text.join(", ", kanji.getOnLesungen());
                }
                else {
                    return Text.join(", ", kanji.getKunLesungen());
                }
            case 9:
                if (showKanjiNumberInMyHandwrittenKanjiNotebooks) {
                    return Text.join(", ", kanji.getKunLesungen());
                }
                else {
                    return "Vokabeln mit dem Kanji anzeigen";
                }
            case 10:
                if (showKanjiNumberInMyHandwrittenKanjiNotebooks) {
                    return "Vokabeln mit dem Kanji anzeigen";
                }
                else {
                    return data.getFirstSeenDate();
                }
            case 11:
                if (showKanjiNumberInMyHandwrittenKanjiNotebooks) {
                    return data.getFirstSeenDate();
                }
                else {
                    return data.getTestCount();
                }
            case 12:
                if (showKanjiNumberInMyHandwrittenKanjiNotebooks) {
                    return data.getTestCount();
                }
                else {
                    return data.getCorrectTestCount();
                }
            case 13:
                if (showKanjiNumberInMyHandwrittenKanjiNotebooks) {
                    return data.getCorrectTestCount();
                }
                else {
                    return TableHelper.dateOrEmpty(data.getLastTestDate(), data.getTestCount());
                }
            case 14:
                if (showKanjiNumberInMyHandwrittenKanjiNotebooks) {
                    return TableHelper.dateOrEmpty(data.getLastTestDate(), data.getTestCount());
                }
                else {
                    return TableHelper.dateOrEmpty(data.getLastCorrectTestDate(),
                            data.getCorrectTestCount());
                }
            case 15:
                if (showKanjiNumberInMyHandwrittenKanjiNotebooks) {
                    return TableHelper.dateOrEmpty(data.getLastCorrectTestDate(),
                            data.getCorrectTestCount());
                }
                else {
                    return TableHelper.createMonospaceHtml(
                            data.getLastTenTestResultsAsStorageString());
                }
            case 16:
                if (showKanjiNumberInMyHandwrittenKanjiNotebooks) {
                    return TableHelper.createMonospaceHtml(
                            data.getLastTenTestResultsAsStorageString());
                }
                else {
                    return "Details";
                }
            case 17:
                if (showKanjiNumberInMyHandwrittenKanjiNotebooks) {
                    return "Details";
                }
                else {
                    throw new RuntimeException(
                            "Unzuläsiger Spaltenindex ohne handwritten '" + columnIndex + "'.");
                }

            default:
                throw new RuntimeException("Unzuläsiger Spaltenindex '" + columnIndex + "'.");
        }
    }

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        if (showKanjiNumberInMyHandwrittenKanjiNotebooks) {
            switch (columnIndex) {
                case 0:
                case 5:
                case 6:
                case 7:
                case 12:
                case 13:
                    return Integer.class;
                case 1:
                case 2:
                case 3:
                case 4:
                case 8:
                case 9:
                case 16:
                    return String.class;
                case 11:
                case 14:
                case 15:
                    return ImmutualDate.class;
                    // 10 ist der Button zum Anzeigen der zugehörigen Vokabeln
                    // 17 ist der Button zum Anzeigen der Details des Kanji
                default:
                    return String.class;
            }
        }
        else {
            switch (columnIndex) {
                case 0:
                case 5:
                case 6:
                case 11:
                case 12:
                    return Integer.class;
                case 1:
                case 2:
                case 3:
                case 4:
                case 7:
                case 8:
                case 15:
                    return String.class;
                case 10:
                case 13:
                case 14:
                    return ImmutualDate.class;
                    //  9 ist der Button zum Anzeigen der zugehörigen Vokabeln
                    // 16 ist der Button zum Anzeigen der Details des Kanji
                default:
                    return String.class;
            }
        }
    }

    /**
     * Erzeugt die Vordergrundfarbe für die Zeile mit dem übergebenen Zeilenindex.
     *
     * @param rowIndex
     *            Zeilenindex (die erste hat die 0)
     * @return Farbwert für den Vordergrund.
     */
    public Color determineRowForegroundColor(int rowIndex) {
        Kanji kanji = kanjiList.get(rowIndex);
        InternalAdditionalKanjiData data = requester.getInternalDataForKanji(kanji);
        VocableColors vocableColors = new VocableColors(options);
        return vocableColors.determineKanjiForegroundColor(data, true);
    }

    /**
     * Erzeugt die Hintergrundfarbe für die Zeile mit dem übergebenen Zeilenindex.
     *
     * @param rowIndex
     *            Zeilenindex (die erste hat die 0)
     * @return Farbwert für den Hintergrund.
     */
    public Color determineRowBackgroundColor(int rowIndex) {
        Kanji kanji = kanjiList.get(rowIndex);
        InternalAdditionalKanjiData data = requester.getInternalDataForKanji(kanji);
        VocableColors vocableColors = new VocableColors(options);
        return vocableColors.determineKanjiBackgroundColor(data, true);
    }

}
