package com.atlassian.bitbucket.mesh.config;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.core.env.PropertiesPropertySource;

import java.util.Properties;
import java.util.function.BiConsumer;

import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class DefaultLoggingConfigTest {

    private AbstractEnvironment environment;
    @Mock
    private BiConsumer<String, String> logLevelMutator;
    private Properties properties;
    private DefaultLoggingConfig underTest;

    @Before
    public void setup() {
        environment = new AbstractEnvironment() {
        };
        properties = new Properties();
        environment.getPropertySources().addLast(new PropertiesPropertySource("mock", properties));
    }

    @Test
    public void testConstructionDoesNotUpdateLevels() {
        properties.setProperty("logging.logger.ROOT", "DEBUG");
        underTest = new DefaultLoggingConfig(environment, logLevelMutator);

        verifyNoInteractions(logLevelMutator);
    }

    @Test
    public void testReloadAndRemovingRestoresDefaultLevel() {
        properties.setProperty("logging.logger.ROOT", "DEBUG");
        underTest = new DefaultLoggingConfig(environment, logLevelMutator);
        properties.remove("logging.logger.ROOT");

        underTest.reload();

        verify(logLevelMutator).accept("ROOT", "WARN");
        verifyNoMoreInteractions(logLevelMutator);
    }

    @Test
    public void testReloadAndRemovingRestoresDefaultLevelForChildLogger() {
        properties.setProperty("logging.logger.com.atlassian.bitbucket.mesh", "DEBUG");
        underTest = new DefaultLoggingConfig(environment, logLevelMutator);
        properties.remove("logging.logger.com.atlassian.bitbucket.mesh");

        underTest.reload();

        verify(logLevelMutator).accept("com.atlassian.bitbucket.mesh", "INFO");
        verifyNoMoreInteractions(logLevelMutator);
    }

    @Test
    public void testReloadAndRemovingTwiceRestoresDefaultLevelForChildLogger() {
        underTest = new DefaultLoggingConfig(environment, logLevelMutator);
        properties.setProperty("logging.logger.com.atlassian.bitbucket.mesh", "DEBUG");
        underTest.reload();
        properties.remove("logging.logger.com.atlassian.bitbucket.mesh");

        underTest.reload();

        InOrder inOrder = inOrder(logLevelMutator);
        inOrder.verify(logLevelMutator).accept("com.atlassian.bitbucket.mesh", "DEBUG");
        inOrder.verify(logLevelMutator).accept("com.atlassian.bitbucket.mesh", "INFO");
        verifyNoMoreInteractions(logLevelMutator);
    }

    @Test
    public void testReloadAppliesLogLevelChanges() {
        properties.setProperty("logging.logger.ROOT", "DEBUG");
        underTest = new DefaultLoggingConfig(environment, logLevelMutator);

        underTest.reload();

        verify(logLevelMutator).accept("ROOT", "DEBUG");
        verifyNoMoreInteractions(logLevelMutator);
    }
}