package com.atlassian.stash.sal.api;

import com.atlassian.sal.api.UrlMode;
import com.atlassian.bitbucket.Product;
import com.atlassian.bitbucket.nav.NavBuilder;
import com.atlassian.bitbucket.request.RequestContext;
import com.atlassian.bitbucket.request.RequestManager;
import com.atlassian.bitbucket.server.ApplicationPropertiesService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import java.io.File;
import java.net.URI;
import java.util.Date;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class DefaultApplicationPropertiesTest {

    @Mock
    private ApplicationPropertiesService propertiesService;
    @Mock
    private NavBuilder navBuilder;
    @Mock
    private RequestManager requestManager;
    @InjectMocks
    private DefaultApplicationProperties properties;

    @SuppressWarnings("deprecation")
    @Test
    public void testGetBaseUrl() throws Exception {
        when(navBuilder.buildBaseUrl()).thenReturn("very-interesting-url");
        assertEquals("very-interesting-url", properties.getBaseUrl());
    }

    @Test
    public void testGetBaseUrlAbsolute() {
        when(navBuilder.buildAbsolute()).thenReturn("https://stash.domain.com/stash");
        assertEquals("https://stash.domain.com/stash", properties.getBaseUrl(UrlMode.ABSOLUTE));
    }

    @Test
    public void testGetBaseUrlAuto() {
        when(navBuilder.buildConfigured()).thenReturn("https://stash.domain.com/stash");
        when(navBuilder.buildRelative()).thenReturn("/stash-relative");
        assertEquals("https://stash.domain.com/stash", properties.getBaseUrl(UrlMode.AUTO));
        RequestContext context = mock(RequestContext.class);
        when(requestManager.getRequestContext()).thenReturn(context);
        assertEquals("/stash-relative", properties.getBaseUrl(UrlMode.AUTO));
    }

    @Test
    public void testGetBaseUrlCanonical() {
        when(navBuilder.buildConfigured()).thenReturn("https://stash.domain.com/configured");
        assertEquals("https://stash.domain.com/configured", properties.getBaseUrl(UrlMode.CANONICAL));
    }

    @Test
    public void testGetBaseUrlRelative() {
        when(navBuilder.buildRelative()).thenReturn("/stash");
        assertEquals("/stash", properties.getBaseUrl(UrlMode.RELATIVE));
    }

    @Test
    public void testGetBaseUrlRelativeCanonical() throws Exception {
        when(propertiesService.getBaseUrl()).thenReturn(URI.create("https://stash.domain.com/configured"));
        assertEquals("/configured", properties.getBaseUrl(UrlMode.RELATIVE_CANONICAL));
    }

    @Test
    public void testGetBuildDate() throws Exception {
        final Date now = new Date();
        when(propertiesService.getBuildTimestamp()).thenReturn(now);
        assertEquals(now, properties.getBuildDate());
    }

    @Test
    public void testGetBuildNumber() throws Exception {
        when(propertiesService.getBuildNumber()).thenReturn("0.2");
        assertEquals("0.2", properties.getBuildNumber());
    }

    @Test
    public void testGetDisplayName() throws Exception {
        assertEquals(Product.NAME, properties.getDisplayName());
    }

    @Test
    public void testGetHomeDirectory() throws Exception {
        final File dir = new File(".").getAbsoluteFile();
        when(propertiesService.getHomeDir()).thenReturn(dir);
        assertEquals(dir, properties.getHomeDirectory());
    }

    @SuppressWarnings("deprecation")
    public void testGetPropertyValue() throws Exception {
        when(propertiesService.getPluginProperty(eq("meaning"))).thenReturn("deeper");

        assertEquals("deeper", properties.getPropertyValue("meaning"));

        verify(propertiesService).getPluginProperty(eq("meaning"));
    }

    @Test
    public void testGetVersion() throws Exception {
        when(propertiesService.getBuildVersion()).thenReturn("0.1");
        assertEquals("0.1", properties.getVersion());
    }
}
