package de.duehl.vocabulary.japanese.ui.components.bars;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;

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

import de.duehl.swing.ui.GuiTools;
import de.duehl.swing.ui.move.SwitchableVerticalMoveButtons;
import de.duehl.swing.ui.move.data.MovingGui;
import de.duehl.swing.ui.move.data.NotMovingGui;
import de.duehl.swing.ui.move.data.VerticalMoveButtonsUser;
import de.duehl.vocabulary.japanese.data.Vocable;
import de.duehl.vocabulary.japanese.ui.components.text.VocaleBarTextCreator;

/**
 * Diese Klasse stellt die grafische Oberfläche der Anzeige einer Vokabel in einer eigenen
 * Vokabelliste oder der Liste mit der Auswahl der Vokabeln dazu dar.
 *
 * Dieser wird nur in dem Dialog zum Bearbeiten einer Liste (OwnListEditorDialog) und im Dialog
 * zur erweiterten Suche (ComplexVocableSearchDialog) angezeigt.
 *
 * @version 1.01     2025-08-07
 * @author Christian Dühl
 */

public class VocableBar implements VerticalMoveButtonsUser {

    /** Die angezeigte Vokabel. */
    private final Vocable vocable;

    /** Wird ausgeführt, wenn der Button gedrückt wird. */
    private final Runnable buttonAction;

    /** Der Dialog, in dem die Bars bewegt etc. werden. */
    private final MovingGui<Vocable> gui;

    /** Der Panel auf dem die Vokabel dargestellt wird. */
    private final JPanel panel;

    /** Der Panel auf dem der Schalter und vielleicht auch die CheckBox dargestellt wird. */
    private final JPanel rightPanel;

    /** Das Label, auf dem die Vokabel dargestellt wird. */
    private final JLabel vocableLabel;

    /** CheckBox zur Selektion. */
    private final JCheckBox selectionCheckBox;

    /** Der Multifunktions-Button (Hinzufügen zur Liste oder Löschen aus Liste). */
    private final JButton multifunctionButton;

    /** Der umschaltbare Panel mit Buttons zum Verschieben nach oben und unten. */
    private final SwitchableVerticalMoveButtons switchableMoveButtons;

    /**
     * Gibt an, ob die Schalter zum Bewegen der Bar genutzt werden (nur dann muss gui definiert
     * sein). Dies braucht man für den Dialog zum Bearbeiten der eigenen Listen, nicht aber für die
     * erweiterte Suche.
     */
    private boolean canBeMoved;

    /** Gibt an, ob auf der linken Seite einen extra Button mit den Details angezeigt wird. */
    private boolean showExtraDetailButtonOnTheLeft;

    /** Den Button mit den Details auf der linken Seite. */
    private final JButton extraDetailbutton;

    /**
     * Konstruktor für die erweiterte Suche (ComplexVocableSearchDialog). Dort wird der Button
     * nicht verwendet.
     *
     * @param vocable
     *            Die angezeigte Vokabel.
     * @param buttonAction
     *            Wird ausgeführt, wenn der Button gedrückt wird.
     */
    public VocableBar(Vocable vocable, Runnable buttonAction) {
        this(vocable, buttonAction, new NotMovingGui<Vocable>());
    }

    /**
     * Konstruktor für den Dialog zur Bearbeitung eigener Listen (OwnListEditorDialog) (rechte oder
     * linke Seite).
     *
     * Diese Klasse wird sowohl in der Vokabel-Liste rechts als auch links in der gefilterten Liste
     * aller Vokabeln genutzt.
     *
     * @param vocable
     *            Die angezeigte Vokabel.
     * @param buttonAction
     *            Wird ausgeführt, wenn der Button gedrückt wird.
     * @param gui
     *            Der Dialog, in dem die Bars bewegt etc. werden.
     */
    public VocableBar(Vocable vocable, Runnable buttonAction, MovingGui<Vocable> gui) {
        this.vocable = vocable;
        this.buttonAction = buttonAction;
        this.gui = gui;

        panel = new JPanel();
        vocableLabel = new JLabel();
        rightPanel = new JPanel();
        multifunctionButton = new JButton();
        selectionCheckBox = new JCheckBox();
        switchableMoveButtons = new SwitchableVerticalMoveButtons((VerticalMoveButtonsUser) this);

        showExtraDetailButtonOnTheLeft = false;
        extraDetailbutton = new JButton("?");

        init();
    }

    private void init() {
        initVocableLabel();
        initButton();
        initRightPanel();
    }

    private void initVocableLabel() {
        vocableLabel.setText(createVocableText());
        GuiTools.biggerFont(vocableLabel, 7);
        vocableLabel.setHorizontalAlignment(JLabel.CENTER);
    }

    private void initButton() {
        multifunctionButton.addActionListener(e -> buttonAction.run());
    }

    private void initRightPanel() {
        rightPanel.setLayout(new BorderLayout());
        rightPanel.add(multifunctionButton, BorderLayout.EAST);
    }

