package com.atlassian.stash.internal.content;

import com.atlassian.stash.internal.ApplicationSettings;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import java.io.File;
import java.net.FileNameMap;
import java.net.URLConnection;

import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class MimeTypeMappingConfigurationTest extends Assert {

    @Mock
    private ApplicationSettings applicationSettings;

    @Before
    public void mockApplicationSettings() {
        when(applicationSettings.getConfigDir()).thenReturn(new File(""));
    }

    /**
     * Call init(), but make sure you don't poison the URLConnection static object with a new FileNameMap.
     * @param mimeTypeMappingConfiguration conf to load configs for
     */
    private void loadStandardConfigs(MimeTypeMappingConfiguration mimeTypeMappingConfiguration) {
        FileNameMap oldMap = URLConnection.getFileNameMap();
        try {
            mimeTypeMappingConfiguration.init();
        } finally {
            URLConnection.setFileNameMap(oldMap);
        }
    }

    @Test
    public void testIdentifiesTextMimeType() {
        MimeTypeMappingConfiguration conf = new MimeTypeMappingConfiguration(applicationSettings);
        String mimeType = "randomString";
        conf.addTextMimeType(mimeType);

        assertTrue("Text mime-type registers as text", conf.isTextMimeType(mimeType));
        assertFalse("Text mime-type doesn't register as binary", conf.isBinaryMimeType(mimeType));
    }

    @Test
    public void testIdentifiesBinaryMimeType() {
        MimeTypeMappingConfiguration conf = new MimeTypeMappingConfiguration(applicationSettings);
        String mimeType = "randomString";
        conf.addBinaryMimeType(mimeType);

        assertFalse("Binary mime-type doesn't register as text", conf.isTextMimeType(mimeType));
        assertTrue("Binary mime-type registers as binary", conf.isBinaryMimeType(mimeType));
    }

    @Test
    public void testIdentifiesTextPrefixedMimeType() {
        MimeTypeMappingConfiguration conf = new MimeTypeMappingConfiguration(applicationSettings);
        String mimeType = "text/randomString";

        assertTrue("'text/*' mime-type registers as text", conf.isTextMimeType(mimeType));
        assertFalse("'text/*' mime-type doesn't register as binary", conf.isBinaryMimeType(mimeType));
    }

    @Test
    public void testIdentifiesUnknownMimeType() {
        MimeTypeMappingConfiguration conf = new MimeTypeMappingConfiguration(applicationSettings);
        String mimeType = "randomString";

        assertFalse("Unknown mime-type doesn't register as text", conf.isTextMimeType(mimeType));
        assertFalse("Unknown mime-type doesn't register as binary", conf.isBinaryMimeType(mimeType));
    }

    @Test
    public void testDeterminesMimeFromExtension() {
        MimeTypeMappingConfiguration conf = new MimeTypeMappingConfiguration(applicationSettings);

        String mimeType = "randomString";

        conf.addExtensionMapping(mimeType, "txt");

        assertEquals("Known file extension maps to correct mime-type", mimeType, conf.getContentTypeFor("thing.txt"));
        assertEquals("Unknown file extension falls back to Sun's mime table", "application/octet-stream", conf.getContentTypeFor("thing.bin"));
    }

    @Test
    public void testStandardConfigsAreLoaded() {
        MimeTypeMappingConfiguration conf = new MimeTypeMappingConfiguration(applicationSettings);

        loadStandardConfigs(conf);

        assertEquals("Extension from binary-mime.types is recognized", "chemical/x-xyz", conf.getContentTypeFor("thing.xyz"));
    }
}
