package de.duehl.vocabulary.japanese.ui.dialog.grammar;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;

import de.duehl.swing.ui.GuiTools;
import de.duehl.swing.ui.components.MultipleElementsPanel;
import de.duehl.swing.ui.components.selections.StringSelection;
import de.duehl.swing.ui.components.selections.tools.SelectionsHelper;
import de.duehl.swing.ui.dialogs.base.ModalDialogBase;
import de.duehl.swing.ui.layout.VerticalLayout;
import de.duehl.vocabulary.japanese.common.persistence.Options;
import de.duehl.vocabulary.japanese.common.persistence.data.HistoricalOwnListPersistanceDataList;
import de.duehl.vocabulary.japanese.data.FumikoDataStructures;
import de.duehl.vocabulary.japanese.data.OwnList;
import de.duehl.vocabulary.japanese.grammar.table.data.GrammarTableType;
import de.duehl.vocabulary.japanese.logic.ownlists.OwnLists;
import de.duehl.vocabulary.japanese.ui.data.FumikoUiObjects;
import de.duehl.vocabulary.japanese.ui.dialog.grammar.options.GrammarTableOptionsPanel;
import de.duehl.vocabulary.japanese.ui.listcommander.selector.OwnListSelector;

import static de.duehl.vocabulary.japanese.grammar.VerbSearchWords.SORTED_VERB_SEARCH_WORDS;
import static de.duehl.vocabulary.japanese.grammar.AdjectiveSearchWords.SORTED_I_ADJEKTIVE_SEARCH_WORDS;
import static de.duehl.vocabulary.japanese.grammar.AdjectiveSearchWords.SORTED_NA_ADJEKTIVE_SEARCH_WORDS;

/**
 * Diese Klasse erzeugt die grafische Oberfläche des Dialoges zur Erstellung von grammatikalischen
 * Tabellen von Verben oder Adjektiven.
 *
 * @version 1.01     2025-11-29
 * @author Christian Dühl
 */

public class GrammarTableCreatorDialog extends ModalDialogBase {

    public static final int VERTICAL_SPACE_BETWEEN_PARTS = 5;
    public static final int VERTICAL_SPACE_IN_PARTS = 3;


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

    /** Zur Eingabe des Titels der Tabelle. */
    private final StringSelection titleSelection;

    /** Das Element zur Auswahl einer eigenen Liste. */
    private final OwnListSelector ownListSelector;

    /** Die Checkboxen für die Verbformen. */
    private final List<JCheckBox> verbFormCheckBoxes;

    /** Die Checkboxen für die I-Adjektivformen. */
    private final List<JCheckBox> iAdjectiveFormCheckBoxes;

    /** Die Checkboxen für die NA-Adjektivformen. */
    private final List<JCheckBox> naAdjectiveFormCheckBoxes;

    /** Der Panel mit den Reitern für die Wahl zwischen den Verben und den Adjektiven. */
    private final JTabbedPane verbOrAdjectiveFormsTabs;

    /** Der Inhalt des Reiters mit den grammatikalischen Formen der Verben. */
    private final JPanel verbFormsTabPanel;

    /** Der Inhalt des Reiters mit den grammatikalischen Formen der I-Adjektiven. */
    private final JPanel iAdjectiveFormsTabPanel;

    /** Der Inhalt des Reiters mit den grammatikalischen Formen der Na-Adjektiven. */
    private final JPanel naAdjectiveFormsTabPanel;

    /**
     * Erzeugt den Panel mit den Optionen und speichert diese am Ende auch wieder im Options-Objekt
     * ab.
     */
    private final GrammarTableOptionsPanel grammarOptionsPanel;

    /** Der Titel der zu erzeugenden Tabelle. */
    private String tableTitle;

    /** Die eigene Liste, aus der die Verben bzw. Adjektive genommen werden. */
    private OwnList ownList;

    /** Die Art der Tabelle. Möglich sind Verben, I- und Na-Adjektive. */
    private GrammarTableType grammarTableType;

