package de.duehl.vocabulary.japanese.ui.tabs;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.JTabbedPane;

import de.duehl.vocabulary.japanese.common.persistence.Options;
import de.duehl.vocabulary.japanese.data.FumikoDataStructures;
import de.duehl.vocabulary.japanese.data.OwnList;
import de.duehl.vocabulary.japanese.data.Vocable;
import de.duehl.vocabulary.japanese.data.Vocabulary;
import de.duehl.vocabulary.japanese.logic.VocabularyTrainerLogic;
import de.duehl.vocabulary.japanese.ui.VocabularyTrainerGui;
import de.duehl.vocabulary.japanese.ui.components.bars.VocabularyBar;
import de.duehl.vocabulary.japanese.ui.data.FumikoUiObjects;

/**
 * Diese Klasse stellt Panel mit den Reitern für die Unterkategorien (zur übergeordneten
 * Kategorie) dar.
 *
 * @version 1.01     2025-11-20
 * @author Christian Dühl
 */

public class SubCategoryTabs {

    /** Die Unterkategorien, die hier dargestellt werden. */
    private final List<String> subCategoriesOfCategory;

    /** Die Logik des Vokabel-Trainers. */
    private final VocabularyTrainerLogic logic;

    /** Die grafische Oberfläche des Vokabel-Trainers. */
    private final VocabularyTrainerGui gui;

    /** Die Datenstrukturen des Vokabeltrainers. */
    private final FumikoDataStructures dataStructures;

    /** Die häufig verwendeten Funktionen der grafischen Oberfläche des Vokabeltrainers. */
    private final FumikoUiObjects uiObjects;

    /**
     * Das Verzeichnis der Listen von Vokabularien nach der Unterkategorie (in der übergeordneten
     * Kategorie).
     */
    private final Map<String, List<Vocabulary>> vocabularyBySubCategoryList;

    /** Der Panel mit den Reitern für die Unterkategorien. */
    private final JTabbedPane subCategoryTabs;

    /** Die Liste der Panels mit den Bars zu den Vokabularien. */
    private final List<VocabularyPanel> vocabularyPanels;

    /**
     * Konstruktor.
     *
     * @param subCategoriesOfCategory
     *            Die Unterkategorien, die hier dargestellt werden.
     * @param vocabulariesOfCategory
     *            Die Vokabularien die die übergeordneten Kategorie haben.
     * @param logic
     *            Die Logik des Vokabel-Trainers.
     * @param gui
     *            Die grafische Oberfläche des Vokabel-Trainers.
     * @param dataStructures
     *            Die Datenstrukturen des Vokabeltrainers..
     * @param uiObjects
     *            Die häufig verwendeten Funktionen der grafischen Oberfläche des Vokabeltrainers.
     */
    public SubCategoryTabs(List<String> subCategoriesOfCategory,
            List<Vocabulary> vocabulariesOfCategory, VocabularyTrainerLogic logic,
            VocabularyTrainerGui gui, FumikoDataStructures dataStructures,
            FumikoUiObjects uiObjects) {
        this.subCategoriesOfCategory = subCategoriesOfCategory;
        this.logic = logic;
        this.gui = gui;
        this.dataStructures = dataStructures;
        this.uiObjects = uiObjects;

        vocabularyBySubCategoryList =
                createVocabulariesBySubCategoryMap(vocabulariesOfCategory);

        subCategoryTabs = new JTabbedPane();
        vocabularyPanels = new ArrayList<>();

        populateSubCategoryTabs();
    }

    private Map<String, List<Vocabulary>> createVocabulariesBySubCategoryMap(
            List<Vocabulary> vocabulariesOfCategory) {
        Map<String, List<Vocabulary>> vocybularyBySubCategoryList = new HashMap<>();

        for (Vocabulary vocabulary : vocabulariesOfCategory) {
            String subCategory = vocabulary.getSubCategory();
            if (!vocybularyBySubCategoryList.containsKey(subCategory)) {
                vocybularyBySubCategoryList.put(subCategory, new ArrayList<>());
            }
            List<Vocabulary> list = vocybularyBySubCategoryList.get(subCategory);
            list.add(vocabulary);
        }

        return vocybularyBySubCategoryList;
    }

