/**
 * Authors: Frederik Leyvraz, David Degenhardt
 * License: GNU General Public License v3.0 only
 * Version: 1.0.0
 */

package ch.bfh.ti.latexindexer;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static junit.framework.Assert.*;

public class IndexWriterTest {


    private Path tempFile, oneLiner;
    private Map<String, List<Integer>> occurrences;
    private Map<String, List<Integer>> chosen_occurrences;
    private IndexWriter indexWriter;

    @BeforeEach
    public void setUp() throws IOException {
        tempFile = Files.createTempFile("testlatex", ".tex");
        List<String> lines = Arrays.asList(
            "\\documentclass{article}",
            "",
            "\\begin{document}",
            "",
            "\\title{Minimal LaTeX Document}",
            "\\author{Your Name}",
            "\\date{\\today}",
            "",
            "\\maketitle",
            "",
            "\\section{Introduction}",
            "        This is a minimal LaTeX document created by ChatGPT.",
            "\\section{Another One}",
            "        This is a second section created by by ChatGPT.",
            "        Sometimes also referred to as chatty.",
            "",
            "\\subsection{Stacks and Queues}",
            "       Stacks follow the LIFO (Last In, First Out) principle, meaning that the last element added to",
            "       the stack is the first one to be removed. This is analogous to a stack of plates where " +
            "       you add and remove plates only from the top. The 'growth' direction" +
            "       for a stack is from the bottom to the top.",
            "\\end{document}"
        );
        Files.write(tempFile, lines);

        oneLiner = Files.createTempFile("oneliner", ".tex");
        List<String> oneLine = Arrays.asList("\\begin{document}",
                "\\section{Tree}",
                "Trees are data structures. Unlike other data structures, trees and tree-like structures are not linear.",
                "\\end{document}"
        );

        Files.write(oneLiner, oneLine);

        chosen_occurrences = new HashMap<>();
        chosen_occurrences.put(tempFile.toString(), Arrays.asList(11));
    }

    @AfterEach
    public void tearDown() throws IOException {
        Files.deleteIfExists(tempFile);
    }

    @Test
    void testAddToIndex() throws IOException {
        indexWriter = new IndexWriter(tempFile.toString());
        indexWriter.replaceWordInFiles(new Word("ChatGPT"));
        List<String> modifiedLines = Files.readAllLines(tempFile);
        assertEquals("        This is a minimal LaTeX document created by ChatGPT\\index{ChatGPT}.", modifiedLines.get(11));
        assertEquals("        This is a second section created by by ChatGPT\\index{ChatGPT}.", modifiedLines.get(13));


    }

    @Test
    void testAddToIndexByOccurrence() throws IOException {
        indexWriter = new IndexWriter(tempFile.toString());
        indexWriter.addToIndexByOccurrence(chosen_occurrences, new Word("ChatGPT"));
        List<String> modifiedLines = Files.readAllLines(tempFile);

        assertEquals("        This is a minimal LaTeX document created by ChatGPT\\index{ChatGPT}.", modifiedLines.get(11));

        // Other lines remain unchanged
        assertEquals("        This is a second section created by by ChatGPT.", modifiedLines.get(13));

    }

    @Test
    void testGetOccurrences() throws IOException {

        occurrences = new HashMap<>();
        occurrences.put(tempFile.toString(), Arrays.asList(11, 13));

        indexWriter = new IndexWriter(tempFile.toString());
        assertEquals(occurrences, indexWriter.getOccurrences(new Word("ChatGPT")));
    }

    @Test
    void testGetOccurencesOfSubvariants() throws IOException {
        occurrences = new HashMap<>();
        occurrences.put(tempFile.toString(), Arrays.asList(11, 13, 14));
        Word word = new Word("ChatGPT");
        word.setVariation("chatty");

        indexWriter = new IndexWriter(tempFile.toString());
        assertEquals(occurrences, indexWriter.getOccurrences(word));
    }

