package de.duehl.vocabulary.japanese.ui.dialog.kana.hiraganatest;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;

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

import de.duehl.swing.ui.GuiTools;
import de.duehl.swing.ui.components.selections.StringSelection;
import de.duehl.swing.ui.components.selections.TextAreaSelection;
import de.duehl.swing.ui.components.selections.tools.SelectionsHelper;
import de.duehl.swing.ui.dialogs.base.ModalDialogBase;
import de.duehl.swing.ui.key.BindKeysOnRootPane;
import de.duehl.swing.ui.layout.VerticalLayout;
import de.duehl.vocabulary.japanese.common.color.VocableColors;
import de.duehl.vocabulary.japanese.common.persistence.Options;
import de.duehl.vocabulary.japanese.data.symbol.Hiragana;
import de.duehl.vocabulary.japanese.logic.symbol.kana.test.data.SingleUserInputHiraganaCheckResult;
import de.duehl.vocabulary.japanese.ui.dialog.kana.hiraganatest.components.HiraganaPanel;

/**
 * Diese Klasse zeigt den Erfolg oder Misserfolg nach dem Abfragen eines Hiragana an.
 *
 * @version 1.01     2025-02-02
 * @author Christian Dühl
 */

public class HiraganaTestEvaluationDialog extends ModalDialogBase {

    /** Minimale Breite des Fensters, ansonsten passt es sich an den Inhalt an. */
    private static final int MIN_WIDTH = 700;


    /** Das Ergebnis der Prüfung. */
    private final SingleUserInputHiraganaCheckResult result;

    /** Das Hiragana welches abgefragt wurde. */
    private final Hiragana hiragana;

    /** Gibt an, ob die Übersetzung korrekt war. */
    private final boolean correct;

    /** Die anzuzeigende Nachricht. */
    private final String message;

    /** Die Hintergrundfarbe. */
    private final Color backgroundColor;

    /** Das UI-Komponente, auf der die Daten des Hiragana dargestellt werden. */
    private final HiraganaPanel hiraganaPanel;

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

    /** Gibt an, ob im Fall einer falsch beantworteten Vokabel nur ein Tippfehler vorlag. */
    private boolean onlyTypingError;

    private final StringSelection userInputHepburnSelection;

    private final TextAreaSelection errorMessageSelection;

    private boolean errorFilled;

    /**
     * Konstruktor.
     *
     * @param result
     *            Das Ergebnis der Bewertung der Benutzereingaben inklusive Hiragana, welches
     *            abgefragt wurde.
     * @param userInputGermanMeaning
     *            Die vom Benutzer eingegebene deutsche Bedeutung.
     * @param userInputOnLesung
     *            Die vom Benutzer eingebenen ON-Lesungen.
     * @param userInputKunLesung
     *            Die vom Benutzer eingebenen kun-Lesungen.
     * @param correct
     *            Gibt an, ob die Abfrage korrekt war.
     * @param options
     *            Die Programmoptionen.
     * @param parentLocation
     *            Position des Rahmens der Oberfläche, vor der dieser Dialog erzeugt wird.
     * @param programImage
     *            Anzuzeigendes ProgrammIcon.
     */
    public HiraganaTestEvaluationDialog(SingleUserInputHiraganaCheckResult result,
            String userInputHepburn, Options options, Point parentLocation, Image programImage) {
        super(parentLocation, programImage, result.isOk() ? "Richtig!" : "Leider falsch");
        addEscapeBehaviour();

        this.result = result;
        this.hiragana = result.getHiragana();
        this.correct = result.isOk();

        onlyTypingError = false;

        message = correct ? "Richtig beantwortet, sehr gut!" : "Das war leider nicht richtig";

        VocableColors vocableColors = new VocableColors(options);
        backgroundColor = correct
                ? vocableColors.getSuccessColor()
                : vocableColors.getFailureColor();

        quitButton = new JButton("Beenden");

        hiraganaPanel = new HiraganaPanel();
        userInputHepburnSelection = new StringSelection("Eingebene Hepburn-Darstellung");
        errorMessageSelection = new TextAreaSelection("Fehlermeldungen");

        init(userInputHepburn);
        fillDialog();
    }

    private void init(String userInputHepburn) {
        initHiraganaPanel();
        fillHiraganaPanel();

        initUserInputTextSelectionms();
        fillUserInputTextSelections(userInputHepburn);

        initResultTextSelections();
        fillResultTextSelections();

        initQuitButton();
    }

