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

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 javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import de.duehl.basics.io.FileHelper;
import de.duehl.swing.ui.GuiTools;
import de.duehl.swing.ui.dialogs.base.NonModalFrameDialogBase;
import de.duehl.swing.ui.layout.VerticalLayout;
import de.duehl.vocabulary.japanese.data.FumikoDataStructures;
import de.duehl.vocabulary.japanese.data.KanjiSet;
import de.duehl.vocabulary.japanese.logic.VocabularyTrainerLogic;
import de.duehl.vocabulary.japanese.ui.components.bars.KanjiSetBar;
import de.duehl.vocabulary.japanese.ui.data.FumikoUiObjects;
import de.duehl.vocabulary.japanese.ui.dialog.kanji.kanjiset.check.KanjiSetIntegrityChecker;

/**
 * Diese Klasse lässt den Benutzer die Kanji-Mengen verwalten (neue anlegen, Listen bearbeiten,
 * Listen löschen).
 *
 * @version 1.01     2026-07-16
 * @author Christian Dühl
 */

public class KanjiSetManagementDialog extends NonModalFrameDialogBase
        implements KanjiSetBarsRefresher {

    /** Die Größe des Dialogs. */
    private static final Dimension DIALOG_DIMENSION = new Dimension(1550, 800);

    /** Die Anzahl der Spalten, in denen die Kanji-Mengen dargestellt werden. */
    private static final int NUMBER_OF_COLUMNS = 3;


    /** Die Logik des Vokabeltrainers. */
    private final VocabularyTrainerLogic logic;

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

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

    /** Die Liste der benutzerdefinierten Kanji-Mengen. */
    private final List<KanjiSet> kanjiSets;

    /** Die Menge der dargestellten Bars mit je einer Kanji-Menge. */
    private final List<KanjiSetBar> bars;

    /** Das Panel auf dem die Spalten mit Bars mit je einer Kanji-Menge dargestellt werden. */
    private final JPanel barsPanel;

    /** Das Panel auf dem die Bars mit je einer Kanji-Menge dargestellt werden. */
    private final List<JPanel> singleBarsPanels;

    /** Der Button zum Beenden des Dialogs. */
    private final JButton okButton;

    /**
     * Konstruktor.
     *
     * @param logic
     *            Die Logik des Vokabeltrainers.
     * @param dataStructures
     *            Die Datenstrukturen des Vokabeltrainers.
     * @param uiObjects
     *            Die häufig verwendeten Funktionen der grafischen Oberfläche des Vokabeltrainers.
     * @param kanjiSets
     *            Die Liste der benutzerdefinierten Kanji-Mengen.
     * @param parentLocation
     *            Position des Rahmens der Oberfläche, vor der dieser Dialog erzeugt wird.
     */
    public KanjiSetManagementDialog(VocabularyTrainerLogic logic,
            FumikoDataStructures dataStructures, FumikoUiObjects uiObjects, Point parentLocation) {
        super(parentLocation, uiObjects.getProgramImage(), "Verwaltung der Kanji-Mengen",
                DIALOG_DIMENSION);
        addClosingWindowListener(() -> quit());
        addEscapeBehaviour();

        this.logic = logic;
        this.dataStructures = dataStructures;
        this.uiObjects = uiObjects;

        kanjiSets = dataStructures.getKanjiSets();

        bars = new ArrayList<>();
        barsPanel = new JPanel();
        singleBarsPanels = new ArrayList<>();

        okButton = new JButton();

        init();
        createAndShowBars();
        fillDialog();
    }

    private void init() {
        initBarsPanel();
    }

    private void initBarsPanel() {
        barsPanel.setLayout(new GridLayout(0, 3, 2, 2));

        for (int index = 0; index < NUMBER_OF_COLUMNS; ++index) {
            JPanel singleBarsPanel = new JPanel();
            singleBarsPanel.setLayout(new VerticalLayout(0, VerticalLayout.BOTH));
            singleBarsPanels.add(singleBarsPanel);
            barsPanel.add(singleBarsPanel);
        }
    }

    private void createAndShowBars() {
        bars.clear();
        for (int index = 0; index < NUMBER_OF_COLUMNS; ++index) {
            JPanel singleBarsPanel = singleBarsPanels.get(index);
            singleBarsPanel.removeAll();
        }

        List<String> allNames = new ArrayList<>();
        for (KanjiSet kanjiSet : kanjiSets) {
            allNames.add(kanjiSet.getName());
        }

        double barsInColDouble = (kanjiSets.size() * 1.0D) / NUMBER_OF_COLUMNS;
        int barsInCol = (int) Math.ceil(barsInColDouble);

        int count = 0;
        for (KanjiSet kanjiSet : kanjiSets) {
            KanjiSetBar bar = new KanjiSetBar(kanjiSet, allNames, (KanjiSetBarsRefresher) this,
                    logic, dataStructures, uiObjects, () -> getLocation());
            bars.add(bar);
            int index = count / barsInCol;
            JPanel singleBarsPanel = singleBarsPanels.get(index);
            singleBarsPanel.add(bar.getPanel());
            ++count;
        }

        /*
        for (int index = 0; index < NUMBER_OF_COLUMNS; ++index) {
            JPanel singleBarsPanel = singleBarsPanels.get(index);
            singleBarsPanel.invalidate();
            singleBarsPanel.validate();
            singleBarsPanel.repaint();
        }

         */
        barsPanel.invalidate();
        barsPanel.validate();
        barsPanel.repaint();
        pack();
    }

    /** Baut die Gui auf. */
    @Override
    protected void populateDialog() {
        add(createUpperButtonPart(), BorderLayout.NORTH);
        add(GuiTools.createScrollPane(barsPanel), BorderLayout.CENTER);
        add(createButtonsPart(), BorderLayout.SOUTH);

        SwingUtilities.invokeLater(() -> okButton.requestFocus());
    }

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

        panel.add(createNewKanjiSetButton(), BorderLayout.WEST);
        panel.add(createCheckKanjiSetIntegrityButton(), BorderLayout.EAST);

        return panel;
    }

    private Component createNewKanjiSetButton() {
        JButton button = new JButton("Neue Kanji-Menge hinzufügen");
        button.addActionListener(e -> addNewKanjiList());
        return button;
    }

    private void addNewKanjiList() {
        List<String> notAllowedNames = new ArrayList<>();
        for (KanjiSet kanjiSet : kanjiSets) {
            notAllowedNames.add(kanjiSet.getName());
        }

        String title = "Den Namen der neuen Kanji-Menge eingeben";
        String message = "Bitte den Namen der neuen Kanji-Menge eingeben.";
        String name = GuiTools.askUserToEnterAStringValue(getWindowAsComponent(), title, message);
        if (name.isBlank()) {
            return;
        }

        if (notAllowedNames.contains(name)) {
            title = "Der Name ist bereits vergeben";
            message = "Den Name '" + name + "' ist bereits vergeben.";
            GuiTools.informUser(getWindowAsComponent(), title, message);
            return;
        }

        KanjiSet kanjiSet = new KanjiSet(name);
        kanjiSets.add(kanjiSet);
        KanjiSet.sort(kanjiSets);
        createAndShowBars();
    }

    private Component createCheckKanjiSetIntegrityButton() {
        JButton button = new JButton("Kanji-Mengen Integrität überprüfen");
        button.addActionListener(e -> checkKanjiSetIntegrity());
        return button;
    }

    private void checkKanjiSetIntegrity() {
        KanjiSetIntegrityChecker.checkKanjiSetsIntegrityWithSuccessInfo(kanjiSets,
                getWindowAsComponent(), getLocation());
    }

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

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

        return panel;
    }

    private Component createQuitButton() {
        okButton.setText("Beenden");
        okButton.addActionListener(e -> quit());
        return okButton;
    }

    private void quit() {
        saveKanjiLists();
        closeDialog();
    }

    /** Speichert die Kanji-Mengen ab. */
    private void saveKanjiLists() {
        logic.saveKanjiSets();
    }

    /** Löscht die übergebene Kanji-Menge aus der Liste der Kanji-Mengen. */
    @Override
    public void deleteKanjiSetFromListAndFileFromDisk(KanjiSet kanjiSet) {
        kanjiSets.remove(kanjiSet);
        String filename = kanjiSet.determineFilename();
        if (FileHelper.isFile(filename)) { // gibt es nicht, wenn man sie gerade erst angelegt hat
            FileHelper.deleteFile(filename);
        }
    }

    /** Stellt die Bars mit den Kanji-Mengen neu dar. */
    @Override
    public void refreshKanjiSetBars() {
        createAndShowBars();
    }

}