    /**
     * Die Suchbegriffe, welch die Spalten der Tabelle darstellen.
     *
     * Diese sind entweder Verb- oder Adjektivformen.
     */
    private List<String> searchWords;

    /** Gibt an, ob der Dialog mit OK beendet wurde. */
    private boolean applied;

    /**
     * Konstruktor.
     *
     * @param dataStructures
     *            Die Datenstrukturen des Vokabeltrainers.
     * @param uiObjects
     *            Die häufig verwendeten Funktionen der grafischen Oberfläche des Vokabeltrainers.
     */
    public GrammarTableCreatorDialog(FumikoDataStructures dataStructures,
            FumikoUiObjects uiObjects) {
        super(uiObjects.getGuiLocation(), uiObjects.getProgramImage(),
                "Erzeugung grammatikalischer Tabllen von Verben oder Adjektiven");
        this.dataStructures = dataStructures;

        titleSelection = new StringSelection("Der Titel der Tabelle");

        Options options = dataStructures.getOptions();
        ownListSelector = new OwnListSelector(dataStructures, uiObjects,
                options.getHistoricalOwnLists(),
                ownList -> selectedOwnListChanged(ownList),
                () -> getLocation());
        ownListSelector.allowSelectAll();
        ownListSelector.createSelector();

        verbFormCheckBoxes = new ArrayList<>();
        iAdjectiveFormCheckBoxes = new ArrayList<>();
        naAdjectiveFormCheckBoxes = new ArrayList<>();
        verbOrAdjectiveFormsTabs = new JTabbedPane();
        verbFormsTabPanel = new JPanel();
        iAdjectiveFormsTabPanel = new JPanel();
        naAdjectiveFormsTabPanel = new JPanel();

        grammarOptionsPanel = new GrammarTableOptionsPanel(options, () -> getLocation(), uiObjects);

        init();
        fillDialog();
    }

    private void selectedOwnListChanged(OwnList ownList) {
        if (!ownListSelector.isOwnListIsConstructedWithAllSelection()) {
            Options options = dataStructures.getOptions();
            HistoricalOwnListPersistanceDataList historicalLists = options.getHistoricalOwnLists();
            historicalLists.addOwnListData(ownList.toOwnListPersistanceData());
        }
        this.ownList = ownList;
        // wird auch aufgerufen, wenn die eigene Liste aus der Historie ausgewählt wird.
    }

    private void init() {
        initTitleSelection();
        initVerbFormCheckBoxes();
        initIAdjectiveFormCheckBoxes();
        initNaAdjectiveFormCheckBoxes();
        initMainTabs();
        initTabPanels();
        initValues();
    }

    private void initTitleSelection() {
        SelectionsHelper.initSelectionAsEditor(titleSelection);
    }

    private void initVerbFormCheckBoxes() {
        initFormCheckBoxes(SORTED_VERB_SEARCH_WORDS, verbFormCheckBoxes);
    }

    private void initIAdjectiveFormCheckBoxes() {
        initFormCheckBoxes(SORTED_I_ADJEKTIVE_SEARCH_WORDS, iAdjectiveFormCheckBoxes);
    }

    private void initNaAdjectiveFormCheckBoxes() {
        initFormCheckBoxes(SORTED_NA_ADJEKTIVE_SEARCH_WORDS, naAdjectiveFormCheckBoxes);
    }

    private void initFormCheckBoxes(List<String> grammarForms, List<JCheckBox> checkBoxes) {
        for (String grammarForm : grammarForms) {
            JCheckBox checkBox = new JCheckBox(grammarForm);
            checkBoxes.add(checkBox);
        }
    }

    private void initMainTabs() {
        verbOrAdjectiveFormsTabs.add("Verbformen",
                GuiTools.createScrollPane(verbFormsTabPanel));
        verbOrAdjectiveFormsTabs.add("I-Adjektivformen",
                GuiTools.createScrollPane(iAdjectiveFormsTabPanel));
        verbOrAdjectiveFormsTabs.add("NA-Adjektivformen",
                GuiTools.createScrollPane(naAdjectiveFormsTabPanel));
    }

