package de.duehl.vocabulary.japanese.tools;

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

import org.junit.jupiter.api.Test;

import de.duehl.basics.collections.CollectionsHelper;
import de.duehl.basics.datetime.date.ImmutualDate;
import de.duehl.vocabulary.japanese.VocabularyTrainerVersion;
import de.duehl.vocabulary.japanese.common.data.InternalAdditionalVocableData;
import de.duehl.vocabulary.japanese.common.data.VocablesShuffleType;
import de.duehl.vocabulary.japanese.common.persistence.Options;
import de.duehl.vocabulary.japanese.data.FumikoDataStructures;
import de.duehl.vocabulary.japanese.data.Vocable;

import static org.junit.jupiter.api.Assertions.*;
import static de.duehl.vocabulary.japanese.tools.VocablesForTesting.*;

public class VocableListShufflerTestGenerell {

    /*
     * Beim zuerst gesehen-Datum gewinnt das spätere Datum, da diese Vokabeln neuer
     * und daher vermutlich unbekannter sind.
     */
    private static final InternalAdditionalVocableData DATA_FIRST_SEEN_20231001 =
            new InternalAdditionalVocableData()
                    .setFirstSeenDate(new ImmutualDate("01.10.2023"))
                    ;
    private static final InternalAdditionalVocableData DATA_FIRST_SEEN_20231002 =
            new InternalAdditionalVocableData()
                    .setFirstSeenDate(new ImmutualDate("02.10.2023"))
                    ;
    private static final InternalAdditionalVocableData DATA_FIRST_SEEN_20231003 =
            new InternalAdditionalVocableData()
                    .setFirstSeenDate(new ImmutualDate("03.10.2023"))
                    ;
    private static final InternalAdditionalVocableData DATA_FIRST_SEEN_20231004 =
            new InternalAdditionalVocableData()
                    .setFirstSeenDate(new ImmutualDate("04.10.2023"))
                    ;
    private static final InternalAdditionalVocableData DATA_FIRST_SEEN_20231005 =
            new InternalAdditionalVocableData()
                    .setFirstSeenDate(new ImmutualDate("05.10.2023"))
                    ;
    private static final InternalAdditionalVocableData DATA_FIRST_SEEN_20231006 =
            new InternalAdditionalVocableData()
                    .setFirstSeenDate(new ImmutualDate("06.10.2023"))
                    ;
    private static final InternalAdditionalVocableData DATA_FIRST_SEEN_20231007 =
            new InternalAdditionalVocableData()
                    .setFirstSeenDate(new ImmutualDate("07.10.2023"))
                    ;
    private static final InternalAdditionalVocableData DATA_FIRST_SEEN_20231008 =
            new InternalAdditionalVocableData()
                    .setFirstSeenDate(new ImmutualDate("08.10.2023"))
                    ;

    @Test
    public void sortByFirstSeenDate() {
        List<Vocable> vocables = CollectionsHelper.buildListFrom(MAKURA, KAGAMI, AI, SEKKEN, BEDDO,
                FUTON, DEMO, KAGE);

        Map<Vocable, InternalAdditionalVocableData> requesterMap = new HashMap<>();
        requesterMap.put(MAKURA, DATA_FIRST_SEEN_20231003);
        requesterMap.put(KAGAMI, DATA_FIRST_SEEN_20231001);
        requesterMap.put(AI, DATA_FIRST_SEEN_20231002);
        requesterMap.put(SEKKEN, DATA_FIRST_SEEN_20231008);
        requesterMap.put(BEDDO, DATA_FIRST_SEEN_20231007);
        requesterMap.put(FUTON, DATA_FIRST_SEEN_20231005);
        requesterMap.put(DEMO, DATA_FIRST_SEEN_20231006);
        requesterMap.put(KAGE, DATA_FIRST_SEEN_20231004);

        Options options = new Options(new VocabularyTrainerVersion().getVersion());
        options.setReverseShuffledVocables(false);

        FumikoDataStructures dataStructures = TestDataStructureBuilder.create(requesterMap,
                options);

        VocableListShuffler shuffler = new VocableListShuffler(vocables,
                VocablesShuffleType.FIRST_SEEN_DATE, dataStructures);
        shuffler.shuffle();

        //printVocables(vocables, requesterMap);

        List<Vocable> shuffled = shuffler.getVocables();
        assertEquals(8, shuffled.size());
        assertEquals(SEKKEN, shuffled.get(0));
        assertEquals(BEDDO, shuffled.get(1));
        assertEquals(DEMO, shuffled.get(2));
        assertEquals(FUTON, shuffled.get(3));
        assertEquals(KAGE, shuffled.get(4));
        assertEquals(MAKURA, shuffled.get(5));
        assertEquals(AI, shuffled.get(6));
        assertEquals(KAGAMI, shuffled.get(7));
    }

