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

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.SwingConstants;

import de.duehl.swing.persistance.SwingSessionManagerHelper;
import de.duehl.swing.ui.GuiTools;
import de.duehl.swing.ui.components.selections.StringSelection;
import de.duehl.swing.ui.components.selections.tools.SelectionsHelper;
import de.duehl.swing.ui.dialogs.base.ModalDialogBase;
import de.duehl.swing.ui.layout.VerticalLayout;
import de.duehl.swing.ui.move.data.MovingGui;
import de.duehl.swing.ui.pages.DatasetsOnPages;
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.io.OwnListReader;
import de.duehl.vocabulary.japanese.logic.ownlists.OwnLists;
import de.duehl.vocabulary.japanese.tools.VocabularyTools;
import de.duehl.vocabulary.japanese.ui.components.bars.VocableBar;
import de.duehl.vocabulary.japanese.ui.data.FumikoUiObjects;
import de.duehl.vocabulary.japanese.ui.dialog.options.OptionsDialog;
import de.duehl.vocabulary.japanese.ui.dialog.vocables.detail.VocableWithInternaDialog;
import de.duehl.vocabulary.japanese.ui.filter.VocableFilterPanel;

/**
 * Diese Klasse stellt den Dialog dar, in welcher eine eigene Listen von Vokabeln bearbeitet wird.
 *
 * @version 1.01     2025-11-27
 * @author Christian Dühl
 */

public class OwnListEditorDialog extends ModalDialogBase implements MovingGui<Vocable> {

    private static final Dimension DIALOG_DIMENSION = new Dimension(1750, 900);


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

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

    /** Die zu bearbeitende Vokabelliste. */
    private final OwnList ownList;

    /** Die Vokabeln der Liste. */
    private final List<Vocable> vocables;

    /** Das Element mit den Filterkriterien für die Vokabeln. */
    private final VocableFilterPanel vocableFilter;

    /** Die Darstellung des Namens der Liste. */
    private final StringSelection nameSelection;

    /** Zeigt die Vokabeln an, die den Filterkriterien entsprechen. */
    private final DatasetsOnPages<Vocable> pages;

    /** Der Panel mit den Vokabeln der Liste, die wir hier bearbeiten. */
    private final JPanel vocablesOfListPanel;

    /** Die ScrollPane um den Panel mit den Vokabeln der Liste, die wir hier bearbeiten. */
    private final JScrollPane vocablesOfListScroll;

    /** Das Verzeichnis der Vokabel-Bars nach den Vokabeln. */
    private final Map<Vocable, VocableBar> barByVocable;

    /** Der Button zum Anzeigen oder Verstecken der Buttons zum Bewegen der Bars der Liste. */
    private final JButton toggleMoveButtonsButton;

    /** Gibt an, ob die Buttons zum Verschieben auf den Bars der Liste angezeigt werden. */
    private boolean showMoveButtonsOnBars;

    /** Die Liste der Kategorien eigener Listen, wird hier ggf. erweitert. */
    private final List<String> ownListCategories;

    /** Die Liste der Unterkategorien eigener Listen, wird hier ggf. erweitert. */
    private final List<String> ownListSubCategories;

    /** Die Combobox für die Kategorie der eigenen Liste, die man bearbeitet. */
    private final JComboBox<String> ownListCategoryComboBox;

    /** Die Combobox für die Unterkategorie der eigenen Liste, die man bearbeitet. */
    private final JComboBox<String> ownListSubCategoryComboBox;

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