    private void populateSubCategoryTabs() {
        for (String subCategory : subCategoriesOfCategory) {
            populateForSubCategory(subCategory);
        }
    }

    private void populateForSubCategory(String subCategory) {
        if (!vocabularyBySubCategoryList.containsKey(subCategory)) {
            throw new RuntimeException("Zur Unterkategorie '" + subCategory + "' wurde keine "
                    + "Liste an Vokabularien gefunden.");
        }

        List<Vocabulary> vocabulariesOfSubCategory = vocabularyBySubCategoryList.get(subCategory);
        VocabularyPanel vocabularyPanel = new VocabularyPanel(vocabulariesOfSubCategory, logic, gui,
                dataStructures, uiObjects);
        subCategoryTabs.add(subCategory, vocabularyPanel.getVocabularyPanel());

        vocabularyPanels.add(vocabularyPanel);
    }

    /**
     * Hier werden die persistent gespeicherten zuletzt aktiven Tabs sowohl bei den Vokabularien
     * als auch bei den eigenen Listen wieder angezeigt.
     *
     * Das Gegenstück zu dieser Methode ist storeShownTabIndices().
     */
    public void showTabsWeViewedLastTime(String lastShownTabIndexType) {
        Options options = dataStructures.getOptions();
        int lastShownSubCategoryTabIndex;
        if (lastShownTabIndexType.equals(MainTabs.VOCABULARY_LAST_SHOWN_TAB_INDEX_TYPE)) {
            lastShownSubCategoryTabIndex = options.getLastShownVocabularySubCategoryTabIndex();
        }
        else if (lastShownTabIndexType.equals(MainTabs.OWN_LIST_LAST_SHOWN_TAB_INDEX_TYPE)) {
            lastShownSubCategoryTabIndex = options.getLastShownOwnListSubCategoryTabIndex();
        }
        else {
            throw new RuntimeException(
                    "Unbekannter lastShownTabIndexType '" + lastShownTabIndexType + "'.");
        }

        if (lastShownSubCategoryTabIndex >= 0
                && lastShownSubCategoryTabIndex < subCategoryTabs.getTabCount()) {
            subCategoryTabs.setSelectedIndex(lastShownSubCategoryTabIndex);
        }
    }

    /**
     * Speichert die Indices des aktuell angezeigten Tabs in jeder Kategorie in den Optionen.
     *
     * Das Gegenstück zu dieser Methode ist showTabsWeViewedLastTime().
     */
    public void storeShownTabIndices(Options options, String lastShownTabIndexType) {
        int lastShownSubCategoryTabIndex = subCategoryTabs.getSelectedIndex();

        if (lastShownTabIndexType.equals(MainTabs.VOCABULARY_LAST_SHOWN_TAB_INDEX_TYPE)) {
            options.setLastShownVocabularySubCategoryTabIndex(lastShownSubCategoryTabIndex);
        }
        else if (lastShownTabIndexType.equals(MainTabs.OWN_LIST_LAST_SHOWN_TAB_INDEX_TYPE)) {
            options.setLastShownOwnListSubCategoryTabIndex(lastShownSubCategoryTabIndex);
        }
        else {
            throw new RuntimeException(
                    "Unbekannter lastShownTabIndexType '" + lastShownTabIndexType + "'.");
        }
    }

    /** Ermittelt die Liste der Vokabeln aus den ausgewählten Vokabularien. */
    public List<Vocable> collectVocablesOfSelectedVocabularies() {
        List<Vocable> vocables = new ArrayList<>();

        for (VocabularyPanel vocabularyPanel : vocabularyPanels) {
            vocables.addAll(vocabularyPanel.collectVocablesOfSelectedVocabularies());
        }

        return vocables;
    }

    /** Sortiert die angezeigten Vokabularien so, wie es in den Optionen eingetragen ist. */
    public void showVocabularyBarsInWantedOrder() {
        for (VocabularyPanel vocabularyPanel : vocabularyPanels) {
            vocabularyPanel.showVocabularyBarsInWantedOrder();
        }
    }

    /** Zeigt oder versteckt die Buttons zur individuellen Sortierung der Vokabularien. */
    public void showOrHideIndividualVocabularySortModeMoveButtons() {
        for (VocabularyPanel vocabularyPanel : vocabularyPanels) {
            vocabularyPanel.showOrHideIndividualVocabularySortModeMoveButtons();
        }
    }

