package de.duehl.vocabulary.japanese.ui.dialog.update;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Image;
import java.awt.Point;
import java.util.ArrayList;
import java.util.List;

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

import de.duehl.basics.text.html.HtmlTool;
import de.duehl.swing.ui.GuiTools;
import de.duehl.swing.ui.dialogs.base.ModalDialogBase;
import de.duehl.swing.ui.layout.VerticalLayout;
import de.duehl.vocabulary.japanese.logic.ownlists.groups.OwnListGroup;
import de.duehl.vocabulary.japanese.ui.dialog.update.bar.GroupBar;
import de.duehl.vocabulary.japanese.website.update.ownlists.OwnListGroupsUpdater;
import de.duehl.vocabulary.japanese.website.update.ownlists.data.NewestOwnListVersionListEntry;
import de.duehl.vocabulary.japanese.website.update.ownlists.data.OwnListInterestAndVersionEntry;

/**
 * Diese Klasse zeigt dem Benutzer den Dialog an, in der er die Einstellung seiner Interessen
 * vornehmen und eine oder mehrere Gruppen von Liste herunterladen kann.
 *
 *   +----------------+------------------+----------+---------------+------------+
 *   | Listengruppe   |  Listenversion   |   neu?   |    Interesse  |  Download  |
 *   +----------------+------------------+----------+---------------+------------+
 *   | FROM_ZERO_1    |  35              |   nein   |    nein       |    [ ]     |
 *   | FROM_ZERO_2    |  17              |   nein   |    nein       |    [ ]     |
 *   | FROM_ZERO_3    |  3               |   nein   |    nein       |    [ ]     |
 *   | SCHRITT_FUER_1 |  4               |   nein   |    nein       |    [ ]     |
 *   | MARUGOTO_A1    |  7               |   ja     |    ja         |    [x]     |
 *   | VHS_A1_1       |  11              |   nein   |    ja         |    [ ]     |
 *   | VHS_A1_2       |  1               |   ja     |    ja         |    [x]     |
 *   +----------------+------------------+----------+---------------+------------+
 *
 * Angezeigt wird statt des Kürzels der Gruppe natürlich die im Enum hinterlegte
 * Beschreibung. Vielleicht hinterlege ich da auch noch eine noch kürzere Version.
 * Siehe de.duehl.vocabulary.japanese.logic.ownlists.OwnListGroup.
 * In den Entries ist das Kürzel gespeichert, also ("FROM_ZERO_1").
 *
 * Falls die Liste der neuen oder aktualisierten Gruppen leer ist, wird der Teil zur Anzeige der
 * Neuerungen nicht mit angezeigt.
 *
 * @version 1.01     2024-10-12
 * @author Christian Dühl
 */

public class OwnListInterestSelectionAndDownloadDialog extends ModalDialogBase {

    /** Die Liste der Einträge in der Datei Neuste_Version_Listen.txt auf dem Server. */
    private List<NewestOwnListVersionListEntry> newestOwnListVersionEntries;

    /**
     * Die Liste der Einträge in der Datei Eigene_Listen_Interessen_und_Versionen.txt auf dem
     * Rechner des Benutzers.
     */
    private final List<OwnListInterestAndVersionEntry> interestAndVersionEntries;

    /**
     * Die Liste derjenigen Gruppennamen, die der Benutzer bisher noch nicht oder nur in einer
     * älteren Version kannte.
     */
    private final List<String> newerOrUnseenGroupNames;

    /** Gibt an, ob der Dialog mit OK bestätigt wurde. */
    private boolean applied;

    /** Die Bars zu den Gruppen. */
    private final List<GroupBar> bars;

    /**
     * Konstruktor.
     *
     * @param newestOwnListVersionEntries
     *            Die Liste der Einträge in der Datei Neuste_Version_Listen.txt auf dem Server.
     * @param interestAndVersionEntries
     *            Die Liste der Einträge in der Datei Eigene_Listen_Interessen_und_Versionen.txt
     *            auf dem Rechner des Benutzers.
     * @param newerOrUnseenGroupNames
     *            Die Liste derjenigen Gruppennamen, die der Benutzer bisher noch nicht oder nur in
     *            einer älteren Version kannte.
     * @param parentLocation
     *            Position des Rahmens der Oberfläche, vor der dieser Dialog erzeugt wird.
     * @param programImage
     *            Anzuzeigendes ProgrammIcon.
     */
    public OwnListInterestSelectionAndDownloadDialog(
            List<NewestOwnListVersionListEntry> newestOwnListVersionEntries,
            List<OwnListInterestAndVersionEntry> interestAndVersionEntries,
            List<String> newerOrUnseenGroupNames,
            Point parentLocation, Image programImage) {
        super(parentLocation, programImage,
                "Einstellung der Interessen und Download aktualisierter oder neuer Gruppen");
        this.newestOwnListVersionEntries = newestOwnListVersionEntries;
        this.interestAndVersionEntries = interestAndVersionEntries;
        this.newerOrUnseenGroupNames = newerOrUnseenGroupNames;

        bars = new ArrayList<>();

        applied = false;

        initElements();
        fillDialog();
    }