    /**
     * Nutzt den Button im Dialog zur Bearbeitung eigener Listen auf der linken Seite zum
     * Hinzufügen und zeigt auch die CheckBox zur Auswahl der Vokabel an.
     */
    public void useButtonAsAddVocableToList() {
        multifunctionButton.setText("hinzufügen");
        rightPanel.add(selectionCheckBox, BorderLayout.WEST);
        canBeMoved = true;
    }

    /**
     * Nutzt den Button im Dialog zur Bearbeitung eigener Listen auf der rechten Seite zum Löschen.
     * Die CheckBox wird nicht angezeigt.
     */
    public void useButtonAsDeletion() {
        multifunctionButton.setText("entfernen");
        canBeMoved = true;
    }

    /** Nutzt den Button im Dialog zur erweiterten Suche um Details anzuzeigen. */
    public void useButtonAsShowDetails() {
        multifunctionButton.setText("Details ansehen");
        canBeMoved = false;
    }

    /** Zeigt auf der linken Seite einen extra Button mit den Details an. */
    public void showExtraDetailButtonOnTheLeft(Runnable detailRunnable) {
        extraDetailbutton.addActionListener(e -> detailRunnable.run());
        showExtraDetailButtonOnTheLeft = true;
    }

    /** Baut die Gui auf. */
    public void createGui() {
        setUpAndDownButtonColorsAndEnabled();
        fillPanel();
    }

    /** Kennzeichnet die Vokabel als ausgegraut (sie ist bereits in der Liste). */
    public void disable() {
        multifunctionButton.setEnabled(false);
        selectionCheckBox.setSelected(false);
        selectionCheckBox.setEnabled(false);
        vocableLabel.setForeground(Color.LIGHT_GRAY);
        extraDetailbutton.setEnabled(false);
    }

    /** Kennzeichnet die Vokabel als aktiv (sie ist nicht in der Liste). */
    public void enable() {
        multifunctionButton.setEnabled(true);
        selectionCheckBox.setEnabled(true);
        vocableLabel.setForeground(Color.BLACK);
        extraDetailbutton.setEnabled(true);
    }

    /** Gibt an, ob die Bar eines Vokabulars nach oben bewegt werden kann. */
    @Override
    public boolean canMoveButtonsUserMoveUp() {
        return canBeMoved && gui.canBarMoveUp(vocable);
    }

    /** Gibt an, ob die Bar einer Vokabel nach unten bewegt werden kann. */
    @Override
    public boolean canMoveButtonsUserMoveDown() {
        return canBeMoved && gui.canBarMoveDown(vocable);
    }

    /** Verschiebt die Bar einer Vokabel an die erste Stelle. */
    @Override
    public void moveMoveButtonsUserToFirst() {
        if (canBeMoved) {
            gui.moveBarToFirst(vocable);
        }
    }

    /** Verschiebt die Bar einer Vokabel nach oben. */
    @Override
    public void moveMoveButtonsUserUp() {
        if (canBeMoved) {
            gui.moveBarUp(vocable);
        }
    }

    /** Verschiebt die Bar einer Vokabel nach unten. */
    @Override
    public void moveMoveButtonsUserDown() {
        if (canBeMoved) {
            gui.moveBarDown(vocable);
        }
    }

    /** Verschiebt die Bar einer Vokabel an die letzte Stelle. */
    @Override
    public void moveMoveButtonsUserToLast() {
        if (canBeMoved) {
            gui.moveBarToLast(vocable);
        }
    }

    /**
     * Setzt die Farben und Darstellung der Buttons abhängig davon, ob sie verschoben werden
     * können.
     */
    public void setUpAndDownButtonColorsAndEnabled() {
        switchableMoveButtons.setUpAndDownButtonColorsAndEnabled();
    }

    private void fillPanel() {
        panel.setLayout(new BorderLayout());
        GuiTools.createTitle(panel);

        if (showExtraDetailButtonOnTheLeft) {
            panel.add(GuiTools.centerVertical(extraDetailbutton), BorderLayout.WEST);
        }
        panel.add(vocableLabel, BorderLayout.CENTER);
        panel.add(createButtonPart(), BorderLayout.EAST);
    }

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

        panel.add(rightPanel, BorderLayout.WEST);
        panel.add(GuiTools.centerVertical(switchableMoveButtons.getPanel()), BorderLayout.EAST);

        return panel;
    }

    private String createVocableText() {
        VocaleBarTextCreator creator = new VocaleBarTextCreator(vocable);
        creator.create();
        return creator.getText();
    }

    /** Getter für den Panel auf dem die Vokabel dargestellt wird. */
    public Component getPanel() {
        return panel;
    }

    /** Setzt die Vokabel aus aus- oder nicht ausgewählt. */
    public void setSelected(boolean selected) {
        selectionCheckBox.setSelected(selected);
    }

    /** Gibt an, ob die Vokabel ausgewählt ist. */
    public boolean isSelected() {
        return selectionCheckBox.isSelected();
    }

    /** Zeigt die Buttons zum Verschieben an oder blendet wie aus. */
    public void showMoveButtonsOnBars(boolean showMoveButtonsOnBars) {
        switchableMoveButtons.showMoveButtons(showMoveButtonsOnBars);
        panel.repaint();
    }

}
