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

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import de.duehl.basics.datetime.date.ImmutualDate;
import de.duehl.basics.text.Text;
import de.duehl.vocabulary.japanese.common.data.VocabularySortOrder;
import de.duehl.vocabulary.japanese.data.OwnList;
import de.duehl.vocabulary.japanese.io.ManualVocabularySortOrderFileIo;
import de.duehl.vocabulary.japanese.logic.ownlists.OwnLists;
import de.duehl.vocabulary.japanese.ui.components.bars.VocabularyBar;

/**
 * Diese Klasse sortiert die Liste der Bars zu den Vokabularien, welche in der grafischen
 * Oberfläche des Vokabel-Trainers dargestellt wird.
 *
 * @version 1.01     2024-11-22
 * @author Christian Dühl
 */

public class VocabularyBarSorter {

    /** Die Liste der Bars zu den Vokabularien. */
    private final List<VocabularyBar> vocabularyBars;

    /** Die gewünschte Reihenfolge in der die Bars zu den Vokabularien sortiert werden sollen. */
    private final VocabularySortOrder sortOrder;

    private List<String> manualSortedDescriptions;

    /**
     * Konstruktor.
     *
     * @param vocabularyBars
     *            Die Liste der Bars zu den Vokabularien.
     * @param sortOrder
     *            Die gewünschte Reihenfolge in der die Bars zu den Vokabularien sortiert werden
     *            sollen.
     */
    public VocabularyBarSorter(List<VocabularyBar> vocabularyBars, VocabularySortOrder sortOrder) {
        this.vocabularyBars = vocabularyBars;
        this.sortOrder = sortOrder;
        manualSortedDescriptions = new ArrayList<>();
    }

    /** Sortiert die Bars zu den Vokabularien. */
    public void sort() {
        readManualSortOrderIfNeeded();
        sortInternal();
    }

    private void readManualSortOrderIfNeeded() {
        if (sortOrder == VocabularySortOrder.MANUAL_SORT_ORDER) {
            if (isSortingOwnListsBars()) {
                List<String> names = OwnLists.readOwnListNames();
                List<String> descriptions = namesToDescriptions(names);
                manualSortedDescriptions = descriptions;

            }
            else {
                manualSortedDescriptions =
                        ManualVocabularySortOrderFileIo.readManualVocabularyDescriptionsOrder();
            }
        }
    }

    private List<String> namesToDescriptions(List<String> names) {
        List<String> descriptions = new ArrayList<>();

        for (String name : names) {
            String description = OwnList.createDescriptionFromName(name);
            descriptions.add(description);
        }

        return descriptions;
    }

    private boolean isSortingOwnListsBars() {
        VocabularyBar firstBar = vocabularyBars.get(0);
        return firstBar.isOwnListsBar();
    }

    private void sortInternal() {
        Collections.sort(vocabularyBars, new Comparator<VocabularyBar>() {
            @Override
            public int compare(VocabularyBar bar1, VocabularyBar bar2) {
                return compareInternal(bar1, bar2);
            }
        });
    }

    /** Gibt die Reihenfolge zweier Bars zu Vokabularien abhängig von der Sortierreihenfolge an. */
    private int compareInternal(VocabularyBar bar1, VocabularyBar bar2) {
        switch (sortOrder) {
            case ALPHABETICAL:
                return compareAlphabetical(bar1, bar2);
            case REVERSED_ALPHABETICAL:
                return -compareAlphabetical(bar1, bar2);
            case OLDEST_VOCABULARIES_FIRST:
                return compareNewestFirst(bar1, bar2);
            case NEWEST_VOCABULARIES_FIRST:
                return -compareNewestFirst(bar1, bar2);
            case MANUAL_SORT_ORDER:
                return compareByManualOrder(bar1, bar2);
            default:
                throw new RuntimeException("Unbekannte Sortierreihenfolge '" + sortOrder + ".");
        }
    }

    private int compareAlphabetical(VocabularyBar bar1, VocabularyBar bar2) {
        String description1 = bar1.getVocabulary().getDescription();
        String description2 = bar2.getVocabulary().getDescription();

        return Text.compareStringsBetter(description1, description2);
        //return description1.compareTo(description2);
    }

    private int compareNewestFirst(VocabularyBar bar1, VocabularyBar bar2) {
        ImmutualDate firstSeenDate1 = bar1.getVocabulary().getFirstSeenDate();
        ImmutualDate firstSeenDate2 = bar2.getVocabulary().getFirstSeenDate();

        if (firstSeenDate1.after(firstSeenDate2)) {
            return 1;
        }
        else if (firstSeenDate1.before(firstSeenDate2)) {
            return -1;
        }
        else {
            return compareAlphabetical(bar1, bar2);
        }
    }

    private int compareByManualOrder(VocabularyBar bar1, VocabularyBar bar2) {
        String description1 = bar1.getVocabulary().getDescription();
        String description2 = bar2.getVocabulary().getDescription();
        if (manualSortedDescriptions.contains(description1)
                && manualSortedDescriptions.contains(description2)) {
            int index1 = manualSortedDescriptions.indexOf(description1);
            int index2 = manualSortedDescriptions.indexOf(description2);
            return index1 - index2;
        }
        else if (manualSortedDescriptions.contains(description1)) {
            return -1;
        }
        else if (manualSortedDescriptions.contains(description2)) {
            return 1;
        }
        else {
            return 0;
        }
    }

}
