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

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import de.duehl.basics.io.FileHelper;
import de.duehl.basics.text.Text;
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;

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

public class KanjiSetManagementDialog extends NonModalFrameDialogBase
        implements KanjiSetBarsRefresher {

    private static final int MIN_WIDTH = 500;


    /** 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 Bars mit je einer Kanji-Menge dargestellt werden. */
    private final JPanel barsPanel;

    /** Der Button zum Anlegen einer neuen Kanji-Menge. */
    private final JButton newKanjiSetButton;

    /** 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");
        addClosingWindowListener(() -> quit());
        addEscapeBehaviour();

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

        kanjiSets = dataStructures.getKanjiSets();

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

        newKanjiSetButton = new JButton("Neue Kanji-Menge hinzufügen");
        okButton = new JButton();

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

    private void init() {
        initBarsPanel();
        initNewKanjiSetButton();
    }

    private void initBarsPanel() {
        barsPanel.setLayout(new VerticalLayout(0, VerticalLayout.BOTH));
    }

    private void initNewKanjiSetButton() {
        newKanjiSetButton.addActionListener(e -> addNewKanjiList());
    }

    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);
        createAndShowBars();
    }

    private void createAndShowBars() {
        bars.clear();
        barsPanel.removeAll();

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

        for (KanjiSet kanjiSet : kanjiSets) {
            KanjiSetBar bar = new KanjiSetBar(kanjiSet, allNames, (KanjiSetBarsRefresher) this,
                    logic, dataStructures, uiObjects, () -> getLocation());
            bars.add(bar);
            barsPanel.add(bar.getPanel());
        }

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

    private void sortKanjiSets() {
        Collections.sort(kanjiSets, new Comparator<KanjiSet>() {
            @Override
            public int compare(KanjiSet set1, KanjiSet set2) {
                String group1 = set1.getGroup();
                String group2 = set2.getGroup();
                int cmp = Text.compareStringsBetter(group1, group2);
                if (cmp == 0) {
                    String name1 = set1.getName();
                    String name2 = set2.getName();
                    cmp = Text.compareStringsBetter(name1, name2);
                }
                return cmp;
            }
        });
    }

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

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

    private Component createHeaderPart() {
        JPanel panel = new JPanel();
        panel.setLayout(new VerticalLayout(0, VerticalLayout.BOTH));

        panel.add(createDummyMinWidthLabelPart());
        panel.add(createUpperButtonPart());

        return panel;
    }

    private Component createDummyMinWidthLabelPart() {
        JLabel label = new JLabel("");
        label.setPreferredSize(new Dimension(MIN_WIDTH, 0));
        return label;
    }

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

        panel.add(newKanjiSetButton, BorderLayout.WEST);

        return panel;
    }

    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();
    }

}
