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

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;

import javax.swing.Action;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.JScrollPane;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;

import de.duehl.swing.logic.LongTimeProcessInformer;
import de.duehl.swing.logic.Quitter;
import de.duehl.swing.ui.GuiTools;
import de.duehl.swing.ui.components.selections.StringSelection;
import de.duehl.swing.ui.components.selections.tools.SelectionsHelper;
import de.duehl.swing.ui.dialogs.base.additional.LocationGetter;
import de.duehl.swing.ui.key.BindKeysOnRootPane;
import de.duehl.swing.ui.layout.VerticalLayout;
import de.duehl.vocabulary.japanese.common.data.InternalAdditionalKanjiData;
import de.duehl.vocabulary.japanese.data.FumikoDataStructures;
import de.duehl.vocabulary.japanese.data.symbol.Kanji;
import de.duehl.vocabulary.japanese.logic.symbol.kanji.internal.InternalKanjiDataRequester;
import de.duehl.vocabulary.japanese.ui.data.FumikoUiObjects;
import de.duehl.vocabulary.japanese.ui.dialog.kanji.display.KanjiPanel;
import de.duehl.vocabulary.japanese.ui.dialog.kanji.display.KanjiGermanMeaningAndLesungenPanel;
import de.duehl.vocabulary.japanese.ui.dialog.kanji.display.findlists.SetsWithKanjiFinder;
import de.duehl.vocabulary.japanese.ui.dialog.kanji.stroke.KanjiStrokesUiTools;
import de.duehl.vocabulary.japanese.ui.dialog.kanji.table.components.AllVocablesWithKanjiShower;

/**
 * Diese Klasse zeigt die Details eines Kanji inklusive der internen Daten des Benutzers auf einem
 * Panel an.
 *
 * @version 1.01     2026-08-28
 * @author Christian Dühl
 */

public class KanjiDetailPanel {

    private static final int WANTED_WIDTH = 700;
    private static final int WANTED_KANJI_AND_INTERNAL_HEIGHT = 900;


    /** Das angezeigte Kanji-Zeichen. */
    private final Kanji kanji;

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

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

    /** Die Oberfläche, welche diese Klasse aufruft, auf der man eine GlassPane anzeigen kann. */
    private final LongTimeProcessInformer informer;

    /** Das Objekt, das die aktuelle Position der Oberfläche zurück geben kann. */
    private LocationGetter locationGetter;

    /** Wird aufgerufen wenn der Beenden-Button betätigt wird. */
    private final Quitter quitter;

    /** Der Panel auf dem das Kanji mit den Details dargestellt wird. */
    private final JPanel panel;

    /** Erzeugt die Komponente, die das Kanji groß dargestellt. */
    private final KanjiPanel kanjiPanel;

    /** Stellt das Kanji auch als Zeichen zum Rauskopieren dar. */
    private final StringSelection kanjiAsCharacterSeletion;

    /** Stellt die deutschen Bedeutungen und die Lesungen des Kanji dar. */
    private final KanjiGermanMeaningAndLesungenPanel kanjiGermanMeaningAnLesungenPanel;

    private final StringSelection numberInKanjiAndKanaBookSelection;
    private final StringSelection pageNumberInKanjiAndKanaBookSelection;
    private final StringSelection numberInMyHandwrittenKanjiNotebooksSelection;

    private final StringSelection firstSeenDateSelection;
    private final StringSelection testCountSelection;
    private final StringSelection correctTestCountSelection;
    private final StringSelection lastTestDatetSelection;
    private final StringSelection lastCorrectTestDateSelection;
    private final StringSelection lastTenTestResultsSelection;

    private final JButton showAllVocableWithKanjiButton;
    private final JButton showAllKanjiSetsWithKanjiButton;
    private final JButton showKanjiStrokesButton;

    /**
     * Das Objekt, welches zu einem Kanji alle Kanji-Mengen findet, in denen dieses Kanji vorkommt.
     */
    private SetsWithKanjiFinder setsWithKanjiFinder;

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

