package com.atlassian.stash.internal.sal;

import com.atlassian.bitbucket.timezone.TimeZoneService;
import com.atlassian.bitbucket.user.ApplicationUser;
import com.atlassian.bitbucket.user.TestApplicationUser;
import com.atlassian.sal.api.user.UserKey;
import com.atlassian.stash.internal.user.InternalUserService;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;

import java.util.TimeZone;

import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.when;

public class DefaultTimeZoneManagerTest {

    @Rule
    public MockitoRule mockito = MockitoJUnit.rule();

    @InjectMocks
    private DefaultTimeZoneManager timeZoneManager;
    @Mock
    private InternalUserService internalUserService;
    @Mock
    private TimeZoneService timeZoneService;

    @Test
    public void testGetDefaultTimeZone() {
        TimeZone defaultTz = TimeZone.getTimeZone("Europe/Stockholm");

        withDefaultTz(defaultTz);

        assertThat(timeZoneManager.getDefaultTimeZone(), equalTo(defaultTz));
    }

    @Test
    public void testGetUserTimeZone() {
        TimeZone userTz = TimeZone.getTimeZone("Europe/Oslo");

        withCurrentUserTz(userTz);

        assertThat(timeZoneManager.getUserTimeZone(), equalTo(userTz));
    }

    @Test(expected = NullPointerException.class)
    public void testGetUserTimeZoneForNullUser() {
        timeZoneManager.getUserTimeZone(null);
    }

    @Test
    public void testGetUserTimeZoneForUserThatDoesNotExist() {
        TimeZone defaultTz = TimeZone.getTimeZone("Australia/Hobart");

        withDefaultTz(defaultTz);

        assertThat(timeZoneManager.getUserTimeZone(UserKey.fromLong(10)), equalTo(defaultTz));
    }

    @Test
    public void testGetUserTimeZoneForUserThatDoesExist() {

        TimeZone defaultTz = TimeZone.getTimeZone("Australia/Hobart");
        TimeZone userTz = TimeZone.getTimeZone("America/New_York");
        UserKey userKey = UserKey.fromLong(10);

        withDefaultTz(defaultTz);
        withTzForUserWithKey(userKey, userTz);

        assertThat(timeZoneManager.getUserTimeZone(userKey), equalTo(userTz));
    }

    private DefaultTimeZoneManagerTest withCurrentUserTz(TimeZone userTz) {
        when(timeZoneService.getTimeZone()).thenReturn(userTz.toZoneId());
        return this;
    }

    private DefaultTimeZoneManagerTest withDefaultTz(TimeZone defaultTz) {
        when(timeZoneService.getDefaultTimeZone()).thenReturn(defaultTz.toZoneId());
        return this;
    }

    private DefaultTimeZoneManagerTest withTzForUserWithKey(UserKey userKey, TimeZone userTz) {
        ApplicationUser user = new TestApplicationUser(userKey.getStringValue());

        when(internalUserService.getUserByKey(userKey)).thenReturn(user);
        when(timeZoneService.getTimeZone(user)).thenReturn(userTz.toZoneId());

        return this;
    }
}