    @Test
    public void sortByFirstSeenDateReverse() {
        List<Vocable> vocables = CollectionsHelper.buildListFrom(MAKURA, KAGAMI, AI, SEKKEN, BEDDO,
                FUTON, DEMO, KAGE);

        Map<Vocable, InternalAdditionalVocableData> requesterMap = new HashMap<>();
        requesterMap.put(MAKURA, DATA_FIRST_SEEN_20231003);
        requesterMap.put(KAGAMI, DATA_FIRST_SEEN_20231001);
        requesterMap.put(AI, DATA_FIRST_SEEN_20231002);
        requesterMap.put(SEKKEN, DATA_FIRST_SEEN_20231008);
        requesterMap.put(BEDDO, DATA_FIRST_SEEN_20231007);
        requesterMap.put(FUTON, DATA_FIRST_SEEN_20231005);
        requesterMap.put(DEMO, DATA_FIRST_SEEN_20231006);
        requesterMap.put(KAGE, DATA_FIRST_SEEN_20231004);

        Options options = new Options(new VocabularyTrainerVersion().getVersion());
        options.setReverseShuffledVocables(true);

        FumikoDataStructures dataStructures = TestDataStructureBuilder.create(requesterMap,
                options);

        VocableListShuffler shuffler = new VocableListShuffler(vocables,
                VocablesShuffleType.FIRST_SEEN_DATE, dataStructures);

        shuffler.shuffle();

        //printVocables(vocables, requesterMap);

        List<Vocable> shuffled = shuffler.getVocables();
        assertEquals(8, shuffled.size());
        assertEquals(KAGAMI, shuffled.get(0));
        assertEquals(AI, shuffled.get(1));
        assertEquals(MAKURA, shuffled.get(2));
        assertEquals(KAGE, shuffled.get(3));
        assertEquals(FUTON, shuffled.get(4));
        assertEquals(DEMO, shuffled.get(5));
        assertEquals(BEDDO, shuffled.get(6));
        assertEquals(SEKKEN, shuffled.get(7));
    }

    @SuppressWarnings("unused")
    private void printVocables(List<Vocable> vocables,
            Map<Vocable, InternalAdditionalVocableData> requesterMap) {
        int count = 0;
        for (Vocable vocable : vocables) {
            InternalAdditionalVocableData data = requesterMap.get(vocable);
            System.out.println(++count + ".)\n"
                    + vocable.toNiceString(4)
                    + data.toNiceString(4)
                    );
        }
    }

    @Test
    public void sortByFirstSeenDateShort() {
        List<Vocable> vocables = CollectionsHelper.buildListFrom(MAKURA, KAGAMI);

        Map<Vocable, InternalAdditionalVocableData> requesterMap = new HashMap<>();
        requesterMap.put(MAKURA, DATA_FIRST_SEEN_20231003);
        requesterMap.put(KAGAMI, DATA_FIRST_SEEN_20231001);

        Options options = new Options(new VocabularyTrainerVersion().getVersion());
        options.setReverseShuffledVocables(false);

        FumikoDataStructures dataStructures = TestDataStructureBuilder.create(requesterMap,
                options);

        VocableListShuffler shuffler = new VocableListShuffler(vocables,
                VocablesShuffleType.FIRST_SEEN_DATE, dataStructures);
        shuffler.shuffle();

        //printVocables(vocables, requesterMap);

        List<Vocable> shuffled = shuffler.getVocables();
        assertEquals(2, shuffled.size());
        assertEquals(MAKURA, shuffled.get(0));
        assertEquals(KAGAMI, shuffled.get(1));
    }

    @Test
    public void sortByFirstSeenDateReverseShort() {
        List<Vocable> vocables = CollectionsHelper.buildListFrom(MAKURA, KAGAMI);

        Map<Vocable, InternalAdditionalVocableData> requesterMap = new HashMap<>();
        requesterMap.put(MAKURA, DATA_FIRST_SEEN_20231003);
        requesterMap.put(KAGAMI, DATA_FIRST_SEEN_20231001);

        Options options = new Options(new VocabularyTrainerVersion().getVersion());
        options.setReverseShuffledVocables(true);

        FumikoDataStructures dataStructures = TestDataStructureBuilder.create(requesterMap,
                options);

        VocableListShuffler shuffler = new VocableListShuffler(vocables,
                VocablesShuffleType.FIRST_SEEN_DATE, dataStructures);
        shuffler.shuffle();

        //printVocables(vocables, requesterMap);

        List<Vocable> shuffled = shuffler.getVocables();
        assertEquals(2, shuffled.size());
        assertEquals(KAGAMI, shuffled.get(0));
        assertEquals(MAKURA, shuffled.get(1));
    }

}