    /**
     * Konstruktor.
     *
     * @param kanji
     *            Das anzuzeigende Kanji.
     * @param dataStructures
     *            Die Datenstrukturen des Vokabeltrainers.
     * @param uiObjects
     *            Die häufig verwendeten Funktionen der grafischen Oberfläche des Vokabeltrainers.
     * @param informer
     *            Die Oberfläche, welche diese Klasse aufruft, auf der man eine GlassPane anzeigen
     *            kann.
     * @param thisPanelUsingDialog
     *            Der modale oder nicht modale Dialog bzw., Frame, der diesen Panel nutzt.
     * @param locationGetter
     *            Das Objekt, das die aktuelle Position der Oberfläche zurück geben kann.
     * @param quitter
     *            Wird aufgerufen wenn der Beenden-Button betätigt wird.
     */
    public KanjiDetailPanel(Kanji kanji, FumikoDataStructures dataStructures,
            FumikoUiObjects uiObjects, LongTimeProcessInformer informer,
            Component thisPanelUsingDialog, LocationGetter locationGetter, Quitter quitter) {
        this.kanji = kanji;
        this.dataStructures = dataStructures;
        this.uiObjects = uiObjects;
        this.informer = informer;
        this.locationGetter = locationGetter;
        this.quitter = quitter;

        panel = new JPanel();

        kanjiPanel = new KanjiPanel();
        kanjiPanel.setBiggerFontSize(200); // Default: 400
        kanjiPanel.showKanji(kanji);

        kanjiGermanMeaningAnLesungenPanel = new KanjiGermanMeaningAndLesungenPanel(kanji);
        kanjiAsCharacterSeletion = new StringSelection("Das Kanji (noch einmal zum rauskopieren)");
        kanjiAsCharacterSeletion.setText(kanji.getCharacter());

        numberInKanjiAndKanaBookSelection = new StringSelection(
                "Nummer im Buch 'Kanji und Kana' von Wolfgang Hadamitzky");
        pageNumberInKanjiAndKanaBookSelection = new StringSelection(
                "Seite im Buch 'Kanji und Kana' von Wolfgang Hadamitzky");
        numberInMyHandwrittenKanjiNotebooksSelection = new StringSelection(
                "Nummer in meinen handschriftlichen Heften");

        firstSeenDateSelection = new StringSelection("Zuerst gesehen");
        testCountSelection = new StringSelection("Anzahl Test");
        correctTestCountSelection = new StringSelection("Anzahl erfolgreicher Test");
        lastTestDatetSelection = new StringSelection("zuletzt getestet am");
        lastCorrectTestDateSelection = new StringSelection("zuletzt erfolgreich getestet am");
        lastTenTestResultsSelection = new StringSelection("Erfolg der letzten Tests");

        setsWithKanjiFinder = new SetsWithKanjiFinder(dataStructures, thisPanelUsingDialog);
        showAllVocableWithKanjiButton = new JButton("Zeige alle Vokabeln mit diesem Kanji an");
        showAllKanjiSetsWithKanjiButton = new JButton(
                "Zeige alle Kanji-Mengen mit diesem Kanji an");
        showKanjiStrokesButton = new JButton("Zeige die Strichfolge dieses Kanji an");


        okButton = new JButton("Beenden");

        init();
        showKanjiInterna();
        populatePanel();
    }

    private void init() {
        initPanel();
        initOkButton();
        initSelections();
        initKanjiButtons();
    }

    private void initPanel() {
        panel.setLayout(new BorderLayout());
    }

    private void initOkButton() {
        okButton.addActionListener(e -> quitter.quit());
    }

    private void initSelections() {
        SelectionsHelper.initSelectionAsFocusableViewer(kanjiAsCharacterSeletion);

        SelectionsHelper.initSelectionAsFocusableViewer(numberInKanjiAndKanaBookSelection);
        SelectionsHelper.initSelectionAsFocusableViewer(pageNumberInKanjiAndKanaBookSelection);
        SelectionsHelper.initSelectionAsFocusableViewer(numberInMyHandwrittenKanjiNotebooksSelection);

        SelectionsHelper.initSelectionAsFocusableViewer(firstSeenDateSelection);
        SelectionsHelper.initSelectionAsFocusableViewer(testCountSelection);
        SelectionsHelper.initSelectionAsFocusableViewer(correctTestCountSelection);
        SelectionsHelper.initSelectionAsFocusableViewer(lastTestDatetSelection);
        SelectionsHelper.initSelectionAsFocusableViewer(lastCorrectTestDateSelection);
        SelectionsHelper.initSelectionAsFocusableViewer(lastTenTestResultsSelection);
    }

    private void initKanjiButtons() {
        showAllVocableWithKanjiButton.addActionListener(e -> showAllVocablesWithKanji());
        showAllKanjiSetsWithKanjiButton.addActionListener(e -> showAllKanjiSetsWithKanji());
        showKanjiStrokesButton.addActionListener(e -> showKanjiStrokes());
    }