    /**
     * Konstruktor.
     *
     * @param dataStructures
     *            Die Datenstrukturen des Vokabeltrainers.
     * @param uiObjects
     *            Die häufig verwendeten Funktionen der grafischen Oberfläche des Vokabeltrainers.
     * @param ownList
     *            Die zu bearbeitende Vokabelliste.
     */
    public OwnListEditorDialog(OwnList ownList, FumikoDataStructures dataStructures,
            FumikoUiObjects uiObjects) {
        super(uiObjects.getGuiLocation(), uiObjects.getProgramImage(),
                createTitle(ownList.getName()), createDimension(dataStructures.getOptions()));
        addClosingWindowListener(() -> quit());

        this.ownList = ownList;
        this.dataStructures = dataStructures;
        this.uiObjects = uiObjects;

        barByVocable = new HashMap<>();

        vocables = new ArrayList<>();
        vocables.addAll(ownList.getVocables());

        nameSelection = new StringSelection("Name der Liste");
        nameSelection.setText(ownList.getName());

        vocableFilter = new VocableFilterPanel(dataStructures,
                filteredVocablesList -> reactOnFilteredVocables(filteredVocablesList));

        toggleMoveButtonsButton = new JButton();
        showMoveButtonsOnBars = false;

        ownListCategories = new ArrayList<>();
        ownListSubCategories = new ArrayList<>();
        ownListCategoryComboBox = new JComboBox<>();
        ownListSubCategoryComboBox = new JComboBox<>();

        Options options = dataStructures.getOptions();
        int numberOfDatasetsPerSide =  options.getNumberOfDatasetsPerPageOfOwnListEditor();
        int numberOfColumns = options.getNumberOfColumnsOfOwnListEditor();
        pages = new DatasetsOnPages<>(vocableFilter.createFilteredVocablesList(),
                vocable -> createDatasetUi(vocable), numberOfDatasetsPerSide, numberOfColumns);

        Point location = options.getLocationOfOwnListEditor();
        if (!location.equals(SwingSessionManagerHelper.NOT_INITIALISED_POINT)) {
            setLocation(location);
        }

        vocablesOfListPanel = new JPanel();
        vocablesOfListScroll = GuiTools.createScrollPane(vocablesOfListPanel);

        applied = false;

        init();
        filterVocables();
        showVocabelsInList();
        fillDialog();
    }

    private static String createTitle(String name) {
        return "Bearbeiten der Vokabelliste '" + name + "'";
    }

    private void setTitle() {
        setTitle(createTitle(nameSelection.getTrimmedText()));
    }

    private static Dimension createDimension(Options options) {
        Dimension size = options.getSizeOfOwnListEditor();
        if (size.equals(SwingSessionManagerHelper.NOT_INITIALISED_DIMENSION)) {
            return DIALOG_DIMENSION;
        }
        else {
            return size;
        }
    }

    /** Erstellt aus dem übergebenen Datensatz die Anzeige für die Gui. */
    private Component createDatasetUi(Vocable vocable) {
        VocableBar bar = new VocableBar(vocable, () -> addVocable(vocable), this);
        bar.useButtonAsAddVocableToList();
        if (vocables.contains(vocable)) {
            bar.disable();
        }
        bar.showExtraDetailButtonOnTheLeft(() -> showDetails(vocable));
        bar.createGui();
        barByVocable.put(vocable, bar);
        return bar.getPanel();
    }

    private void showDetails(Vocable vocable) {
        VocableWithInternaDialog dialog = new VocableWithInternaDialog(vocable, dataStructures,
                uiObjects, getLocation());
        dialog.setVisible(true);
    }

    private void addVocable(Vocable vocable) {
        if (!vocables.contains(vocable)) {
            addNotContainedVocable(vocable);
        }
    }

    private void addNotContainedVocable(Vocable vocable) {
        vocables.add(vocable);
        showVocabelsInList();

        VocableBar bar = barByVocable.get(vocable);
        bar.disable();
        vocableFilter.requestFocusInSearchFieldLater();

        /*
         * Falls in der Liste enthaltene Vokabeln links ausgeblendet werden, müssen wir neu
         * filtern:
         */
        Options options = dataStructures.getOptions();
        if (options.isHideVocablesFromListInSearchAreaInOwnListEditor()) {
            int rememberedPageNumer = pages.getActualPageNumber();
            filterVocables();
            pages.showPage(rememberedPageNumer);
        }
    }

    private void init() {
        initVocableFilter();
        initOwnListCategories();
        initOwnListSubCategories();
        initComboBoxes();
        fillComboBoxes();
        initVocablesOfListPanel();
        initNameSelection();
        initToggleButton();
        setRightShowAndHideButtonTexts();
        setTitle();
    }

    private void initVocableFilter() {
        vocableFilter.arrangeForListEditDialog();
    }

    private void initOwnListCategories() {
        OwnLists ownLists = dataStructures.getOwnLists();
        ownListCategories.addAll(VocabularyTools.determineCategories(ownLists.getOwnLists()));
    }

    private void initOwnListSubCategories() {
        /*
         * TODO: Das ist nicht abhängig von der Kategorie!
         * Falls man das möchte, siehe OwnListListSelector.
         */
        OwnLists ownLists = dataStructures.getOwnLists();
        for (OwnList ownList : ownLists.getOwnLists()) {
            String subCategory = ownList.getSubCategory();
            if (!ownListSubCategories.contains(subCategory)) {
                ownListSubCategories.add(subCategory);
            }
        }
        Collections.sort(ownListSubCategories);
    }

