package de.duehl.vocabulary.japanese.ui.listcommander;

import java.awt.Component;
import java.awt.GridLayout;

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

import de.duehl.twosidecommander.ui.list.ListDisplayer;
import de.duehl.twosidecommander.ui.TwoSideCommander;
import de.duehl.vocabulary.japanese.common.persistence.Options;
import de.duehl.vocabulary.japanese.common.persistence.data.HistoricalOwnListPersistanceDataList;
import de.duehl.vocabulary.japanese.data.FumikoDataStructures;
import de.duehl.vocabulary.japanese.data.OwnList;
import de.duehl.vocabulary.japanese.data.Vocable;
import de.duehl.vocabulary.japanese.logic.ownlists.OwnLists;
import de.duehl.vocabulary.japanese.ui.VocabularyTrainerGui;
import de.duehl.vocabulary.japanese.ui.data.FumikoUiObjects;
import de.duehl.vocabulary.japanese.ui.dialog.vocables.detail.VocableWithInternaDialog;
import de.duehl.vocabulary.japanese.ui.listcommander.list.OwnListDisplayer;
import de.duehl.vocabulary.japanese.ui.listcommander.selector.OwnListSelector;

/**
 * Diese Klasse stellt den Listen-Commander dar, mit dem sich zwischen zwei eigenen Listen Vokabeln
 * kopieren, verschieben oder löschen lassen.
 *
 * @version 1.01     2025-11-29
 * @author Christian Dühl
 */

public class OwnListCommander extends TwoSideCommander {

    /** Die grafische Oberfläche des Vokabel-Trainers. */
    private final VocabularyTrainerGui gui;

    /** Die Datenstrukturen des Vokabeltrainers. */
    private final FumikoDataStructures dataStructures;

    /** Die häufig verwendeten Funktionen der grafischen Oberfläche des Vokabeltrainers. */
    private final FumikoUiObjects uiObjects;

    /** Der linke Selector. */
    private OwnListSelector leftSelector;

    /** Der rechte Selector. */
    private OwnListSelector rightSelector;

    /** Der linke Displayer. */
    private OwnListDisplayer leftListDisplayer;

    /** Der rechte Displayer. */
    private OwnListDisplayer rightListDisplayer;

    /**
     * Konstruktor.
     *
     * @param gui
     *            Die grafische Oberfläche des Vokabel-Trainers.
     * @param dataStructures
     *            Die Datenstrukturen des Vokabeltrainers.
     * @param uiObjects
     *            Die häufig verwendeten Funktionen der grafischen Oberfläche des Vokabeltrainers.
     */
    public OwnListCommander(VocabularyTrainerGui gui, FumikoDataStructures dataStructures,
            FumikoUiObjects uiObjects) {
        super("Listen-Commander", gui.getLocation(), uiObjects.getProgramImage());
        this.gui = gui;
        this.dataStructures = dataStructures;
        this.uiObjects = uiObjects;
    }

    /** Initialisiert und startet den Listen-Commander. */
    public void start() {
        createAndInitListDisplayer();
        createAndSetOwnListSelectors();
        enableToggableMovingButtons();
        createAndSetMiddleBarButtons();
        createGui();
        setOwnKeyBindings();
        setVisible(true);
    }

    private void createAndInitListDisplayer() {
        leftListDisplayer = new OwnListDisplayer(this);
        setLeftListDisplayer(leftListDisplayer);

        rightListDisplayer = new OwnListDisplayer(this);
        setRightListDisplayer(rightListDisplayer);
    }

    private void createAndSetOwnListSelectors() {
        Options options = dataStructures.getOptions();
        leftSelector = new OwnListSelector(dataStructures, uiObjects,
                options.getHistoricalLeftOwnListsInListCommander(),
                ownList -> leftOwnListChanged(ownList),
                () -> getLocation());
        leftSelector.createSelector();
        setLeftListSelector(leftSelector);

        rightSelector = new OwnListSelector(dataStructures, uiObjects,
                options.getHistoricalRightOwnListsInListCommander(),
                ownList -> rightOwnListChanged(ownList),
                () -> getLocation());
        rightSelector.createSelector();
        setRightListSelector(rightSelector);
    }

    private void leftOwnListChanged(OwnList ownList) {
        ownListChanged(leftListDisplayer, ownList);
        Options options = dataStructures.getOptions();
        HistoricalOwnListPersistanceDataList historicalLeftLists =
                options.getHistoricalLeftOwnListsInListCommander();
        historicalLeftLists.addOwnListData(ownList.toOwnListPersistanceData());
    }

    private void rightOwnListChanged(OwnList ownList) {
        ownListChanged(rightListDisplayer, ownList);
        Options options = dataStructures.getOptions();
        HistoricalOwnListPersistanceDataList historicalRightLists =
                options.getHistoricalRightOwnListsInListCommander();
        historicalRightLists.addOwnListData(ownList.toOwnListPersistanceData());
    }

    private void ownListChanged(OwnListDisplayer listDisplayer, OwnList ownList) {
        listDisplayer.setOwnList(ownList);
        listDisplayer.readAndShowList();
    }

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

        panel.add(createEditActiveListButton());
        panel.add(createNewListButton());

        setMiddleButtonBar(panel);
    }

    private Component createEditActiveListButton() {
        JButton button = new JButton("<html><center>"
                + "F3 - Aktive Liste"
                + "<br>"
                + "bearbeiten"
                + "</center></html>");
        button.addActionListener(e -> editActiveList());
        return button;
    }

    private void editActiveList() {
        ListDisplayer activeListDisplayer = getActiveListDisplayer();
        OwnListDisplayer activeOwnListDisplayer =
                OwnListDisplayer.castListDisplayer(activeListDisplayer);
        OwnList ownList = activeOwnListDisplayer.getOwnList();
        boolean applied = gui.editOwnList(ownList);
        if (applied) {
            //storeOwnLists(); das macht editOwnList() schon, wenn mit ok bestätigt wurde.
            activeListDisplayer.readAndShowList();
            leftSelector.refillComboboxes();
            rightSelector.refillComboboxes();
        }
    }

    private Component createNewListButton() {
        JButton button = new JButton("<html><center>"
                + "F4 - Neue Liste"
                + "<br>"
                + "anlegen"
                + "</center></html>");

        button.addActionListener(e -> createNewList());
        return button;
    }

    private void createNewList() {
        boolean created = gui.createNewOwnList();
        if (created) {
            leftSelector.refillComboboxes();
            rightSelector.refillComboboxes();
        }
    }

    private void setOwnKeyBindings() {
        setKeyBindingF3(() -> editActiveList());
        setKeyBindingF4(() -> createNewList());
    }

    /** Zeigt den Detail-Dialog zu einer Vokabel an. */
    public void showVocableDetails(Vocable vocable) {
        VocableWithInternaDialog dialog = new VocableWithInternaDialog(vocable, dataStructures,
                uiObjects, getLocation());
        dialog.setVisible(true);
    }

    /** Speichert die Listen im im benutzerspezifische Verzeichnis ab. */
    public void storeOwnLists() {
        OwnLists ownLists = dataStructures.getOwnLists();
        ownLists.storeOwnLists();
    }

}
