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

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

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

import de.duehl.basics.text.NumberString;
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.ModalDialogBase;
import de.duehl.swing.ui.layout.VerticalLayout;
import de.duehl.vocabulary.japanese.common.data.InternalAdditionalKanaData;
import de.duehl.vocabulary.japanese.common.persistence.Options;
import de.duehl.vocabulary.japanese.data.FumikoDataStructures;
import de.duehl.vocabulary.japanese.data.symbol.Hiragana;
import de.duehl.vocabulary.japanese.logic.symbol.kana.internal.InternalKanaDataRequester;
import de.duehl.vocabulary.japanese.logic.symbol.kana.test.HiraganaTestChecker;
import de.duehl.vocabulary.japanese.logic.symbol.kana.test.data.SingleUserInputHiraganaCheckResult;
import de.duehl.vocabulary.japanese.ui.data.FumikoUiObjects;
import de.duehl.vocabulary.japanese.ui.dialog.kana.hiraganatest.components.HiraganaLabel;
import de.duehl.vocabulary.japanese.ui.tools.VocabularyTrainerUiTools;

/**
 * Diese Klasse fragt ein Hiragana nach dem anderen ab: Das Symbol wird angezeigt und der Benutzer
 * kann deutsche Bedeutungen sowie ON- und kun-Lesungen eingeben.
 *
 * Anhand der in den Hiragana-Enum-Objekten wird dann überprüft, ob (ausreichend viel) eingegeben
 * wurde und im Dialog zur Bewertung der einen Abfrage werden alle Daten zu dem Hiragana angezeigt.
 *
 * @version 1.01     2025-02-02
 * @author Christian Dühl
 */

public class HiraganaTester extends ModalDialogBase {

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


    /** Die Liste der abzufragenden Hiragana. */
    private final List<Hiragana> hiraganaToTest;

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

    /** Das Label auf dem das Hiragana dargestellt wird. */
    private final HiraganaLabel hiraganaLabel;

    /** Das Eingabefeld für die Hepburn-Darstellung. */
    private final StringSelection hepburnTextField;

    /** Der Index des angezeigten Hiragana. */
    private int shownHiraganaIndex;

    /** Die Anzahl der abgefragten Hiragana. */
    private int tested;

    /** Die Anzahl der richtig abgefragten Hiragana. */
    private int correctTested;

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

    /**
     * Die Prozentzahl des Erfolgs der letzten zehn Abfragen dieser Hiragana bevor der aktuelle
     * Test gelaufen ist.
     */
    private final double lastTenTestsPercentBefore;

    private final StringSelection numberOfHiraganaSelection;
    private final StringSelection numberOfDoneHiraganaSelection;
    private final StringSelection numberOfCorrectDoneHiraganaSelection;
    private final StringSelection correctDonePercentHiraganaSelection;

    /**
     * Konstruktor.
     *
     * @param hiraganaToTest
     *            Die Liste der abzufragenden Hiragana.
     * @param dataStructures
     *            Die Datenstrukturen des Vokabeltrainers.
     * @param uiObjects
     *            Die häufig verwendeten Funktionen der grafischen Oberfläche des Vokabeltrainers.
     */
    public HiraganaTester(List<Hiragana> hiraganaToTest, FumikoDataStructures dataStructures,
            FumikoUiObjects uiObjects) {
        super(uiObjects.getGuiLocation(), uiObjects.getProgramImage(), "Hiragana-Test",
                DIALOG_DIMENSION);
        this.hiraganaToTest = hiraganaToTest;
        this.dataStructures = dataStructures;

        hiraganaLabel = new HiraganaLabel();

        hepburnTextField = new StringSelection("Hepburn-Darstellung");

        quitButton = new JButton("");

        lastTenTestsPercentBefore = VocabularyTrainerUiTools
                .createLastTenHiraganaTestsPercent(hiraganaToTest, dataStructures);

        numberOfHiraganaSelection = new StringSelection("Anzahl abzufragender Hiragana");
        numberOfDoneHiraganaSelection = new StringSelection("Anzahl bereits abgefragte Hiragana");
        numberOfCorrectDoneHiraganaSelection = new StringSelection(
                "Anzahl korrekt beantworteter Hiragana");
        correctDonePercentHiraganaSelection = new StringSelection(
                "Prozent korrekt beantworteter Hiragana");

        init();
        fillDialog();
    }

    private void init() {
        tested = 0;
        correctTested = 0;

        initStringSelections();

        shownHiraganaIndex = 0;
        showHiraganaAtIndex();
    }

    private void initStringSelections() {
        SelectionsHelper.initSelectionAsEditor(hepburnTextField);

        hepburnTextField.addReturnListener(() -> checkAndShowNextOrEndDialog());

        SelectionsHelper.initSelectionAsViewer(numberOfHiraganaSelection);
        SelectionsHelper.initSelectionAsViewer(numberOfDoneHiraganaSelection);
        SelectionsHelper.initSelectionAsViewer(numberOfCorrectDoneHiraganaSelection);
        SelectionsHelper.initSelectionAsViewer(correctDonePercentHiraganaSelection);

        numberOfHiraganaSelection.setText(NumberString.taupu(hiraganaToTest.size()));
        setNumbersAndPercent();
    }