    /**
     * Gibt die Vokabularien in der benutzerdefinierten Reihenfolge zurück.
     *
     * Wird nur aufgerufen, wenn die Vokabularien auch in der individuellen Sortierung angezeigt
     * werden.
     */
    public List<Vocabulary> getVocabularyBarsInIndividualOrder() {
        List<Vocabulary> list = new ArrayList<>();

        for (VocabularyPanel vocabularyPanel : vocabularyPanels) {
            list.addAll(vocabularyPanel.getVocabularyBarsInIndividualOrder());
        }

        return list;
    }

    /**
     * Gibt die OwnLists in der benutzerdefinierten Reihenfolge zurück.
     *
     * Wird nur aufgerufen, wenn die Vokabularien auch in der individuellen Sortierung angezeigt
     * werden.
     */
    public List<OwnList> getOwnListsInIndividualOrder() {
        List<OwnList> list = new ArrayList<>();

        for (VocabularyPanel vocabularyPanel : vocabularyPanels) {
            list.addAll(vocabularyPanel.getOwnListsInIndividualOrder());
        }

        return list;
    }

    /** Ermittelt die auf dem aktuellen Reiter angezeigten VocabularyBars. */
    public List<VocabularyBar> determineBarsOfSelectedTab() {
        int selectedIndex = subCategoryTabs.getSelectedIndex();

        VocabularyPanel vocabularyPanel = vocabularyPanels.get(selectedIndex);
        // Die Indizes passen überein.

        return vocabularyPanel.getBars();
    }

    /**
     * Setzt die Vordergrundfarbe auf den nach den Optionen und ggf. dem Durchschnitt der
     * erfolgreichen Abfrage der Vokabeln aus dem Vokabular in allen Vokabularien richtig.
     */
    public void setCorrectForegroundColorOfVocabularyBars() {
        for (VocabularyPanel vocabularyPanel : vocabularyPanels) {
            vocabularyPanel.setCorrectForegroundColorOfVocabularyBars();
        }
    }

    /** Aktualisiert den angezeigten Text in allen Vokabularien je nach den Optionen. */
    public void setCorrectTextOfVocabularyBars() {
        for (VocabularyPanel vocabularyPanel : vocabularyPanels) {
            vocabularyPanel.setCorrectTextOfVocabularyBars();
        }
    }

    /**
     * Aktualisiert den angezeigten Text zum Prozent des Erfolges in allen Vokabularien je nach den
     * Optionen.
     */
    public void showOrHidePercentInVocabularyBarsLater() {
        for (VocabularyPanel vocabularyPanel : vocabularyPanels) {
            vocabularyPanel.showOrHidePercentInVocabularyBars();
        }
    }

    /** Getter für den Panel mit den Reitern für die Unterkategorien. */
    public JTabbedPane getSubCategoryTabs() {
        return subCategoryTabs;
    }

    /**
     * Zeigt auf dem Übersetzen-Buttons aller Bars das richtige Icon für die Richtung der
     * Übersetzung an.
     */
    public void showTranslationDirectionOnBarButtons() {
        for (VocabularyPanel vocabularyPanel : vocabularyPanels) {
            vocabularyPanel.showTranslationDirectionOnBarButtons();
        }
    }

    /** Buttons zum Exportieren, Bearbeiten und Löschen von eigene Listen ein oder ausschalten. */
    public void toggleShowOwnListButtons() {
        for (VocabularyPanel vocabularyPanel : vocabularyPanels) {
            vocabularyPanel.toggleShowOwnListButtons();
        }
    }

    /** Zeigt die normalen Button zum Abfragen und betrachten der Vokabularien an. */
    public void showTestViewListSheetButtons() {
        for (VocabularyPanel vocabularyPanel : vocabularyPanels) {
            vocabularyPanel.showTestViewListSheetButtons();
        }
    }

    /** Zeigt bei eigenen Listen die Buttons zum Löschen, Bearbeiten und Exportieren an. */
    public void showOwnListExtraButtons() {
        for (VocabularyPanel vocabularyPanel : vocabularyPanels) {
            vocabularyPanel.showOwnListExtraButtons();
        }
    }

}
