package de.duehl.swing.ui.dialogs.lists;

/*
 * Copyright 2021 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.Dimension;
import java.awt.Image;
import java.awt.Point;

import javax.swing.JLabel;
import javax.swing.JPanel;

import de.duehl.swing.ui.GuiTools;
import de.duehl.swing.ui.buttons.painted.PaintedButton;
import de.duehl.swing.ui.buttons.painted.PlusButton;
import de.duehl.swing.ui.dialogs.lists.logic.LogicalEditableList;
import de.duehl.swing.ui.dialogs.lists.logic.LogicalEditableListElement;
import de.duehl.swing.ui.dialogs.lists.ui.EditableListElement;

/**
 * Diese Klasse steht für die Basis eines Dialogs, in dem man eine Liste von Dingen mit graphischer
 * Repräsentation anzeigen, bearbeiten, löschen, umsortieren und neue Elemente hinzufügen kann.
 *
 * @version 1.02     2021-11-18
 * @author Christian Dühl
 */

public abstract class EditableListDialog<Element extends LogicalEditableListElement>
        extends EditableListDialogBase<Element> {

    /** Überschrift über den dargestellten Elementen. */
    private final String elementsTitle;

    /**
     * Konstruktor.
     *
     * Die abgeleitete Klasse muss <code>fillDialog()</code> aufrufen.
     *
     * @param dialogDimension
     *            Größe des Dialogfensters.
     * @param parentLocation
     *            Position des Rahmens der Oberfläche, vor der dieser Dialog erzeugt wird.
     * @param programImage
     *            Icon für das Programm.
     * @param dialogTitle
     *            Titel des Dialogs.
     * @param elementsTitle
     *            Überschrift über den dargestellten Elementen.
     * @param logicalList
     *            Liste mit den logischen Elementen, welche dargestellt werden
     */
    public EditableListDialog(Dimension dialogDimension, Point parentLocation, Image programImage,
            String dialogTitle, String elementsTitle, LogicalEditableList<Element> logicalList) {
        super(dialogDimension, parentLocation, programImage, dialogTitle, logicalList);
        setMinimumSize(dialogDimension);

        this.elementsTitle = elementsTitle;
    }

    /** Erzeugt den Hauptbereich des Dialogs. */
    @Override
    protected final Component createMainPart() {
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());

        panel.add(createTitleAndButtonForNewElementPart(), BorderLayout.NORTH);
        panel.add(getElementsPanel(), BorderLayout.CENTER);

        return panel;
    }

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

        panel.add(createTitleLabel(), BorderLayout.CENTER);
        panel.add(createNewElementPart(), BorderLayout.EAST);

        return panel;
    }

    private Component createTitleLabel() {
        JLabel label = new JLabel(elementsTitle);
        GuiTools.biggerFont(label, 10);
        GuiTools.boldFont(label);
        return label;
    }

    private Component createNewElementPart() {
        PaintedButton button = new PlusButton();
        button.setFocusable(false);
        button.addActionListener(e -> createNewUiElement());
        button.setForceSquare(true);
        return button;
    }

    private void createNewUiElement() {
        Element element = createNewElement();

        EditableListElement<Element> uiElement = createUiElement(element);
        uiElement.editElement();

        if (element.areUserInputValuesFilled()) {
            if (logicalList.canWeAdd(element)) {
                logicalList.add(element);
                updateElementsPanel();
            }
            else {
                GuiTools.informUser(getDialog(), "Gleiche Daten eingegeben!",
                        "Es wurde kein neues Listenobjekt erzeugt, da die Eingabe der Daten "
                                + "einem bereits vorhandenen Element in zu großem Maße "
                                + "gleicht.");
            }
        }
        else {
            GuiTools.informUser(getDialog(), "Zu wenige Daten eingegeben!",
                    "Es wurde kein neues Listenobjekt erzeugt, da die Eingabe der Daten "
                            + "unvollständig war.");
        }
    }

    /**
     * Erstellt ein neues logisches Element.
     *
     * Zur logischen Liste wird es hinterher schon automatisch hinzugefügt.
     */
    protected abstract Element createNewElement();

    /** Erzeugt die Darstellung für das übergebene Element. */
    @Override
    protected Component createRealElementPart(Element element) {
        EditableListElement<Element> uiElement = createUiElement(element);
        return uiElement.createPanel();
    }

}