    private void showHiraganaAtIndex() {
        Hiragana hiragana = hiraganaToTest.get(shownHiraganaIndex);
        hiraganaLabel.showHiragana(hiragana);

        hepburnTextField.setText("");

        hepburnTextField.requestFocus();
    }

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

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

        panel.add(createSummeryPart(), BorderLayout.NORTH);
        panel.add(createHiraganaLablePart(), BorderLayout.CENTER);
        panel.add(createUserInputPart(), BorderLayout.SOUTH);

        return panel;
    }

    private Component createSummeryPart() {
        JPanel panel = new JPanel();
        panel.setLayout(new GridLayout(1, 0, 3, 3));

        panel.add(numberOfHiraganaSelection.getPanel());
        panel.add(numberOfDoneHiraganaSelection.getPanel());
        panel.add(numberOfCorrectDoneHiraganaSelection.getPanel());
        panel.add(correctDonePercentHiraganaSelection.getPanel());

        return panel;
    }

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

        panel.add(hiraganaLabel.getLabel(), BorderLayout.CENTER);

        return panel;
    }

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

        panel.add(createPureUserInputPart(), BorderLayout.CENTER);
        panel.add(createButtonsPart(), BorderLayout.SOUTH);

        return panel;
    }

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

        panel.add(hepburnTextField.getPanel());

        return panel;
    }

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

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

        return panel;
    }
    private Component createQuitButton() {
        quitButton.setText("Abbrechen");
        quitButton.addActionListener(e -> quit());
        return quitButton;
    }

    private void quit() {
        closeDialog();
    }

    private Component createOkButton() {
        JButton button = new JButton("   Prüfen   ");
        GuiTools.biggerFont(button, 5);
        button.addActionListener(e -> checkAndShowNextOrEndDialog());
        return button;
    }

    private void checkAndShowNextOrEndDialog() {
        ++tested;
        SingleUserInputHiraganaCheckResult result = check();
        boolean ok = result.isOk();
        if (result.isOk()) {
            ++correctTested;
        }

        boolean wasOnlyTypingError = showSingleUserInputCheckResult(result);
        if (!result.isOk() && wasOnlyTypingError) {
            ++correctTested;
            ok = true;
        }

        saveUserTestAnswerInInternalHiraganaData(result.getHiragana(), ok);
        setNumbersAndPercent();

        if (tested == hiraganaToTest.size()) {
            closeDialog();
            showTotalUserInputCheckResult();
        }
        else {
            ++shownHiraganaIndex;
            showHiraganaAtIndex();
        }
    }

    private SingleUserInputHiraganaCheckResult check() {
        Hiragana hiragana = hiraganaToTest.get(shownHiraganaIndex);
        String hepburn = hepburnTextField.getTrimmedText();

        HiraganaTestChecker checker = new HiraganaTestChecker(hiragana, hepburn);
        checker.check();
        return checker.getResult();
    }

    private boolean showSingleUserInputCheckResult(SingleUserInputHiraganaCheckResult result) {
        String userInputHepburn = hepburnTextField.getTrimmedText();

        Options options = dataStructures.getOptions();
        HiraganaTestEvaluationDialog dialog = new HiraganaTestEvaluationDialog(result,
                userInputHepburn, options, getParentLocation(), getProgramImage());
        dialog.setVisible(true);

        if (result.isOk()) {
            return false;
        }
        else {
            return dialog.wasOnlyTypingError();
        }
    }

    private void saveUserTestAnswerInInternalHiraganaData(Hiragana hiragana, boolean ok) {
        InternalKanaDataRequester requester = dataStructures.getInternalKanaDataRequester();
        InternalAdditionalKanaData data = requester.getInternalDataForHiragana(hiragana);
        data.tested(ok);
    }

    public void setNumbersAndPercent() {
        numberOfDoneHiraganaSelection.setText(NumberString.taupu(tested));
        numberOfCorrectDoneHiraganaSelection.setText(NumberString.taupu(correctTested));
        if (tested == 0) {
            correctDonePercentHiraganaSelection.setText("0.00 %");
        }
        else {
            correctDonePercentHiraganaSelection.setText(
                    NumberString.percent(correctTested, tested) + " %");
        }
    }

    private void showTotalUserInputCheckResult() {
        quitButton.setText("Beenden");
        SwingUtilities.invokeLater(() -> quitButton.requestFocus());

        double lastTenTestsPercentAfter =
                VocabularyTrainerUiTools.createLastTenHiraganaTestsPercent(hiraganaToTest,
                        dataStructures);
        String originalDialogTitle = createDialogTitle("Hiragana abfragen");
        Options options = dataStructures.getOptions();
        AllHiraganaTestEvaluationDialog dialog = new AllHiraganaTestEvaluationDialog(options,
                tested, correctTested, getLocation(),
                getProgramImage(), lastTenTestsPercentBefore, lastTenTestsPercentAfter,
                originalDialogTitle);
        dialog.setVisible(true);
    }

    private String createDialogTitle(String testTitle) {
        return VocabularyTrainerUiTools.generateTitleWithHiraganaTestSuccesss(hiraganaToTest,
                testTitle, dataStructures);
    }

}