    private void showAllVocablesWithKanji() {
        AllVocablesWithKanjiShower vocablesShower = new AllVocablesWithKanjiShower(
                dataStructures, uiObjects, locationGetter.getLocation(), informer);
        vocablesShower.showKanji(kanji);
    }

    private void showAllKanjiSetsWithKanji() {
        setsWithKanjiFinder.findKanjiSetsWithKanji(kanji);
    }

    private void showKanjiStrokes() {
        KanjiStrokesUiTools.showKanjiStrokes(kanji.getCharacter(), dataStructures.getKanjiStrokes(),
                panel, locationGetter.getLocation(), uiObjects.getProgramImage());
    }

    private void showKanjiInterna() {
        numberInKanjiAndKanaBookSelection.setText(kanji.getNumberInKanjiAndKanaBook());
        pageNumberInKanjiAndKanaBookSelection.setText(kanji.getPageNumberInKanjiAndKanaBook());
        numberInMyHandwrittenKanjiNotebooksSelection.setText(
                kanji.getNumberInMyHandwrittenKanjiNotebooks());

        InternalKanjiDataRequester kanjiRequester =
                dataStructures.getInternalKanjiDataRequester();
        InternalAdditionalKanjiData data = kanjiRequester.getInternalDataForKanji(kanji);

        firstSeenDateSelection.setText(data.getFirstSeenDate().toString());
        testCountSelection.setText(data.getTestCount());
        correctTestCountSelection.setText(data.getCorrectTestCount());
        lastTestDatetSelection.setText(data.getLastTestDate().toString());
        lastCorrectTestDateSelection.setText(data.getLastCorrectTestDate().toString());
        lastTenTestResultsSelection.setText(data.getLastTenTestResultsAsStorageString());
    }

    private void populatePanel() {
        panel.add(createCenterPart(), BorderLayout.CENTER);
        panel.add(createButtonsPart(),  BorderLayout.SOUTH);

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

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

        panel.add(createKanjiWithDetailsPartScroll());
        panel.add(createKanjiButtonsPart());

        return panel;
    }

    private Component createKanjiWithDetailsPartScroll() {
        JScrollPane scrollPane = GuiTools.createScrollPane(createKanjiWithDetailsPart());
        scrollPane.setPreferredSize(new Dimension(WANTED_WIDTH, WANTED_KANJI_AND_INTERNAL_HEIGHT));
        return scrollPane;
    }

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

        panel.add(kanjiPanel.getPanel());
        panel.add(kanjiAsCharacterSeletion.getPanel());
        panel.add(kanjiGermanMeaningAnLesungenPanel.getPanel());
        panel.add(createInternalKanjiDataPart());

        return panel;
    }

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

        panel.add(numberInKanjiAndKanaBookSelection.getPanel());
        panel.add(pageNumberInKanjiAndKanaBookSelection.getPanel());
        if (dataStructures.getOptions().isShowKanjiNumberInMyHandwrittenKanjiNotebooks()) {
            panel.add(numberInMyHandwrittenKanjiNotebooksSelection.getPanel());
        }

        panel.add(firstSeenDateSelection.getPanel());
        panel.add(testCountSelection.getPanel());
        panel.add(correctTestCountSelection.getPanel());
        panel.add(lastTestDatetSelection.getPanel());
        panel.add(lastCorrectTestDateSelection.getPanel());
        panel.add(lastTenTestResultsSelection.getPanel());

        return panel;
    }

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

        panel.add(showAllVocableWithKanjiButton);
        panel.add(showAllKanjiSetsWithKanjiButton);
        panel.add(showKanjiStrokesButton);

        return panel;
    }

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

        panel.add(okButton, BorderLayout.EAST);

        return panel;
    }

    /** Getter für den Panel auf dem das Kanji mit den Details dargestellt wird. */
    public JPanel getPanel() {
        return panel;
    }

    /**
     * Legt die Tastenbelegung zum Öffnen der Strichdarstellung fest.
     *
     * Dies geht erst, wenn der Panel in einem JFrame oder JDialog eingebettet wurde.
     */
    public void keybindingsForStrokesDialog() {
        KeyStroke keyStrokeS = KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK);
        String actionMapKeyS = "Strg-S";
        Action actionS = BindKeysOnRootPane.runnableToAction(() -> showKanjiStrokes());

        JRootPane rootPane = panel.getRootPane();
        InputMap inputMap = rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
        inputMap.put(keyStrokeS, actionMapKeyS);
        rootPane.getActionMap().put(actionMapKeyS, actionS);
    }

}
