package org.sagebionetworks.web.unitclient.widget.entity;

import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.sagebionetworks.repo.model.doi.Doi;
import org.sagebionetworks.repo.model.doi.DoiStatus;
import org.sagebionetworks.schema.adapter.JSONObjectAdapterException;
import org.sagebionetworks.web.client.GlobalApplicationState;
import org.sagebionetworks.web.client.StackConfigServiceAsync;
import org.sagebionetworks.web.client.SynapseClientAsync;
import org.sagebionetworks.web.client.security.AuthenticationController;
import org.sagebionetworks.web.client.widget.entity.DoiWidget;
import org.sagebionetworks.web.client.widget.entity.DoiWidgetView;
import org.sagebionetworks.web.test.helper.AsyncMockStubber;

import com.google.gwt.user.client.rpc.AsyncCallback;

public class DoiWidgetTest {

	GlobalApplicationState mockGlobalApplicationState;
	DoiWidgetView mockView;
	String entityId = "syn123";
	String testDoiPrefix = "testDoiPrefix";
	DoiWidget doiWidget;
	Doi testDoi;
	StackConfigServiceAsync mockStackConfigService;
	AuthenticationController mockAuthenticationController;
	SynapseClientAsync mockSynapseClient;

	@Before
	public void before() throws JSONObjectAdapterException {
		mockGlobalApplicationState = mock(GlobalApplicationState.class);
		mockView = mock(DoiWidgetView.class);
		mockAuthenticationController = mock(AuthenticationController.class);
		mockStackConfigService = mock(StackConfigServiceAsync.class);
		mockSynapseClient = mock(SynapseClientAsync.class);
		testDoi = new Doi();
		testDoi.setId(entityId);
		testDoi.setDoiStatus(DoiStatus.CREATED);
		AsyncMockStubber.callSuccessWith(testDoiPrefix).when(mockStackConfigService).getDoiPrefix(any(AsyncCallback.class));
		AsyncMockStubber.callSuccessWith(testDoi).when(mockSynapseClient).getEntityDoi(anyString(), anyLong(), any(AsyncCallback.class));
		doiWidget = new DoiWidget(mockView, mockGlobalApplicationState, mockStackConfigService, mockAuthenticationController, mockSynapseClient);
	}
	
	@Test
	public void testConfigureReadyStatus() throws Exception {
		testDoi.setDoiStatus(DoiStatus.READY);
		doiWidget.configure(testDoi, entityId);
		verify(mockView).setVisible(false);
		verify(mockView).clear();
		verify(mockView).showDoiCreated(doiWidget.getDoi(testDoiPrefix, false));
	}

	@Test
	public void testConfigureErrorStatus() throws Exception {
		testDoi.setDoiStatus(DoiStatus.ERROR);
		doiWidget.configure(testDoi, entityId);
		verify(mockView).setVisible(false);
		verify(mockView).clear();
		verify(mockView).showDoiError();
	}

	@Test(expected=UnsatisfiedLinkError.class)
	public void testConfigureInProcessStatus() throws Exception {
		testDoi.setDoiStatus(DoiStatus.IN_PROCESS);
		doiWidget.configure(testDoi, entityId);
		verify(mockView).showDoiInProgress();
	}
	
	@Test
	public void testConfigureNotFound() throws Exception {
		doiWidget.configure(null, entityId);
		verify(mockView).setVisible(false);
		verify(mockView).clear();
	}
	
	@Test
	public void testGetDoiPrefix() throws Exception {
		doiWidget.getDoiPrefix(mock(AsyncCallback.class));
		verify(mockStackConfigService).getDoiPrefix(any(AsyncCallback.class));
	}
	
	@Test
	public void testGetDoiLink() throws Exception {
		String prefix = "10.5072/FK2.";
		Long version = 42l;
		testDoi.setObjectVersion(version);
		doiWidget.configure(testDoi, entityId);
		String link = doiWidget.getDoi(prefix, true);
		assertTrue(link.contains(entityId));
		assertTrue(link.contains(version.toString()));
		assertTrue(link.contains(prefix));
	}

	@Test
	public void testGetDoiLinkNoPrefix() throws Exception {
		String prefix = "";
		Long version = 42l;
		testDoi.setObjectVersion(version);
		doiWidget.configure(testDoi, entityId);
		String link = doiWidget.getDoi(prefix, true);
		assertTrue(link.length() == 0);
		link = doiWidget.getDoi(null, true);
		assertTrue(link.length() == 0);
	}

	@Test(expected=UnsatisfiedLinkError.class)
	public void testGetEntityDoi() {
		// when ready
		testDoi.setDoiStatus(DoiStatus.READY);
		doiWidget.getEntityDoi(entityId, null);
		verify(mockView).setVisible(false);
		verify(mockView).clear();
		verify(mockView).showDoiCreated(doiWidget.getDoi(testDoiPrefix, false));
		// when in error
		testDoi.setDoiStatus(DoiStatus.ERROR);
		doiWidget.getEntityDoi(entityId, null);
		verify(mockView, Mockito.times(2)).setVisible(false);
		verify(mockView, Mockito.times(2)).clear();
		verify(mockView).showDoiError();
		// when in process, should throw UnsatisfiedLinkError
		testDoi.setDoiStatus(DoiStatus.IN_PROCESS);
		doiWidget.getEntityDoi(entityId, null);
		verify(mockView, Mockito.times(3)).setVisible(false);
		verify(mockView, Mockito.times(3)).clear();
		verify(mockView).showDoiError();
	}
	
}

@@ -4448,16 +4448,43 @@
 alse));%0A
+%09%09Mockito.reset(mockView);%0A
 %09%09// whe
@@ -4490,24 +4490,24 @@
 en in error%0A
-
 %09%09testDoi.se
@@ -4594,34 +4594,16 @@
 mockView
-, Mockito.times(2)
 ).setVis
@@ -4636,26 +4636,8 @@
 View
-, Mockito.times(2)
 ).cl
@@ -4678,16 +4678,43 @@
 rror();%0A
+%09%09Mockito.reset(mockView);%0A
 %09%09// whe
@@ -4866,34 +4866,16 @@
 mockView
-, Mockito.times(3)
 ).setVis
@@ -4908,26 +4908,8 @@
 View
-, Mockito.times(3)
 ).cl
@@ -4937,28 +4937,33 @@
 iew).showDoi
-Error
+InProgress
 ();%0A%09%7D%0A%09%0A%7D%0A

Reset mocked view instead of just increasing times called