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

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Point;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;

import de.duehl.basics.io.FileHelper;
import de.duehl.basics.text.Text;
import de.duehl.basics.text.html.HtmlTool;
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.dialogs.base.ModalDialogBase;
import de.duehl.vocabulary.japanese.common.persistence.Options;
import de.duehl.vocabulary.japanese.ui.data.FumikoUiObjects;
import de.duehl.vocabulary.japanese.ui.dialog.grammar.headers.data.GrammarFormAndStringSelection;
import de.duehl.vocabulary.japanese.ui.dialog.grammar.headers.io.GrammarTableOwnHeadersLoader;
import de.duehl.vocabulary.japanese.ui.dialog.grammar.headers.io.GrammarTableOwnHeadersSaver;
import de.duehl.vocabulary.japanese.ui.dialog.grammar.headers.tools.GrammarTableHeaderFieldsToMapCreator;

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;
import static de.duehl.vocabulary.japanese.grammar.VerbSearchWords.SORTED_VERB_SEARCH_WORDS;

/**
 * Diese Klasse erzeugt die grafische Oberfläche des Dialoges zur Bearbeitung der Überschriften
 * für die Erstellung von grammatikalischen Tabellen von Verben oder Adjektiven.
 *
 * Standardmäßig werden als die Überschriften die von mir bei der Vokabelerstellung vergebenen,
 * länglichen, aber eindeutigen Texte verwendet. Für im Unterricht oder zum Lernen zu verwendenden
 * Tabellen hat man aber vielleicht lieber "ています" als "höfliche Verlaufsform Gegenwart über der
 * Tabelle stehen. Daher kann man hier eigene Texte dafür vergeben.
 *
 * Die hier leer gelassenen Felder werden nicht überschrieben, sondern behalten die originalen,
 * von mir vorgegebenen Inhalte.
 *
 * @version 1.01     2025-11-29
 * @author Christian Dühl
 */

public class GrammarTableHeaderEditor extends ModalDialogBase {

    private static final String EXPLANATION = """
            Hier werden die Überschriften für die Erstellung von grammatikalischen Tabellen von
            Verben oder Adjektiven bearbeitet.

            Standardmäßig werden als die Überschriften die von mir bei der Vokabelerstellung ver-
            gebenen, länglichen, aber eindeutigen Texte verwendet. Für im Unterricht oder zum
            Lernen zu verwendenden Tabellen hat man aber vielleicht lieber
                "ています"
            als
                "höfliche Verlaufsform Gegenwart"
            über der Tabelle stehen.
            Daher kann man hier eigene Texte dafür vergeben.

            Die hier leer gelassenen Felder werden nicht überschrieben, sondern behalten die ori-
            ginalen, von mir vorgegebenen Inhalte.
            """;

    /** Die Optionen des Programms. */
    private final Options options;

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

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

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

    /** 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;

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

    /** Gibt an, ob beim Beenden alles ok ist. */
    private boolean ok;

    /** Die während apply() aufgetretenen Probleme. */
    private List<String> applyProblems;

    /**
     * Konstruktor.
     *
     * @param options
     *            Die Optionen des Programms.
     * @param parentLocation
     *            Die Location des aufrufenden Dialogs.
     * @param uiObjects
     *            Die häufig verwendeten Funktionen der grafischen Oberfläche des Vokabeltrainers.
     */
    public GrammarTableHeaderEditor(Options options, Point parentLocation,
            FumikoUiObjects uiObjects) {
        super(parentLocation, uiObjects.getProgramImage(),
                "Erzeugung grammatikalischer Tabllen von Verben oder Adjektiven");
        addEscapeBehaviour();

        this.options = options;

        verbGrammarFormAndStringSelections = new ArrayList<>();
        iAdjectiveGrammarFormAndStringSelections = new ArrayList<>();
        naAdjectiveGrammarFormAndStringSelections = new ArrayList<>();
        verbOrAdjectiveFormsTabs = new JTabbedPane();
        verbFormsTabPanel = new JPanel();
        iAdjectiveFormsTabPanel = new JPanel();
        naAdjectiveFormsTabPanel = new JPanel();
        explanationTabPanel = new JPanel();

        init();
        fillDialog();
    }

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

    private void initVerbFormCheckBoxes() {
        initGrammarFormAndStringSelections(SORTED_VERB_SEARCH_WORDS,
                verbGrammarFormAndStringSelections,
                options.getGrammarTableVerbHeadersMap());
    }

    private void initIAdjectiveFormCheckBoxes() {
        initGrammarFormAndStringSelections(SORTED_I_ADJEKTIVE_SEARCH_WORDS,
                iAdjectiveGrammarFormAndStringSelections,
                options.getGrammarTableIAdjectiveHeadersMap());
    }