    @Test
    void testAddWordToIndexSubvariants() throws IOException {
        indexWriter = new IndexWriter(tempFile.toString());
        Word gpt = new Word("ChatGPT");
        gpt.setVariation("chatty");

        indexWriter.addToIndexByOccurrence(chosen_occurrences, gpt);

        List<String> modifiedLines = Files.readAllLines(tempFile);

        assertEquals("        This is a minimal LaTeX document created by ChatGPT\\index{ChatGPT}.", modifiedLines.get(11));
        // Other lines remain unchanged
        assertEquals("        This is a second section created by by ChatGPT.", modifiedLines.get(13));

    }

    @Test
    void testAddWordToIndexVariationsOneLine() throws IOException {
        indexWriter = new IndexWriter(oneLiner.toString());
        Word tree = new Word("Tree");
        tree.setVariation("Trees");
        tree.setVariation("trees");
        tree.setVariation("tree");

        Word heap = new Word("heap");
        heap.setVariation("Heaps");

        indexWriter.replaceWordInFiles(tree);
        List<String> modifiedLines = Files.readAllLines(oneLiner);
        assertEquals("\\section{Tree\\index{Tree}}", modifiedLines.get(1));
        assertEquals("Trees\\index{Tree} are data structures. " +
                "Unlike other data structures, trees\\index{Tree} and " +
                "tree\\index{Tree}-like structures are not linear.", modifiedLines.get(2));

    }


    @Test
    void testAddWordToIndexSubVariants() throws IOException {
        indexWriter = new IndexWriter(oneLiner.toString());
        Word tree = new Word("Tree");
        tree.setVariation("Trees");
        tree.setVariation("trees");
        tree.setVariation("tree");

        Word trie = new Word("Trie");
        Word heap = new Word("heap");
        heap.setVariation("Heaps");

        heap.setSuperVariant(tree);
        trie.setSuperVariant(heap);

        indexWriter.replaceWordInFiles(tree);
        indexWriter.replaceWordInFiles(trie);
        indexWriter.replaceWordInFiles(heap);

        List<String> modifiedLines = Files.readAllLines(oneLiner);

        assertEquals("\\section{Tree\\index{Tree}}", modifiedLines.get(1));
        assertEquals("Trees\\index{Tree} are data structures. " +
                "Unlike other data structures, trees\\index{Tree} and " +
                "tree\\index{Tree}-like structures are not linear.", modifiedLines.get(2));

    }

    /*@Disabled
    @Test
    void testSubvariantsMultipleAdds() throws IOException {
        indexWriter = new IndexWriter(tempFile.toString());
        Word queue = new Word("queue");
        queue.setVariation("Queues");
        Word stack = new Word("stack");
        stack.setVariation("stacks");
        stack.setVariation("Stacks");
        stack.setSuperVariant(queue);

        indexWriter.replaceWordInFiles(stack);
        indexWriter.replaceWordInFiles(queue); // the other way around works 


        List<String> modifiedLines = Files.readAllLines(tempFile);
        
        System.out.println(modifiedLines.get(18));
        assertEquals("       Stacks\\index{queue!stack} follow the LIFO (Last In, First Out) principle, meaning that the last element added to",
                modifiedLines.get(17));

    }

    @Disabled
    @Test
    void testAddIndexTag() {
        indexWriter = new IndexWriter(tempFile.toString());

        String someLatex = "\\subsection{Stakeholders and associated\n" +
                "SCRUM-Roles}\\label{stakeholders-and-associated-scrum-roles}";

        String expectedResult = "\\subsection{Stakeholders and associated\n" +
                "SCRUM-Roles\\index{Scrum-Roles}}\\label{stakeholders-and-associated-scrum-roles}";

        assertEquals(expectedResult, indexWriter.addIndexTag(someLatex, new Word("Scrum-Roles")));

    }*/





}