    private void initComboBoxes() {
        ownListCategoryComboBox.setAlignmentX(JLabel.CENTER);
        ownListCategoryComboBox.setAlignmentY(JLabel.CENTER);
        ((JLabel) ownListCategoryComboBox.getRenderer()).setHorizontalAlignment(
                SwingConstants.CENTER);

        ownListSubCategoryComboBox.setAlignmentX(JLabel.CENTER);
        ownListSubCategoryComboBox.setAlignmentY(JLabel.CENTER);
        ((JLabel) ownListSubCategoryComboBox.getRenderer()).setHorizontalAlignment(
                SwingConstants.CENTER);
    }

    private void fillComboBoxes() {
        fillOwnListCategoryComboBox();
        ownListCategoryComboBox.setSelectedItem(ownList.getCategory());
        fillOwnListSubCategoryComboBox();
        ownListSubCategoryComboBox.setSelectedItem(ownList.getSubCategory());
    }

    private void fillOwnListCategoryComboBox() {
        ownListCategoryComboBox.removeAllItems();

        for (String category : ownListCategories) {
            ownListCategoryComboBox.addItem(category);
        }
    }

    private void fillOwnListSubCategoryComboBox() {
        /*
         * TODO: Das ist nicht abhängig von der Kategorie!
         * Falls man das möchte, siehe OwnListListSelector.
         */
        ownListSubCategoryComboBox.removeAllItems();
        for (String subCategory : ownListSubCategories) {
            ownListSubCategoryComboBox.addItem(subCategory);
        }
    }

    private void initVocablesOfListPanel() {
        vocablesOfListPanel.setLayout(new VerticalLayout(3, VerticalLayout.BOTH));
    }

    private void initNameSelection() {
        SelectionsHelper.initSelectionAsEditor(nameSelection);
    }

    private void initToggleButton() {
        toggleMoveButtonsButton.addActionListener(e -> toggleMoveButtons());
    }

    private void toggleMoveButtons() {
        showMoveButtonsOnBars = !showMoveButtonsOnBars;
        setRightShowAndHideButtonTexts();
        showVocabelsInList();
    }

    private void setRightShowAndHideButtonTexts() {
        String show = "einblenden";
        String hide = "ausblenden";
        String moveShowOrHide = showMoveButtonsOnBars ? hide : show;

        toggleMoveButtonsButton.setText("<html><center>"
                + "Die Buttons zum Verschieben"
                + "<br>"
                + moveShowOrHide
                + "</center></html>");
    }

    private void showVocabelsInList() {
        vocablesOfListPanel.removeAll();

        for (Vocable vocable : vocables) {
            VocableBar bar = new VocableBar(vocable, () -> deleteFromList(vocable), this);
            bar.useButtonAsDeletion();
            bar.showMoveButtonsOnBars(showMoveButtonsOnBars);
            bar.showExtraDetailButtonOnTheLeft(() -> showDetails(vocable));
            bar.createGui();
            vocablesOfListPanel.add(bar.getPanel());
        }

        vocablesOfListPanel.repaint();
        vocablesOfListPanel.validate();
        vocablesOfListPanel.invalidate();

        vocablesOfListScroll.repaint();
        vocablesOfListScroll.validate();
        vocablesOfListScroll.invalidate();
    }

    private void deleteFromList(Vocable vocable) {
        vocables.remove(vocable);
        showVocabelsInList();

        /*
         * Da die Vokabel nicht zwingend auf den momentan bereits vom Benutzer angeschauten Seiten
         * vorhanden sein muss und damit nicht zwingend eine Bar dazu existieren muss, muss
         * abgefragt werden, ob wir die Bar dazu kennen:
         */
        if (barByVocable.containsKey(vocable)) {
            VocableBar bar = barByVocable.get(vocable);
            bar.enable();
        }
        vocableFilter.requestFocusInSearchFieldLater();

        /*
         * Vielleicht haben wir etwas gelöscht, das links dann wieder oder anders angezeigt werden
         * sollte. Daher:
         */
        Options options = dataStructures.getOptions();
        if (options.isHideVocablesFromListInSearchAreaInOwnListEditor()) {
            filterVocables();

            int rememberedPageNumer = pages.getActualPageNumber();
            filterVocables();
            pages.showPage(rememberedPageNumer);
        }
    }

    private void filterVocables() {
        List<Vocable> filteredVocablesList = vocableFilter.createFilteredVocablesList();
        reactOnFilteredVocables(filteredVocablesList);
    }