    private void initTabPanels() {
        initTabPane(verbFormsTabPanel, verbFormCheckBoxes);
        initTabPane(iAdjectiveFormsTabPanel, iAdjectiveFormCheckBoxes);
        initTabPane(naAdjectiveFormsTabPanel, naAdjectiveFormCheckBoxes);
    }

    private void initTabPane(JPanel formsTabPanel, List<JCheckBox> formCheckBoxes) {
        JPanel panel = new MultipleElementsPanel<JCheckBox>(formCheckBoxes, 3, 5);
        formsTabPanel.setLayout(new BorderLayout());
        formsTabPanel.add(panel, BorderLayout.CENTER);
    }

    private void initValues() {
        tableTitle = "";
        grammarTableType = GrammarTableType.VERB;
        applied = false;
    }

    /** Baut die Gui auf. */
    @Override
    protected void populateDialog() {
        add(createMainPart(), BorderLayout.CENTER);
        add(createButtonPart(), BorderLayout.SOUTH);

        pack();
    }

    private Component createMainPart() {
        JPanel panel = new JPanel();
        panel.setLayout(new VerticalLayout(VERTICAL_SPACE_BETWEEN_PARTS, VerticalLayout.BOTH));

        panel.add(createTitleSelection());
        panel.add(createOwnListSelection());
        panel.add(grammarOptionsPanel.getPanel());
        panel.add(createSearchWordSelection());

        return panel;
    }

    private Component createTitleSelection() {
        JPanel panel = new JPanel();
        panel.setLayout(new VerticalLayout(VERTICAL_SPACE_IN_PARTS, VerticalLayout.BOTH));
        GuiTools.createTitle("Der Titel der erzeugten Tabelle", panel);

        panel.add(titleSelection.getPanel());

        return panel;
    }

    private Component createOwnListSelection() {
        JPanel panel = new JPanel();
        panel.setLayout(new VerticalLayout(VERTICAL_SPACE_IN_PARTS, VerticalLayout.BOTH));
        GuiTools.createTitle("Die eigene Liste, aus der die Verben bzw. Adjektive entnommen werden",
                panel);

        panel.add(ownListSelector.getPanel());

        return panel;
    }

    private Component createSearchWordSelection() {
        JPanel panel = new JPanel();
        panel.setLayout(new VerticalLayout(VERTICAL_SPACE_IN_PARTS, VerticalLayout.BOTH));
        GuiTools.createTitle("Suchworte - die grammatikalischen Formen, die in die Tabelle sollen"
                + " (nur die vom sichtbaren Reiter werden verwendet)",
                panel);

        panel.add(verbOrAdjectiveFormsTabs);
        panel.add(GuiTools.centerHorizontal(createSelectionsButtonsPart()));

        return panel;
    }

    private Component createSelectionsButtonsPart() {
        JPanel panel = new JPanel();
        panel.setLayout(new GridLayout(1, 0, 1, 1));

        panel.add(createSelectAllButton());
        panel.add(createDeselectAllButton());

        return panel;
    }

    private Component createSelectAllButton() {
        JButton button = new JButton("Alle auswählen");
        button.addActionListener(e -> selectAll(true));
        return button;
    }

    private Component createDeselectAllButton() {
        JButton button = new JButton("Alle entfernen");
        button.addActionListener(e -> selectAll(false));
        return button;
    }

    private void selectAll(boolean select) {
        List<JCheckBox> formCheckBoxes = determineActiveFormCheckBoxes();

        for (JCheckBox checkBox : formCheckBoxes) {
            checkBox.setSelected(select);
        }
    }

    private Component createButtonPart() {
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());

        panel.add(createQuitButton(), BorderLayout.WEST);
        panel.add(createOkButton(), BorderLayout.EAST);