    private void initHiraganaPanel() {
        hiraganaPanel.createGui();
    }

    private void fillHiraganaPanel() {
        hiraganaPanel.showHiragana(hiragana);
    }

    private void initUserInputTextSelectionms() {
        SelectionsHelper.initSelectionAsViewer(userInputHepburnSelection);
    }

    private void fillUserInputTextSelections(String userInputHepburn) {
        userInputHepburnSelection.setText(userInputHepburn);
    }

    private void initResultTextSelections() {
        SelectionsHelper.initSelectionAsViewer(errorMessageSelection);
    }

    private void fillResultTextSelections() {
        String errorDescription = result.getErrorDescription();

        errorMessageSelection.setText(errorDescription);

        errorFilled = !errorDescription.isBlank();
    }

    private void initQuitButton() {
        GuiTools.addReturnListener(quitButton, () -> quitButton.doClick());
    }

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

        if (!correct) {
            keybindingsForOnlyTypingError();
        }

        SwingUtilities.invokeLater(() -> quitButton.requestFocus());
        pack();
    }

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

        panel.add(createMessagePart());
        panel.add(createHiraganaDataPart());
        panel.add(createUserDataPart());
        if (errorFilled) {
            panel.add(createErrorMesagePart());
        }

        if (!correct) {
            panel.add(createOnlyTypingErrorLabel());
        }

        return GuiTools.createScrollPane(panel);
    }

    private Component createMessagePart() {
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        GuiTools.createTitle(panel);

        panel.add(createMessageLabel(), BorderLayout.CENTER);

        return panel;
    }

    private Component createMessageLabel() {
        JLabel label = new JLabel(message);
        label.setHorizontalAlignment(JLabel.CENTER);
        label.setPreferredSize(new Dimension(MIN_WIDTH, 30));

        GuiTools.biggerFont(label, 7);
        label.setOpaque(true);
        label.setBackground(backgroundColor);
        return label;
    }

    private Component createHiraganaDataPart() {
        JPanel panel = new JPanel();
        panel.setLayout(new VerticalLayout(0, VerticalLayout.BOTH));
        GuiTools.createBlueTitle("Daten zum abgefragten Hiragana:", panel);

        panel.add(hiraganaPanel.getPanel());

        return panel;
    }

    private Component createUserDataPart() {
        JPanel panel = new JPanel();
        panel.setLayout(new VerticalLayout(0, VerticalLayout.BOTH));
        GuiTools.createBlueTitle("Vom Benutzer eingegebene Daten:", panel);

        panel.add(userInputHepburnSelection.getPanel());

        return panel;
    }

    private Component createErrorMesagePart() {
        JPanel panel = new JPanel();
        panel.setLayout(new VerticalLayout(0, VerticalLayout.BOTH));
        GuiTools.createBlueTitle("Fehler und Hinweise:", panel);

        if (errorFilled) {
            panel.add(errorMessageSelection.getPanel());
        }

        return panel;
    }

    private Component createOnlyTypingErrorLabel() {
        JLabel label = new JLabel("War es nur ein Tippfehler? Dann Strg-Shift-K drücken.");
        label.setBorder(BorderFactory.createEmptyBorder(0,  5,  0,  5));
        return label;
    }

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

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

        return panel;
    }

    private Component createQuitButton() {
        quitButton.addActionListener(e -> closeDialog());
        quitButton.setBackground(backgroundColor);
        return quitButton;
    }

    private void keybindingsForOnlyTypingError() {
        KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_K,
                InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK);
        String actionMapKey = "Strg-Shift-K";
        Action action = BindKeysOnRootPane.runnableToAction(() -> setToOnlyTypingError());

        JRootPane rootPane = getRootPane();
        InputMap inputMap = rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
        inputMap.put(keyStroke, actionMapKey);
        rootPane.getActionMap().put(actionMapKey, action);
    }

    private void setToOnlyTypingError() {
        String title = "War es nur ein Tippfehler?";
        String userMessage = "War die falsche Eingabe wirklich nur ein Tippfehler?\n"
                + "Bitte gewissenhaft antworten und sich nicht selbst belügen.";
        onlyTypingError = GuiTools.askUser(getWindowAsComponent(), title, userMessage);
        if (onlyTypingError) {
            closeDialog();
        }
    }

    /** Gibt an, ob im Fall einer falsch beantworteten Vokabel nur ein Tippfehler vorlag. */
    public boolean wasOnlyTypingError() {
        return onlyTypingError;
    }

}
