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

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

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

import de.duehl.swing.ui.GuiTools;
import de.duehl.swing.ui.dialogs.base.ModalDialogBase;
import de.duehl.swing.ui.layout.VerticalLayout;
import de.duehl.vocabulary.japanese.data.Vocable;
import de.duehl.vocabulary.japanese.ui.data.FumikoUiObjects;
import de.duehl.vocabulary.japanese.ui.dialog.grammar.subdialogs.data.BaseFormAndCheckBox;

/**
 * Diese Klasse erzeugt die grafische Oberfläche des Dialoges zur Auswahl der ermittelten
 * Grundformen von den Verben oder Adjektiven bei der Erstellung von grammatikalischen Tabellen von
 * Verben bzw. Adjektiven.
 *
 * @version 1.01     2025-11-27
 * @author Christian Dühl
 */

public class GrammarTableBaseFormUserSelectionDialog extends ModalDialogBase {

    private static final Dimension DIALOG_DIMENSION = new Dimension(800, 600);

    private static final int VERTICAL_SPACE_BETWEEN_FORMS = 3;


    /**
     * Die anzuzeigenden Vokabeln in ihrer Wörterbuch-/Grundform.
     *
     * Diese werden hier bearbeitet.
     */
    private final List<Vocable> baseFormVocables;

    /** Die Grundformen der Verben oder Adjektive zusammen mit den zugehörigen CheckBoxen. */
    private final List<BaseFormAndCheckBox> baseFormsAndCheckBoxes;

    /** 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 GrammarTableBaseFormUserSelectionDialog(List<Vocable> baseFormVocables,
            FumikoUiObjects uiObjects) {
        super(uiObjects.getGuiLocation(), uiObjects.getProgramImage(),
                "Auswahl der Grundformen für die Tabelle", DIALOG_DIMENSION);

        this.baseFormVocables = baseFormVocables;

        baseFormsAndCheckBoxes = new ArrayList<>();

        init();
        fillDialog();
    }

    private void init() {
        fillBaseFormsAndCheckBoxes();
        initValues();
    }

    private void fillBaseFormsAndCheckBoxes() {
        for (Vocable baseFormVocable : baseFormVocables) {
            fillBaseFormAndCheckBox(baseFormVocable);
        }
    }

    private void fillBaseFormAndCheckBox(Vocable baseFormVocable) {
        String text = baseFormVocable.getKanjiKanaRomajiWithJapaneseBraces();
        JCheckBox checkBox = new JCheckBox(text);
        checkBox.setSelected(true);
        GuiTools.biggerFont(checkBox, 10);
        checkBox.setBorder(BorderFactory.createEmptyBorder(0, 15, 0, 15));
        BaseFormAndCheckBox baseFormAndCheckBox = new BaseFormAndCheckBox(baseFormVocable, checkBox);
        baseFormsAndCheckBoxes.add(baseFormAndCheckBox);
    }

    private void initValues() {
        applied = false;
    }

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

        pack();
    }

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

        for (BaseFormAndCheckBox baseFormAndCheckBox : baseFormsAndCheckBoxes) {

            panel.add(createPanelForCheckBox(baseFormAndCheckBox.getCheckBox()));
        }

        return panel;
    }

    private Component createPanelForCheckBox(JCheckBox checkBox) {
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        GuiTools.createTitle(panel);

        panel.add(checkBox, BorderLayout.CENTER);

        return panel;
    }

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

        panel.add(createQuitButton(), BorderLayout.WEST);
        panel.add(GuiTools.centerHorizontal(createSelectionsButtonsPart()), 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 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) {
        for (BaseFormAndCheckBox baseFormAndCheckBox : baseFormsAndCheckBoxes) {
            JCheckBox checkBox = baseFormAndCheckBox.getCheckBox();
            checkBox.setSelected(select);
        }
    }

    private Component createOkButton() {
        JButton button = new JButton("Auswahl bestätigen");
        button.addActionListener(e -> apply());
        return button;
    }

    private void apply() {
        baseFormVocables.clear();
        for (BaseFormAndCheckBox baseFormAndCheckBox : baseFormsAndCheckBoxes) {
            JCheckBox checkBox = baseFormAndCheckBox.getCheckBox();
            if (checkBox.isSelected()) {
                Vocable baseFormVocable = baseFormAndCheckBox.getBaseFormVocable();
                baseFormVocables.add(baseFormVocable);
            }
        }

        applied = true;
        closeDialog();
    }

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

}