    private void reactOnFilteredVocables(List<Vocable> filteredVocablesList) {
        Options options = dataStructures.getOptions();
        List<Vocable> cleanedFilteredVocablesList;
        if (options.isHideVocablesFromListInSearchAreaInOwnListEditor()) {
            cleanedFilteredVocablesList =
                    createCleanedFilteredVocablesList(filteredVocablesList);
        }
        else {
            cleanedFilteredVocablesList = filteredVocablesList;
        }

        if (cleanedFilteredVocablesList.isEmpty()) {
            GuiTools.informUser(getWindowAsComponent(), "Keine Vokabeln gefunden",
                    "Die Suchkriterien führen zu einer leeren Liste von Vokabeln, daher wird "
                    + "diese nicht angezeigt.");
        }
        else {
            pages.setOtherDatasets(cleanedFilteredVocablesList);
        }
    }

    private List<Vocable> createCleanedFilteredVocablesList(List<Vocable> filteredVocablesList) {
        List<Vocable> cleaned = new ArrayList<>();

        for (Vocable vocable : filteredVocablesList) {
            if (!vocables.contains(vocable)) {
                cleaned.add(vocable);
            }
        }

        return cleaned;
    }

    @Override
    protected void populateDialog() {
        add(createVocableSelectionAndListPart(), BorderLayout.CENTER);
        add(createButtonPart(), BorderLayout.SOUTH);

        pages.addOwnExtension(createPagesExtensionPart());
    }

    private Component createVocableSelectionAndListPart() {
        Options options = dataStructures.getOptions();

        if (options.isUseSplitPaneInOwnListEditor()) {
            return createVocableSelectionAndListPartWithSplitPane();
        }
        else {
            return createVocableSelectionAndListPartWithFixSize();
        }
    }

