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

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;

import de.duehl.basics.collections.CollectionsHelper;
import de.duehl.vocabulary.japanese.data.symbol.Kanji;
import de.duehl.vocabulary.japanese.ui.dialog.kanji.display.data.ButtonAndFontName;

/**
 * Diese Klasse stellt ein einzelnes Kanji-Zeichen (UTF-8) in einem Label dar.
 *
 * Um es in verschiedenen Schriftarten betrachten zu können, gibt es Buttons zum Wechseln der
 * Schriftart.
 *
 * @version 1.01     2025-12-15
 * @author Christian Dühl
 */

public class KanjiPanel {

    private static final int DEFAULT_BIGGER_FONT_SIZE = 400;

    private static final List<String> FONT_NAMES = CollectionsHelper.buildListFrom(
            new JLabel().getFont().getFontName(), // getName()
            "MS Gothic", "Yu Gothic"
            /* Die folgenden Fonts sind hier entweder nicht vorhanden oder zeigen nur Quadrate oder
             * das gleiche wir der erste Font:
             * "Meiryo", "NSimSun", "Hiragino Kaku Gothic",
             * "Serif", "SansSerif", "Monospaced", "Dialog", "DialogInput", //"Verdana",
             * "TimesNewRoman",
             * "Helvetica", "Courier"
             */
            );


    /**
     * Das Panel mit dem Label auf dem das Kanji dargestellt wird und den Buttons zum Wechseln der
     * Schriftart.
     */
    private final JPanel panel;

    /** Das Label auf dem das Kanji dargestellt wird. */
    private final JLabel label;

    /** Der Name des gerade verwendeten Fonts. */
    private String fontName;

    /** Die Vergrößerung der Schrift in der das Kanji dargestellt wird. */
    private int biggerFontSize;

    /** Gibt an, ob der Name und die Größe des Fonts schon gesetzt wurde. */
    private boolean fontNameAndSizeSet;

    /** Die Buttons zum Wechseln des Fonts. */
    private List<ButtonAndFontName> fontButtons;

    /** Wird ausgeführt, nachdem einer der Buttons gedrückt wurde. */
    private Runnable afterFontButtonPressedRunnable;

    /** Gibt an ob festgelegt wurde, nachdem einer der Buttons gedrückt wurde. */
    private boolean afterFontButtonPressedRunnableSet;

    /** Konstruktor. */
    public KanjiPanel() {
        panel = new JPanel();
        label = new JLabel();

        fontName = FONT_NAMES.get(0);
        biggerFontSize = DEFAULT_BIGGER_FONT_SIZE;
        fontNameAndSizeSet = false;

        afterFontButtonPressedRunnable = null;
        afterFontButtonPressedRunnableSet = false;

        initPanel();
        initLabel();
        createButtons();
        setFontButtonsBorder();
        fillPanel();
    }

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

    private void initLabel() {
        label.setOpaque(true);
        label.setBackground(Color.WHITE);
        label.setHorizontalAlignment(JLabel.CENTER);
        label.setVerticalAlignment(JLabel.CENTER);
    }

    private void createButtons() {
        fontButtons = new ArrayList<>();

        int fontNumber = 0;
        for (String name : FONT_NAMES) {
            ++fontNumber;
            JButton button = createFontButton(name, fontNumber);
            fontButtons.add(new ButtonAndFontName(name, button));
        }
    }

    private JButton createFontButton(String name, int fontNumber) {
        JButton button = new JButton("Font " + fontNumber);
        button.addActionListener(e -> fontButtonPressed(name));
        return button;
    }

    private void fontButtonPressed(String name) {
        fontName = name;
        fontNameAndSizeSet = false;
        setFontNameAndSizeIfNecessary();
        setFontButtonsBorder();

        if (afterFontButtonPressedRunnableSet) {
            afterFontButtonPressedRunnable.run();
        }
    }

    private void setFontButtonsBorder() {
        for (ButtonAndFontName fontButton : fontButtons) {
            String name = fontButton.getFontName();
            JButton button = fontButton.getButton();
            setFontButtonBorder(name, button);
        }
    }

    private void setFontButtonBorder(String name, JButton button) {
        boolean pressed = name.equals(fontName);
        if (pressed) {
            button.setBorder(BorderFactory.createLoweredBevelBorder());
        }
        else {
            button.setBorder(BorderFactory.createRaisedBevelBorder());
        }
    }

    private void fillPanel() {
        panel.add(label, BorderLayout.CENTER);
        panel.add(createButtonPart(), BorderLayout.SOUTH);
    }

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

        for (ButtonAndFontName fontButton : fontButtons) {
            JButton button = fontButton.getButton();
            panel.add(button);
        }

        return panel;
    }

    /** Legt fest was ausgeführt wird, nachdem einer der Buttons gedrückt wurde. */
    public void setAfterFontButtonPressedRunnable(Runnable afterFontButtonPressedRunnable) {
        this.afterFontButtonPressedRunnable = afterFontButtonPressedRunnable;
        afterFontButtonPressedRunnableSet = true;
    }

    /** Setter für die Vergrößerung der Schrift in der das Kanji dargestellt wird. */
    public void setBiggerFontSize(int biggerFontSize) {
        this.biggerFontSize = biggerFontSize;
    }

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

    /** Zeigt das Kanji an. Kann mehrfach aufgerufen werden. */
    public void showKanji(Kanji kanji) {
        setFontNameAndSizeIfNecessary();

        String kanjiCharacter = kanji.getCharacter();
        label.setText(kanjiCharacter);
    }

    private void setFontNameAndSizeIfNecessary() {
        if (!fontNameAndSizeSet) {
            Font standardFont = new JLabel().getFont();
            int size = standardFont.getSize() + biggerFontSize;
            Font font = new Font(fontName, standardFont.getStyle(), size);
            label.setFont(font);
            //GuiTools.biggerFont(label, biggerFontSize);
            fontNameAndSizeSet = true;
        }
    }

}