    private void initNaAdjectiveFormCheckBoxes() {
        initGrammarFormAndStringSelections(SORTED_NA_ADJEKTIVE_SEARCH_WORDS,
                naAdjectiveGrammarFormAndStringSelections,
                options.getGrammarTableNaAdjectiveHeadersMap());
    }

    private static void initGrammarFormAndStringSelections(List<String> grammarForms,
            List<GrammarFormAndStringSelection> grammarFormAndStringSelections,
            Map<String, String> grammarTableIAdjectiveHeadersMap) {
        grammarFormAndStringSelections.clear();
        for (String grammarForm : grammarForms) {
            StringSelection stringSelection = new StringSelection(grammarForm);
            String text;
            if (grammarTableIAdjectiveHeadersMap.containsKey(grammarForm)) {
                text = grammarTableIAdjectiveHeadersMap.get(grammarForm);
            }
            else {
                text = "";
            }
            stringSelection.setText(text);
            GrammarFormAndStringSelection grammarFormAndStringSelection =
                    new GrammarFormAndStringSelection(grammarForm, stringSelection);
            grammarFormAndStringSelections.add(grammarFormAndStringSelection);
        }
    }

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

    private void initTabPanels() {
        initTabPane(verbFormsTabPanel, verbGrammarFormAndStringSelections);
        initTabPane(iAdjectiveFormsTabPanel, iAdjectiveGrammarFormAndStringSelections);
        initTabPane(naAdjectiveFormsTabPanel, naAdjectiveGrammarFormAndStringSelections);
        initExplanationTabPane();
    }

    private void initTabPane(JPanel formsTabPanel,
            List<GrammarFormAndStringSelection> grammarFormAndStringSelections) {
        List<JPanel> panels = new ArrayList<>();
        for (GrammarFormAndStringSelection formAndSelection : grammarFormAndStringSelections) {
            StringSelection selection = formAndSelection.getStringSelection();
            panels.add(selection.getPanel());
        }

        JPanel panel = new MultipleElementsPanel<JPanel>(panels, 3, 5);
        formsTabPanel.setLayout(new BorderLayout());
        formsTabPanel.add(panel, BorderLayout.CENTER);
        formsTabPanel.add(createDummyWidthPanel(), BorderLayout.SOUTH);
    }

    private Component createDummyWidthPanel() {
        JPanel panel = new JPanel();
        panel.setPreferredSize(new Dimension(1000, 0));
        return panel;
    }

    private void initExplanationTabPane() {
        explanationTabPanel.setLayout(new BorderLayout());

        explanationTabPanel.add(GuiTools.center(createExplanationPart()), BorderLayout.CENTER);
    }

    private Component createExplanationPart() {
        String text = HtmlTool.htmlify(EXPLANATION);
        JLabel label = new JLabel(text);
        label.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        GuiTools.biggerFont(label, 5);
        return label;
    }

