package de.duehl.swing.ui.dialogs;

/*
 * Copyright 2020 Christian Dühl. All rights reserved.
 *
 * This program is free software. You can redistribute it and/or
 * modify it under the same terms as perl:
 *
 * general:  http://dev.perl.org/licenses/
 * GPL:      http://dev.perl.org/licenses/gpl1.html
 * artistic: http://dev.perl.org/licenses/artistic.html
 */

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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

import de.duehl.swing.ui.GuiTools;
import de.duehl.swing.ui.dialogs.base.ModalDialogBase;
import de.duehl.swing.ui.layout.VerticalLayout;

/**
 * Diese Klasse stellt die abstrakte Basis für den Dialoge zur Auswahl zwischen in vertikalen
 * Buttons angeordneten Auswahlmöglichkeiten dar.
 *
 * @version 1.01     2020-09-21
 * @author Christian Dühl
 */

public abstract class VerticalButtonSelectionDialog extends ModalDialogBase {

    private static final Component NOT_USED_LOWER_PART = new JPanel();

    /** Liste mit den Button-Beschriftungen. */
    private final List<String> buttonTexts;

    /** Die Buttons nach ihrem Titel. */
    private final Map<String, JButton> buttonsByTitle;

    /** Optional unten anzuzeigender Bereich. */
    private Component additionalFooterPart;

    /** Konstruktor. */
    public VerticalButtonSelectionDialog(List<String> buttonTexts) {
        super("Bitte wählen");

        this.buttonTexts = buttonTexts;
        buttonsByTitle = new HashMap<>();

        fillDialog();
    }

//    /** Falls nur ein Button angezeigt wird, wird dieser ausgewählt und der Dialog beendet. */
//    public void selectOnlyButtonIfOneButtonAndCloseDialog() {
//        if (buttonTexts.size() == 1) {
//            reactOnButtonText(buttonTexts.get(0));
//            closeDialog();
//        }
//    }
// Das klappt so leider nicht und hat komische Effekte... daher erstmal auskommentiert.

    /* Erstellt die Oberfläche des Dialogs. */
    @Override
    protected final void populateDialog() {
        add(createMainPanel(), BorderLayout.CENTER);
    }

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

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

        initAdditionalFooterPart();
        if (!additionalFooterPart.equals(NOT_USED_LOWER_PART)) {
            panel.add(additionalFooterPart, BorderLayout.SOUTH);
        }

        return panel;
    }

    /**
     * Methode die überschrieben werden kann, um am unteren Ende des Dialogs noch Komponenten
     * hinzuzufügen.
     */
    protected void initAdditionalFooterPart() {
        setAdditionalFooterPart(NOT_USED_LOWER_PART);
    }

    /** Setter für den optional unten anzuzeigender Bereich. */
    protected final void setAdditionalFooterPart(Component additionalFooterPart) {
        this.additionalFooterPart = additionalFooterPart;
    }

    private Component createVerticalButtonsPart() {
        JPanel panel = new JPanel();
        panel.setLayout(new VerticalLayout(2, VerticalLayout.BOTH));

        for (String text : buttonTexts) {
            panel.add(createButton(text));
        }

        return panel;
    }

    private JButton createButton(String text) {
        JButton button  = new JButton(text);
        button.addActionListener(event -> reactOnButtonClick(event));
        button.setMargin(new Insets(5, 25, 5, 25));
        GuiTools.biggerFont(button, 3);

        if (buttonsByTitle.containsKey(text)) {
            throw new RuntimeException("Der Button-Text '" + text + "' wurde mehrfach vergeben!");
        }
        buttonsByTitle.put(text, button);

        return button;
    }

    private void reactOnButtonClick(ActionEvent event) {
        String buttonText = event.getActionCommand();
        reactOnButtonText(buttonText);
    }

    private void reactOnButtonText(String buttonText) {
        reactOnButtonClick(buttonText);
        closeDialog();
    }

    /** Reagiert auf einen Klick auf den Button mit dem übergebenen Text. */
    protected abstract void reactOnButtonClick(String buttonText);

    /** Versteckt den Button mit dem übergebenen Namen. */
    protected void hideButton(String buttonText) {
        JButton button = getButtonByText(buttonText);
        button.setEnabled(false);
    }

    private JButton getButtonByText(String buttonText) {
        JButton button = buttonsByTitle.get(buttonText);
        if (null == button) {
            throw new RuntimeException("Der Button-Text '" + buttonText + "' ist unbekannt!");
        }
        return button;
    }

    /** Gibt an, ob der Button mit dem übergebenen Namen versteckt wurde. */
    protected boolean isButtonHidden(String buttonText) {
        return !isButtonActive(buttonText);
    }

    /**
     * Gibt an, ob der Button mit dem übergebenen Namen nicht versteckt wurde, also anklickbar ist.
     */
    protected boolean isButtonActive(String buttonText) {
        JButton button = getButtonByText(buttonText);
        return button.isEnabled();
    }

}
