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

import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import de.duehl.vocabulary.japanese.data.Vocable;

/**
 * Diese Klasse sortiert eine Liste von nach bestimmten Suchkriterien gefundenen Vokabeln anhand
 * eines Suchbegriffs nach Relevanz.
 *
 * @version 1.01     2024-11-20
 * @author Christian Dühl
 */

public class VocableSorter {

    /**
     * Die Liste der gefundenen Vokabeln, die den Suchkriterien entsprechen.
     *
     * Diese Liste wird hier sortiert.
     */
    private final List<Vocable> vocables;

    /** Der Suchbegriff, nach dem die gefundenen Vokabeln nach Relevanz sortiert werden sollen. */
    private final String search;

    /**
     * Das Verzeichnis der Bewertungen der Relevanz nach den Vokabeln.
     *
     * Eine höhere Relevanz drückt sich in einer kleineren Zahl aus.
     */
    private Map<Vocable, Integer> relevanceWeighting;

    /**
     * Konstruktor.
     *
     * @param vocablesDie
     *            Die Liste der gefundenen Vokabeln, die den Suchkriterien entsprechen. Diese Liste
     *            wird hier sortiert.
     * @param search
     *            Der Suchbegriff, nach dem die gefundenen Vokabeln nach Relevanz sortiert werden
     *            sollen.
     */
    public VocableSorter(List<Vocable> vocables, String search) {
        this.vocables = vocables;
        this.search = search;
    }

    /** Führt die Sortierung durch. */
    public void sort() {
        if (vocables.size() > 1 && !search.isBlank()) {
            reallySort();
        }
    }

    private void reallySort() {
        createRelevanceWeighting();
        sortByRelevanceWeighting();
    }

    private void createRelevanceWeighting() {
        relevanceWeighting = new HashMap<>();
        for (Vocable vocable : vocables) {
            int weighting = calculateRelevanceWeighting(vocable);
            relevanceWeighting.put(vocable, weighting);
        }
    }

    private int calculateRelevanceWeighting(Vocable vocable) {
        VocableRelevanceWeightingCalculator calculator =
                new VocableRelevanceWeightingCalculator(vocable, search);
        calculator.calculate();
        return calculator.getWeighting();
    }

    private void sortByRelevanceWeighting() {
        Collections.sort(vocables, new Comparator<Vocable>() {
            @Override
            public int compare(Vocable v1, Vocable v2) {
                int weighting1 = relevanceWeighting.get(v1);
                int weighting2 = relevanceWeighting.get(v2);
                return weighting1 - weighting2; // kleiner gewinnt
            }
        });
    }

}