    /** 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 BorderLayout());

        panel.add(verbOrAdjectiveFormsTabs);

        return panel;
    }

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

        panel.add(createQuitButton(), BorderLayout.WEST);
        panel.add(GuiTools.centerHorizontal(createMiddleButtons()), BorderLayout.CENTER);
        panel.add(createOkButton(), BorderLayout.EAST);

        return panel;
    }

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

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

        panel.add(createLoadButton());
        panel.add(createSaveButton());
        panel.add(createClearAllButton());

        return panel;
    }

    private Component createLoadButton() {
        JButton button = new JButton("laden");
        button.addActionListener(e -> load());
        return button;
    }

    private void load() {
        String loadFilename = GuiTools.openFile(getWindowAsComponent(),
                "Datei mit den eigenen Tabellenüberschriften auswählen",
                options.getGrammarTableLastUsedOwnHeadersDirectory(),
                GuiTools.createTextFileFilter());
        if (!loadFilename.isEmpty()) {
            if (FileHelper.isFile(loadFilename)) {
                loadExistingFile(loadFilename);
                String dir = FileHelper.getDirName(loadFilename);
                options.setGrammarTableLastUsedOwnHeadersDirectory(dir);
            }
            else {
                GuiTools.informUser("Datei nicht gefunden",
                        "Die Datei '" + loadFilename + "' wurde nicht gefunden.\n"
                                + "Das Laden wurde abgebrochen.");
            }
        }
    }

    private void loadExistingFile(String loadFilename) {
        GrammarTableOwnHeadersLoader loader = new GrammarTableOwnHeadersLoader(loadFilename);
        loader.load();
        Map<String, String> verbHeaderMap = loader.getVerbHeadersMap();
        Map<String, String> iAdjectiveHeaderMap = loader.getIAdjectiveHeadersMap();
        Map<String, String> naAdjectiveHeaderMap = loader.getNaAdjectiveHeadersMap();

        fillNewTexts(verbGrammarFormAndStringSelections, verbHeaderMap);
        fillNewTexts(iAdjectiveGrammarFormAndStringSelections, iAdjectiveHeaderMap);
        fillNewTexts(naAdjectiveGrammarFormAndStringSelections, naAdjectiveHeaderMap);
    }

    private void fillNewTexts(List<GrammarFormAndStringSelection> formAndSelections,
            Map<String, String> headerMap) {
        for (GrammarFormAndStringSelection formAndSelection : formAndSelections) {
            StringSelection selection = formAndSelection.getStringSelection();
            String title = selection.getTitle();
            if (headerMap.containsKey(title)) {
                String userHeader = headerMap.get(title);
                selection.setText(userHeader);
            }
            else {
                selection.setText("");
            }
        }
    }

    private Component createSaveButton() {
        JButton button = new JButton("speichern");
        button.addActionListener(e -> save());
        return button;
    }

    private void save() {
        String saveFilename = GuiTools.saveFileAsWithTitle(
                "Wohin soll Datei mit den eigenen Tabellenüberschriften gespeichert werden?",
                getWindowAsComponent(),
                options.getGrammarTableLastUsedOwnHeadersDirectory(),
                GuiTools.createTextFileFilter());
        if (!saveFilename.isBlank()) {
            boolean save = false;
            if (FileHelper.exists(saveFilename)) {
                save = GuiTools.askUser("Die Datei existiert bereits.", "Die Datei '"
                        + saveFilename + "' existiert bereits, soll sie überschriben werden?");
            }
            else {
                save = true;
            }
            if (save) {
                reallySaveList(saveFilename);
                String dir = FileHelper.getDirName(saveFilename);
                options.setGrammarTableLastUsedOwnHeadersDirectory(dir);
            }
        }
    }

    private void reallySaveList(String saveFilename) {
        GrammarTableOwnHeadersSaver saver = new GrammarTableOwnHeadersSaver(saveFilename,
                verbGrammarFormAndStringSelections,
                iAdjectiveGrammarFormAndStringSelections,
                naAdjectiveGrammarFormAndStringSelections);
        saver.save();
    }

    private Component createClearAllButton() {
        JButton button = new JButton("alle Felder leeren");
        button.addActionListener(e -> clearAll());
        return button;
    }

    private void clearAll() {
        clearAllFilds(verbGrammarFormAndStringSelections);
        clearAllFilds(iAdjectiveGrammarFormAndStringSelections);
        clearAllFilds(naAdjectiveGrammarFormAndStringSelections);
    }

    private void clearAllFilds(List<GrammarFormAndStringSelection> formAndSelections) {
        for (GrammarFormAndStringSelection formAndSelection : formAndSelections) {
            StringSelection selection = formAndSelection.getStringSelection();
            selection.setText("");
        }
    }

    private Component createOkButton() {
        JButton button = new JButton("Überschriften übernehmen");
        button.addActionListener(e -> apply());
        return button;
    }

    private void apply() {
        ok = true;
        applyProblems = new ArrayList<>();

        if (ok) storeVerbFormHeaders();
        if (ok) storeIAdjectiveFormHeaders();
        if (ok) storeNaAdjectiveFormHeaders();

        if (ok) {
            closeDialog();
        }
        else {
            GuiTools.informUser(getWindowAsComponent(),
                    "Die Überschriften können nicht gespeichert werden",
                    Text.join("\n\n", applyProblems));
        }
    }

    private void storeVerbFormHeaders() {
        storeFormHeaders(verbGrammarFormAndStringSelections,
                options.getGrammarTableVerbHeadersMap());
    }

    private void storeIAdjectiveFormHeaders() {
        storeFormHeaders(iAdjectiveGrammarFormAndStringSelections,
                options.getGrammarTableIAdjectiveHeadersMap());
    }

    private void storeNaAdjectiveFormHeaders() {
        storeFormHeaders(naAdjectiveGrammarFormAndStringSelections,
                options.getGrammarTableNaAdjectiveHeadersMap());
    }

    private void storeFormHeaders(List<GrammarFormAndStringSelection> formAndSelections,
            Map<String, String> grammarTableHeadersMap) {
        GrammarTableHeaderFieldsToMapCreator creator =
                new GrammarTableHeaderFieldsToMapCreator(formAndSelections, grammarTableHeadersMap);
        creator.create();
        if (!creator.isSuccess()) {
            ok = false;
            applyProblems.addAll(creator.getProblems());
        }
    }

}