    private Component createVocableSelectionAndListPartWithSplitPane() {
        JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
                                            //JSplitPane.VERTICAL_SPLIT,
                createVocableSelectionPart(),
                createListPart());
        splitPane.setDividerLocation(1000);
        return splitPane;
    }

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

        panel.add(createVocableSelectionPart(), BorderLayout.CENTER);
        panel.add(createListPart(), BorderLayout.EAST);

        return panel;
    }

    private Component createVocableSelectionPart() {
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        GuiTools.createTitle("Auswahl von Vokabeln", panel);

        panel.add(vocableFilter.getPanel(), BorderLayout.NORTH);
        panel.add(pages.getPanel(), BorderLayout.CENTER);

        return panel;
    }

    private Component createListPart() {
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        GuiTools.createTitle("Die Vokabelliste", panel);

        panel.add(createOwnListUpperPart(), BorderLayout.NORTH);
        panel.add(vocablesOfListScroll, BorderLayout.CENTER);

        return panel;
    }

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

        panel.add(createLeftOwnListUpperPart(), BorderLayout.WEST);
        panel.add(createRightOwnListUpperPart(), BorderLayout.EAST);

        return panel;
    }

    private Component createLeftOwnListUpperPart() {
        JPanel panel = new JPanel();
        panel.setLayout(new VerticalLayout(3, VerticalLayout.BOTH));

        panel.add(nameSelection.getPanel());
        panel.add(createCategoryAndSubCategoryPart());

        return panel;
    }

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

        panel.add(createCategoryAndSubCategoryComboBoxesPart(), BorderLayout.CENTER);
        panel.add(createEnterNewCategoryAndSubCategoryPart(), BorderLayout.EAST);

        return panel;
    }

    private Component createCategoryAndSubCategoryComboBoxesPart() {
        JPanel panel = new JPanel();
        panel.setLayout(new GridLayout(0, 1, 2, 2));
        panel.setPreferredSize(new Dimension(300, 0));

        panel.add(ownListCategoryComboBox);
        panel.add(ownListSubCategoryComboBox);

        return panel;
    }

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

        panel.add(createNewCategoryButton());
        panel.add(createNewSubCategoryButton());

        return panel;
    }

    private Component createNewCategoryButton() {
        JButton button = new JButton("neue Kategorie hinzufügen");
        button.addActionListener(e -> createNewOwnListCategory());
        return button;
    }

    private void createNewOwnListCategory() {
        String actualCategory = (String)  ownListCategoryComboBox.getSelectedItem();
        String newCategory = GuiTools.askUserToEnterAStringValue(getWindowAsComponent(),
                "Bitte geben sie die neue Kategorie ein",
                "Bitte geben sie die neue Kategorie ein.", actualCategory).strip();
        if (!newCategory.isBlank()) {
            if (!ownListCategories.contains(newCategory)) {
                ownListCategories.add(newCategory);
                fillOwnListCategoryComboBox();
            }
            ownListCategoryComboBox.setSelectedItem(newCategory);
        }
    }

    private Component createNewSubCategoryButton() {
        JButton button = new JButton("neue Unterkategorie hinzufügen");
        button.addActionListener(e -> createNewOwnListSubCategory());
        return button;
    }

    private void createNewOwnListSubCategory() {
        String actualSubCategory = (String) ownListSubCategoryComboBox.getSelectedItem();
        String newSubCategory = GuiTools.askUserToEnterAStringValue(getWindowAsComponent(),
                "Bitte geben sie die neue Unterkategorie ein",
                "Bitte geben sie die neue Unterkategorie ein.", actualSubCategory).strip();
        if (!newSubCategory.isBlank()) {
            if (!ownListSubCategories.contains(newSubCategory)) {
                ownListSubCategories.add(newSubCategory);
                fillOwnListSubCategoryComboBox();
            }
            ownListSubCategoryComboBox.setSelectedItem(newSubCategory);
        }
    }

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

        panel.add(toggleMoveButtonsButton, BorderLayout.EAST);

        return panel;
    }

    private Component createButtonPart() {
        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 -> quit());
        return button;
    }

    private void quit() {
        storeListOptions();
        closeDialog();
    }

    private Component createOkButton() {
        JButton button = new JButton(" Ok ");
        GuiTools.boldFont(button);
        GuiTools.biggerFont(button, 5);
        button.addActionListener(e -> apply());
        return button;
    }

    private void apply() {
        String oldName = ownList.getName();
        String newName = nameSelection.getTrimmedText();
        OwnLists ownLists = dataStructures.getOwnLists();
        if (!newName.equals(oldName)) {
            if (newName.isBlank() || !ownLists.nameCheckOk(newName)) {
                GuiTools.informUser(getWindowAsComponent(), "Die Liste wurde nicht umbenannt",
                        "Der eingegebene Name '" + newName + "' ist bereits vorhanden oder "
                                + "resultiert in einem leeren Dateinamen.\n"
                                + "Die Liste wurde daher nicht umbenannt. "
                                + "Die restlichen Änderungen werden aber übernommen.");
                newName = oldName;
            }
            else if (!newName.equals(oldName)) {
                ownLists.renameListFile(oldName, newName);
                ownList.setName(newName);
            }
        }

        String category = (String) ownListCategoryComboBox.getSelectedItem();
        if (category.isBlank()) {
            category = OwnListReader.DEFAULT_OWN_LIST_CATEGORY;
        }
        ownList.setCategory(category);

        String subCategory = (String) ownListSubCategoryComboBox.getSelectedItem();
        if (subCategory.isBlank()) {
            subCategory = OwnListReader.DEFAULT_OWN_LIST_SUB_CATEGORY;
        }
        ownList.setSubCategory(subCategory);

        List<Vocable> vocableListOfOwnList = ownList.getVocables();
        vocableListOfOwnList.clear();
        vocableListOfOwnList.addAll(vocables);

        ownLists.storeOwnLists();
        applied = true;
        quit();

        storeLastUsedOwnList();
    }

    private void storeLastUsedOwnList() {
        Options options = dataStructures.getOptions();
        HistoricalOwnListPersistanceDataList historicalOwnLists = options.getHistoricalOwnLists();
        historicalOwnLists.addOwnListData(ownList.toOwnListPersistanceData());
    }

    private void storeListOptions() {
        int numberOfDatasetsPerSide = pages.getNumberOfDatasetsPerPage();
        int numberOfColumns = pages.getNumberOfColumns();

        Options options = dataStructures.getOptions();
        options.setNumberOfDatasetsPerPageOfOwnListEditor(numberOfDatasetsPerSide);
        options.setNumberOfColumnsOfOwnListEditor(numberOfColumns);

        Point location = getLocation();
        Dimension size = getSizeOfWindow();
        options.setLocationOfOwnListEditor(location);
        options.setSizeOfOwnListEditor(size);

        OwnLists ownLists = dataStructures.getOwnLists();
        ownLists.saveOptions();
    }

    private Component createPagesExtensionPart() {
        JPanel panel = new JPanel();
        panel.setLayout(new FlowLayout(FlowLayout.CENTER, 3, 3));

        panel.add(createOptionsButton());
        panel.add(createSelectAllButton());
        panel.add(createDeselectAllButton());
        panel.add(createAddSelectedButton());
        panel.add(createAddAllButton());

        return panel;
    }

    private Component createOptionsButton() {
        JButton button = new JButton("Options");
        button.addActionListener(e -> showOptions());
        return button;
    }

    private void showOptions() {
        OptionsDialog dialog = new OptionsDialog(dataStructures.getOptions(), getLocation(),
                uiObjects);
        dialog.showOnlyOwnListDialogOptions();
        dialog.populate();
        dialog.setVisible(true);
        if (dialog.wasApplied()) {
            runAfterChangingOptions();
        }
    }

    private void runAfterChangingOptions() {
        OwnLists ownLists = dataStructures.getOwnLists();
        ownLists.saveOptions();
        filterVocables();
    }

    private Component createSelectAllButton() {
        JButton button = new JButton("select all");
        button.addActionListener(e -> selectAll());
        return button;
    }

    private void selectAll() {
        boolean selected = true;
        setBarsOnActualPageSelected(selected);
    }

    private Component createDeselectAllButton() {
        JButton button = new JButton("deselect all");
        button.addActionListener(e -> deselectAll());
        return button;
    }

    private void deselectAll() {
        boolean selected = false;
        setBarsOnActualPageSelected(selected);
    }

    private void setBarsOnActualPageSelected(boolean selected) {
        for (Vocable vocable : pages.getDatasetsFromActualPage()) {
            VocableBar bar = barByVocable.get(vocable);
            bar.setSelected(selected);
        }
    }

    private Component createAddSelectedButton() {
        JButton button = new JButton("add selected");
        button.addActionListener(e -> addSelected());
        return button;
    }

    private void addSelected() {
        List<VocableBar> addedBars = new ArrayList<>();

        for (Vocable vocable : pages.getDatasetsFromActualPage()) {
            VocableBar bar = barByVocable.get(vocable);
            if (bar.isSelected()) {
                addVocable(vocable);
                addedBars.add(bar);
            }
        }

        disableAddedBars(addedBars);
    }

    private Component createAddAllButton() {
        JButton button = new JButton("add all from active Page");
        button.addActionListener(e -> addAll());
        return button;
    }

    private void addAll() {
        List<VocableBar> addedBars = new ArrayList<>();

        for (Vocable vocable : pages.getDatasetsFromActualPage()) {
            addVocable(vocable);
            VocableBar bar = barByVocable.get(vocable);
            addedBars.add(bar);
        }

        disableAddedBars(addedBars);
    }

    private void disableAddedBars(List<VocableBar> addedBars) {
        for (VocableBar bar : addedBars) {
            bar.setSelected(false);
            bar.disable();
        }
    }

    /** Verschiebt die übergebene Bar einer Vokabel an die erste Stelle. */
    @Override
    public void moveBarToFirst(Vocable vocable) {
        int index = vocables.indexOf(vocable);
        vocables.remove(index);
        vocables.add(0, vocable);
        showVocabelsInList();
    }

    /** Verschiebt die übergebene Bar einer Vokabel nach oben. */
    @Override
    public void moveBarUp(Vocable vocable) {
        int index = vocables.indexOf(vocable);
        vocables.remove(index);
        vocables.add(index - 1, vocable);
        showVocabelsInList();
    }

    /** Verschiebt die übergebene Bar einer Vokabel nach unten. */
    @Override
    public void moveBarDown(Vocable vocable) {
        int index = vocables.indexOf(vocable);
        vocables.remove(index);
        vocables.add(index + 1, vocable);
        showVocabelsInList();
    }

    /** Verschiebt die übergebene Bar einer Vokabel an die letzte Stelle. */
    @Override
    public void moveBarToLast(Vocable vocable) {
        int index = vocables.indexOf(vocable);
        vocables.remove(index);
        vocables.add(vocable);
        showVocabelsInList();
    }

    /** Gibt an, ob die übergebene Bar einer Vokabel nach oben bewegt werden kann. */
    @Override
    public boolean canBarMoveUp(Vocable vocable) {
        int index = vocables.indexOf(vocable);
        return index > 0;
    }

    /** Gibt an, ob die übergebene Bar einer Vokabel nach unten bewegt werden kann. */
    @Override
    public boolean canBarMoveDown(Vocable vocable) {
        int index = vocables.indexOf(vocable);
        return index < vocables.size() - 1;
    }

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

}
