package de.renew.navigator.io;

import java.io.File;
import java.net.URI;
import java.net.URL;
import java.util.Collections;
import java.util.List;
import javax.swing.filechooser.FileFilter;

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

import CH.ifa.draw.IOHelper;
import CH.ifa.draw.io.CombinationFileFilter;
import CH.ifa.draw.io.ImportHolder;
import CH.ifa.draw.io.PNGFileFilter;
import CH.ifa.draw.io.importFormats.ImportFormat;
import de.renew.draw.storables.ontology.Drawing;

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.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;


/**
 * @author Konstantin Simon Maria Moellers
 * @version 2015-10-09
 */
public class FileFilterBuilderImplTest {
    private FileFilterBuilderImpl _fileFilterBuilder;
    private IOHelper _ioHelper;
    private ImportHolder _importHolder;

    @BeforeEach
    public void setUp() throws Exception {
        _ioHelper = mock(IOHelper.class);
        _importHolder = mock(ImportHolder.class);
        _fileFilterBuilder = new FileFilterBuilderImpl(_ioHelper, _importHolder);
    }

    @Test
    @Disabled("Temporarily ignored due necessary rework. Will be readded with #19645.")
    public void testBuildFileFilter() throws Exception {
        // Test combination file filters.
        final CombinationFileFilter filter;
        filter = new CombinationFileFilter("Test Descr");
        filter.add(new PNGFileFilter());
        when(_ioHelper.getFileFilter()).thenReturn(filter);

        // Test import formats.
        // FIXME with #19645, add the following format to array: new XMLImportFormat()
        final ImportFormat[] importFormats = { };
        when(_importHolder.allImportFormats()).thenReturn(importFormats);

        final CombinationFileFilter fileFilter = _fileFilterBuilder.buildFileFilter();

        verify(_ioHelper).getFileFilter();
        verify(_importHolder).allImportFormats();

        assertTrue(fileFilter.accept(new File("demo.xml")));
        assertTrue(fileFilter.accept(new File("demo.png")));
        assertEquals(fileFilter.getDescription(), "Test Descr");
    }

    @Test
    public void testBuildFileFilterThrowsException() throws Exception {
        // Test combination file filters.
        final CombinationFileFilter filter;
        filter = new CombinationFileFilter("Test Descr");
        filter.add(new PNGFileFilter());
        when(_ioHelper.getFileFilter()).thenReturn(filter);

        // Test runtime ex when using wrong filter.
        final ImportFormat[] wrongImportFormats = { new ImportFormat() {
            @Override
            public List<Drawing> importFiles(URL[] paths) throws Exception {
                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;
            }
        } };
        when(_importHolder.allImportFormats()).thenReturn(wrongImportFormats);

        // Bang
        assertThrows(RuntimeException.class, () -> _fileFilterBuilder.buildFileFilter());
    }

    @Test
    public void testIsExternallyOpenedFile() throws Exception {
        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 = _fileFilterBuilder.isExternallyOpenedFile(f);

            assertTrue(isExt);
        }

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

            assertFalse(isExt);
        }
    }
}