package de.renew.navigator.io.internal;

import java.io.File;
import java.net.URI;
import java.net.URL;
import java.util.Collections;
import java.util.List;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;

import de.renew.draw.storables.api.StorableApi;
import de.renew.draw.storables.ontology.Drawing;
import de.renew.io.api.FileApi;
import de.renew.io.importFormats.XMLImportFormat;
import de.renew.ioontology.FileFilter;
import de.renew.ioontology.FileType;
import de.renew.ioontology.MultiExtensionFileFilterImpl;
import de.renew.ioontology.importing.ImportFormat;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mockStatic;


/**
 * @author Konstantin Simon Maria Moellers
 * @version 2015-10-09
 */
public class FileFilterHandlerTest {

    private MockedStatic<StorableApi> _mockedStorableApi;

    @BeforeEach
    public void setUp() throws Exception {
        _mockedStorableApi = mockStatic(StorableApi.class);
        _mockedStorableApi.when(StorableApi::getKnownDrawingTypesFileFilter).thenReturn(
            new MultiExtensionFileFilterImpl(
                "Test Descr", List.of(FileApi.createExtensionFileFilter(FileType.PNG))));
    }

    @AfterEach
    public void tearDown() {
        _mockedStorableApi.close();
    }

    @Test
    public void testBuildFileFilterValidFormats() {
        // given
        _mockedStorableApi.when(StorableApi::getImportFormats)
            .thenReturn(List.of(new XMLImportFormat()));

        // when
        final FileFilter fileFilter = FileFilterHandler.buildFileFilter();

        // then
        assertThat(fileFilter).returns(true, ff -> ff.accept(new File("demo.xml")))
            .returns(true, ff -> ff.accept(new File("demo.png")))
            .returns(false, ff -> ff.accept(new File("demo.other")))
            .returns("Test Descr", FileFilter::getDescription);

        assertEquals("Test Descr", fileFilter.getDescription());
    }

    @Test
    public void testBuildFileFilterInvalidFormats() {
        // given
        ImportFormat<Drawing> wrongImportFormat = new ImportFormat<>() {
            @Override
            public List<Drawing> importFiles(URL[] paths) {
                return Collections.emptyList();
            }

            @Override
            public FileFilter fileFilter() {
                return null;
            }

            @Override
            public String formatName() {
                return null;
            }

            @Override
            public boolean canImport(URL path) {
                return false;
            }

            @Override
            public boolean canImport(URI path) {
                return false;
            }
        };

        _mockedStorableApi.when(StorableApi::getImportFormats)
            .thenReturn(List.of(wrongImportFormat));


        // when / then
        assertThrows(RuntimeException.class, FileFilterHandler::buildFileFilter);
    }

    @Test
    public void testIsExternallyOpenedFile() {
        String[] externals = {
            "kb", "java", "jsp", "xml", "xmi", "md", "tex", "html", "cfg", "gif", "png", "jpg",
            "jpeg" };
        String[] internals = { "rnw", "draw" };

        for (final String external : externals) {
            final File f = new File("foo." + external);
            final boolean isExt = FileFilterHandler.isExternallyOpenedFile(f);

            assertTrue(isExt);
        }

        for (final String internal : internals) {
            final File f = new File("foo." + internal);
            final boolean isExt = FileFilterHandler.isExternallyOpenedFile(f);

            assertFalse(isExt);
        }
    }
}