        return panel;
    }

    private Component createQuitButton() {
        JButton button = new JButton("Abbrechen");
        button.addActionListener(e -> closeDialog());
        return button;
    }

    private Component createOkButton() {
        JButton button = new JButton("Tabelle erzeugen");
        button.addActionListener(e -> apply());
        return button;
    }

    private void apply() {
        applied = true;

        if (applied) checkOwnListIstValid();
        if (applied) determineTableTitle();
        if (applied) determineVerbOrAdjectivAndSearchWords();
        if (applied) grammarOptionsPanel.storeIntoOptions();

        if (applied) closeDialog();
    }

    private void checkOwnListIstValid() {
        if (ownList == null || ownList.equals(OwnLists.NO_OWN_LIST_FOUND)) {
            GuiTools.informUser(getWindowAsComponent(),
                    "Die Tabellenerstellung kann nicht gestartet werden",
                    "Es wurde keine eigene Liste ausgewählt.");
            applied = false;
        }
    }

    private void determineTableTitle() {
        tableTitle = titleSelection.getTrimmedText();
        if (tableTitle.isBlank()) {
            GuiTools.informUser(getWindowAsComponent(),
                    "Die Tabellenerstellung kann nicht gestartet werden",
                    "Es wurde kein Titel eingegeben.");
            applied = false;
        }
    }

    private void determineVerbOrAdjectivAndSearchWords() {
        List<JCheckBox> formCheckBoxes = determineActiveFormCheckBoxes();

        searchWords = new ArrayList<>();
        for (JCheckBox checkBox : formCheckBoxes) {
            if (checkBox.isSelected()) {
                String text = checkBox.getText();
                searchWords.add(text);
            }
        }
        if (searchWords.isEmpty()) {
            GuiTools.informUser(getWindowAsComponent(),
                    "Die Tabellenerstellung kann nicht gestartet werden",
                    "Es wurden keine grammatikalischen Formen ausgewählt.");
            applied = false;
        }
    }

    private List<JCheckBox> determineActiveFormCheckBoxes() {
        int selectedIndex = verbOrAdjectiveFormsTabs.getSelectedIndex();

        List<JCheckBox> formCheckBoxes;
        if (selectedIndex == 0) {
            grammarTableType = GrammarTableType.VERB;
            formCheckBoxes = verbFormCheckBoxes;
        }
        else if (selectedIndex == 1) {
            grammarTableType = GrammarTableType.I_ADJEKTIV;
            formCheckBoxes = iAdjectiveFormCheckBoxes;
        }
        else if (selectedIndex == 2) {
            grammarTableType = GrammarTableType.NA_ADJEKTIV;
            formCheckBoxes = naAdjectiveFormCheckBoxes;
        }
        else {
            GuiTools.informUser(getWindowAsComponent(),
                    "Die Tabellenerstellung kann nicht gestartet werden",
                    "Es wurde nicht erkannt, ob der Reiter mit den Verb- oder der Reiter mit den "
                            + "Adjektivformen aktiv ist.\n\n"
                            + "Unbekannter Tab Index " + selectedIndex);
            applied = false;
            formCheckBoxes = new ArrayList<>();
        }

        return formCheckBoxes;
    }

    /** Getter für den Titel der zu erzeugenden Tabelle. */
    public String getTableTitle() {
        return tableTitle;
    }

    /** Getter für die eigene Liste, aus der die Verben bzw. Adjektive genommen werden. */
    public OwnList getOwnList() {
        return ownList;
    }

    /** Getter für die Art der Tabelle. Möglich sind Verben, I- und Na-Adjektive. */
    public GrammarTableType getGrammarTableType() {
        return grammarTableType;
    }

    /**
     * Getter für die Suchbegriffe, welch die Spalten der Tabelle darstellen.
     *
     * Diese sind entweder Verb- oder Adjektivformen.
     */
    public List<String> getSearchWords() {
        return searchWords;
    }

    /** Gibt an, ob der Dialog mit OK beendet wurde. */
    public boolean isApplied() {
        return applied;
    }

}