    private void initElements() {
        initBars();
    }

    private void initBars() {
        for (NewestOwnListVersionListEntry entry : newestOwnListVersionEntries) {
            GroupBar bar = createBar(entry);
            bars.add(bar);
        }
    }

    private GroupBar createBar(NewestOwnListVersionListEntry entry) {
        String groupName = entry.getGroupName();

        String groupDescription = determineGroupDescription(groupName);
        int version = entry.getVersion();
        boolean isNewOrActualised = newerOrUnseenGroupNames.contains(groupName);
        boolean showNewOrActualised = !newerOrUnseenGroupNames.isEmpty();

        boolean interested = isUserInterestedInGroup(groupName);

        GroupBar bar = new GroupBar(groupName, groupDescription, version, isNewOrActualised,
                showNewOrActualised, interested);
        return bar;
    }

    private String determineGroupDescription(String groupName) {
        OwnListGroup group = OwnListGroup.createByGroupName(groupName);
        return group.getDescription();
    }

    private boolean isUserInterestedInGroup(String groupName) {
        OwnListInterestAndVersionEntry entry =
                OwnListGroupsUpdater.findOwnListInterestAndVersionEntryByGroupname(groupName,
                        interestAndVersionEntries);
        if (OwnListGroupsUpdater.NOT_FOUND_INTEREST_AND_VERSION.equals(entry)) {
            return false;
        }
        else {
            return entry.isInterested();
        }
    }

    /** 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());
        GuiTools.createTitle(panel);

        panel.add(createIntroPart(), BorderLayout.NORTH); // TODO später vermutlich Scrollpane
        panel.add(createGroupsPart(), BorderLayout.CENTER);

        return panel;
    }

    private Component createIntroPart() {
        JPanel panel = new JPanel();
        panel.setLayout(new VerticalLayout(5, VerticalLayout.BOTH));

        JLabel label1 = new JLabel("Es gibt Neuerungen bei den Gruppen mit eigenen Listen.");
        GuiTools.biggerFont(label1, 7);
        panel.add(label1);

        JLabel label2 = new JLabel(HtmlTool.htmlify("In diesem Dialog kann sowohl das generelle "
                + "Interesse an den Gruppen geändert wie auch festgelegt werden, welche Gruppen "
                + "an eigenen Listen heruntergeladen und importiert werden sollen.",
                120));
        panel.add(label2);

        return panel;
    }

    private Component createGroupsPart() {
        JPanel panel = new JPanel();
        panel.setLayout(new VerticalLayout(5, VerticalLayout.BOTH));

        for (GroupBar bar : bars) {
            panel.add(bar.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() {
        JButton button = new JButton("Abbrechen");
        button.addActionListener(e -> closeDialog());
        return button;
    }

    private Component createOKButton() {
        JButton button = new JButton("OK");
        button.addActionListener(e -> apply());
        return button;
    }

    private void apply() {
        applied = true;
        closeDialog();
    }

    /** Gibt an, ob der Dialog mit OK bestätigt wurde. */
    public boolean isApplied() {
        return applied;
    }

    /** Gibt eine Liste mit den Namen der Gruppen zurück, an denen der Benutzer Interesse hat. */
    public List<String> getGroupNamesInterestedIn() {
        List<String> groupNamesInterestedIn = new ArrayList<>();

        for (GroupBar bar : bars) {
            if (bar.isInterested()) {
                groupNamesInterestedIn.add(bar.getGroupName());
            }
        }

        return groupNamesInterestedIn;
    }

    /**
     * Gibt eine Liste mit den Namen der Gruppen zurück, die der Benutzer heru7nterladen und
     * importieren will.
     */
    public List<String> getGroupNamesToDownload() {
        List<String> groupNamesToDownload = new ArrayList<>();

        for (GroupBar bar : bars) {
            if (bar.download()) {
                groupNamesToDownload.add(bar.getGroupName());
            }
        }

        return groupNamesToDownload;
    }

}
