package com.atlassian.bitbucket.mesh.config;

import com.atlassian.bitbucket.mesh.junit.TemporaryDirectory;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.StandardEnvironment;

import java.io.IOException;
import java.util.Properties;

import static com.atlassian.bitbucket.mesh.config.DefaultPackCacheConfig.*;
import static org.junit.Assert.*;

@RunWith(MockitoJUnitRunner.class)
public class DefaultPackCacheConfigTest {

    private static final int MAX_COUNT = 20;
    private static final long TTL_SEC = 30L;

    @Rule
    public final TemporaryDirectory tempDir = new TemporaryDirectory();

    private DefaultPackCacheConfig config;

    @Before
    public void setup() throws IOException {
        config = createConfig(true, true, true, MAX_COUNT, TTL_SEC);
    }

    @Test
    public void testDefaultConfiguration() {
        assertEquals(MAX_COUNT, config.getMaxCount());
        assertEquals(TTL_SEC, config.getTimeToLive());
        assertTrue(config.isEnabledForHttp());
        assertTrue(config.isEnabledForSsh());
    }

    @Test
    public void testProtocols() {
        config = createConfig(true, false, true, MAX_COUNT, TTL_SEC);
        assertFalse(config.isEnabledForHttp());
        assertTrue(config.isEnabledForSsh());

        config = createConfig(true, true, false, MAX_COUNT, TTL_SEC);
        assertTrue(config.isEnabledForHttp());
        assertFalse(config.isEnabledForSsh());

        config = createConfig(true, true, true, MAX_COUNT, TTL_SEC);
        assertTrue(config.isEnabledForHttp());
        assertTrue(config.isEnabledForSsh());

        config = createConfig(false, true, true, MAX_COUNT, TTL_SEC);
        assertFalse(config.isEnabledForHttp());
        assertFalse(config.isEnabledForSsh());
    }

    @Test
    public void testReload() {
        Properties properties = properties(true, true, true, MAX_COUNT, TTL_SEC);
        StandardEnvironment env = new StandardEnvironment();
        env.getPropertySources().addLast(new PropertiesPropertySource("configured", properties));
        config = new DefaultPackCacheConfig(env, tempDir.getRoot());

        assertEquals(MAX_COUNT, config.getMaxCount());
        assertEquals(TTL_SEC, config.getTimeToLive());
        assertTrue(config.isEnabledForHttp());
        assertTrue(config.isEnabledForSsh());

        //Simulate a change in the Spring environment
        properties.put(PROP_PACK_MAX_COUNT, 15);
        properties.put(PROP_PROTOCOL_SSH_ENABLED, "false");
        properties.put(PROP_PACK_TTL, 150L);
        config.reload();

        assertEquals(15, config.getMaxCount());
        assertEquals(150L, config.getTimeToLive());
        assertTrue(config.isEnabledForHttp());
        assertFalse(config.isEnabledForSsh());
    }

    private static Environment createEnvironment(Properties properties) {
        StandardEnvironment env = new StandardEnvironment();
        env.getPropertySources().addLast(new PropertiesPropertySource("configured", properties));

        return env;
    }

    private static Properties properties(boolean enabled, boolean http, boolean ssh, int maxCount, long ttl) {
        Properties properties = new Properties();
        properties.put(PROP_EVICTION_HYSTERESIS, Long.toString(1073741824L));
        properties.put(PROP_EVICTION_TRIGGER_FREE_SPACE, Long.toString(6442450944L));
        properties.put(PROP_EXPIRY_CHECK_INTERVAL, Integer.toString(30));
        properties.put(PROP_MINIMUM_FREE_SPACE, Long.toString(5368709120L));
        properties.put(PROP_PACK_ENABLED, Boolean.toString(enabled));
        properties.put(PROP_PACK_MAX_COUNT, Integer.toString(maxCount));
        properties.put(PROP_PROTOCOL_HTTP_ENABLED, Boolean.toString(http));
        properties.put(PROP_PROTOCOL_SSH_ENABLED, Boolean.toString(ssh));
        properties.put(PROP_PACK_TTL, Long.toString(ttl));
        return properties;
    }

    private DefaultPackCacheConfig createConfig(boolean enabled, boolean http, boolean ssh, int maxCount, long ttl) {
        Properties properties = properties(enabled, http, ssh, maxCount, ttl);
        return new DefaultPackCacheConfig(createEnvironment(properties), tempDir.getRoot());
    }
}
