package org.jabref.logic.exporter;

import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.jabref.logic.importer.ImportFormatPreferences;
import org.jabref.logic.importer.fileformat.BibtexImporter;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.util.DummyFileUpdateMonitor;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.io.TempDir;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.Answers;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;

public class MSBibExportFormatTestFiles {

    private static Path resourceDir;
    public BibDatabaseContext databaseContext;
    public Charset charset;
    private Path exportedFile;
    private MSBibExporter exporter;
    private BibtexImporter testImporter;

    static Stream<String> fileNames() throws IOException, URISyntaxException {
        // we have to point it to one existing file, otherwise it will return the default class path
        resourceDir = Paths.get(MSBibExportFormatTestFiles.class.getResource("MsBibExportFormatTest1.bib").toURI()).getParent();
        try (Stream<Path> stream = Files.list(resourceDir)) {
            return stream.map(n -> n.getFileName().toString())
                         .filter(n -> n.endsWith(".bib"))
                         .filter(n -> n.startsWith("MsBib"))
                         .collect(Collectors.toList())
                         .stream();
        }
    }

    @BeforeEach
    void setUp(@TempDir Path testFolder) throws Exception {
        databaseContext = new BibDatabaseContext();
        charset = StandardCharsets.UTF_8;
        exporter = new MSBibExporter();
        Path path = testFolder.resolve("ARandomlyNamedFile.tmp");
        exportedFile = Files.createFile(path);
        testImporter = new BibtexImporter(mock(ImportFormatPreferences.class, Answers.RETURNS_DEEP_STUBS), new DummyFileUpdateMonitor());
    }

    @ParameterizedTest(name = "{index} file={0}")
    @MethodSource("fileNames")
    void testPerformExport(String filename) throws IOException, SaveException {
        String xmlFileName = filename.replace(".bib", ".xml");
        Path expectedFile = resourceDir.resolve(xmlFileName);
        Path importFile = resourceDir.resolve(filename);

        List<BibEntry> entries = testImporter.importDatabase(importFile, StandardCharsets.UTF_8)
                                             .getDatabase()
                                             .getEntries();

        exporter.export(databaseContext, exportedFile, charset, entries);

        assertEquals(Files.readAllLines(expectedFile), Files.readAllLines(exportedFile));
    }
}

@@ -828,68 +828,146 @@
 rs;%0A
-%0A
 import 
-static
+org.xmlunit.diff.DefaultNodeMatcher;%0Aimport
  org.
-j
+xml
 unit.
-jupiter.api.
+diff.ElementSelectors;%0A%0Aimport static org.hamcrest.Matcher
 Assert
-ions
 .assert
-Equals
+That
 ;%0Aim
@@ -1003,16 +1003,79 @@
 to.mock;
+%0Aimport static org.xmlunit.matchers.CompareMatcher.isSimilarTo;
 %0A%0Apublic
@@ -3110,86 +3110,577 @@
     
-assertEquals(Files.readAllLines(expectedFile), Files.readAllLines(exportedFile
+String expected = String.join(%22%5Cn%22, Files.readAllLines(expectedFile));%0A        String actual = String.join(%22%5Cn%22, Files.readAllLines(exportedFile));%0A%0A        // The order of elements changes from Windows to Travis environment somehow%0A        // The order does not really matter, so we ignore it.%0A        // Source: https://stackoverflow.com/a/16540679/873282%0A        assertThat(expected, isSimilarTo(actual)%0A                .ignoreWhitespace()%0A                .normalizeWhitespace()%0A                .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText)
 ));%0A

Fix MSBibExportFormatTestFiles by ignoring the order of XML elements