package org.jabref.logic.importer;

import java.util.regex.Pattern;
import java.util.stream.Stream;

import org.jabref.logic.citationkeypattern.CitationKeyPatternPreferences;
import org.jabref.logic.importer.fileformat.BiblioscapeImporter;
import org.jabref.logic.importer.fileformat.BibtexImporter;
import org.jabref.logic.importer.fileformat.CitaviXmlImporter;
import org.jabref.logic.importer.fileformat.CopacImporter;
import org.jabref.logic.importer.fileformat.EndnoteImporter;
import org.jabref.logic.importer.fileformat.InspecImporter;
import org.jabref.logic.importer.fileformat.IsiImporter;
import org.jabref.logic.importer.fileformat.MedlineImporter;
import org.jabref.logic.importer.fileformat.MedlinePlainImporter;
import org.jabref.logic.importer.fileformat.ModsImporter;
import org.jabref.logic.importer.fileformat.MsBibImporter;
import org.jabref.logic.importer.fileformat.OvidImporter;
import org.jabref.logic.importer.fileformat.RepecNepImporter;
import org.jabref.logic.importer.fileformat.RisImporter;
import org.jabref.logic.importer.fileformat.pdf.PdfMergeMetadataImporter;
import org.jabref.model.util.DummyFileUpdateMonitor;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.ResourceLock;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.Answers;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@ResourceLock("Localization.lang")
public class ImporterTest {

    private static final Pattern WHITESPACE_PATTERN = Pattern.compile("\\s");

    @Test
    void supportsFileExtensionIsCaseInsensitive() {
        RisImporter risImporter = new RisImporter();
        assertTrue(risImporter.supportsFileExtension("ris"));
        assertTrue(risImporter.supportsFileExtension("RIS"));
        assertTrue(risImporter.supportsFileExtension("Ris"));
    }

    @ParameterizedTest
    @MethodSource("instancesToTest")
    void getFormatterNameDoesNotReturnNull(Importer format) {
        assertNotNull(format.getName());
    }

    @ParameterizedTest
    @MethodSource("instancesToTest")
    void getFileTypeDoesNotReturnNull(Importer format) {
        assertNotNull(format.getFileType());
    }

    @ParameterizedTest
    @MethodSource("instancesToTest")
    void getIdDoesNotReturnNull(Importer format) {
        assertNotNull(format.getId());
    }

    @ParameterizedTest
    @MethodSource("instancesToTest")
    void getIdDoesNotContainWhitespace(Importer format) {
        assertFalse(WHITESPACE_PATTERN.matcher(format.getId()).find());
    }

    @ParameterizedTest
    @MethodSource("instancesToTest")
    void getDescriptionDoesNotReturnNull(Importer format) {
        assertNotNull(format.getDescription());
    }

    public static Stream<Importer> instancesToTest() {
        ImportFormatPreferences importFormatPreferences = mock(ImportFormatPreferences.class, Answers.RETURNS_DEEP_STUBS);
        when(importFormatPreferences.bibEntryPreferences().getKeywordSeparator()).thenReturn(',');
        CitationKeyPatternPreferences citationKeyPatternPreferences = mock(CitationKeyPatternPreferences.class);
        when(citationKeyPatternPreferences.getUnwantedCharacters()).thenReturn(CitationKeyPatternPreferences.DEFAULT_UNWANTED_CHARACTERS);
        return Stream.of(
                // all classes implementing {@link Importer}
                // sorted alphabetically
                new BiblioscapeImporter(),
                new BibtexImporter(importFormatPreferences, new DummyFileUpdateMonitor()),
                new CitaviXmlImporter(),
                new CopacImporter(),
                new EndnoteImporter(citationKeyPatternPreferences),
                new InspecImporter(),
                new IsiImporter(),
                new MedlineImporter(),
                new MedlinePlainImporter(importFormatPreferences),
                new ModsImporter(importFormatPreferences),
                new MsBibImporter(),
                new OvidImporter(),
                new PdfMergeMetadataImporter(importFormatPreferences),
                new RepecNepImporter(importFormatPreferences),
                new RisImporter()
        );
    }
}
