package eu.dnetlib.enabling.resultset; // NOPMD

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;

import java.util.List;

import javax.xml.ws.wsaddressing.W3CEndpointReference;

import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;

import com.google.common.collect.Lists;

import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
import eu.dnetlib.enabling.tools.ServiceResolver;
import eu.dnetlib.miscutils.factory.Factory;
import eu.dnetlib.miscutils.functional.ThreadSafeUnaryFunction;
import eu.dnetlib.miscutils.functional.UnaryFunction;

/**
 * test xslt resultset.
 *
 * @author marko
 *
 */
@RunWith(MockitoJUnitRunner.class)
public class MappedResultSetTest {

	/**
	 * instance under test.
	 */
	private transient MappedResultSet mappedResultSet;

	/**
	 * service resolver.
	 */
	@Mock
	private transient ServiceResolver serviceResolver;

	/**
	 * resultset service mock.
	 */
	@Mock
	private transient ResultSetService resultSetService;
	
	/**
	 * resultset mock.
	 */
	@Mock
	private transient ResultSet resultSet;	

	private Answer<Object> resultSetAnswer = new Answer<Object>() {

		private List<String> list = Lists.newArrayList("1","2","3","4","5","6","7","8","9","10");
		
		@Override
		public Object answer(InvocationOnMock invocation) throws Throwable {
			String method = invocation.getMethod().getName();
			if (method.equals("getResult") || method.equals("getResults")) {
				int from = (Integer) invocation.getArguments()[1];
				int to = (Integer) invocation.getArguments()[2];
				
				return list.subList(from-1, to);
			}
			if (method.equals("getNumberOfElements") || method.equals("getNumberOfResults")) {
				return list.size();
			}
			if (method.equals("getRSStatus")) {
				return "closed";
			}
			if (method.equals("isOpen")) {
				return false;
			}			
			System.out.println(invocation.toString());
			return null;
		}		
	};

	/**
	 * Common setup.
	 * @throws ResultSetException 
	 *
	 */
	@Before
	public void setUp() throws ResultSetException {
		
		when(serviceResolver.getService(eq(ResultSetService.class), any(W3CEndpointReference.class))).thenReturn(resultSetService);
		when(serviceResolver.getResourceIdentifier(any(W3CEndpointReference.class))).thenReturn("123");

		when(resultSetService.getNumberOfElements(anyString())).thenAnswer(resultSetAnswer);
		when(resultSetService.getResult(anyString(), anyInt(), anyInt(), anyString())).thenAnswer(resultSetAnswer );
		when(resultSetService.getRSStatus(anyString())).thenAnswer(resultSetAnswer);
		
		when(resultSet.getNumberOfResults()).thenAnswer(resultSetAnswer);
		when(resultSet.getResults(anyInt(), anyInt())).thenAnswer(resultSetAnswer );
		when(resultSet.isOpen()).thenAnswer(resultSetAnswer);		
	}
	
	@Test
	@Ignore
	public void testThreadSafeMappedResultSet_1() {
		
		final Factory<UnaryFunction<String, String>> functionFactory = new Factory<UnaryFunction<String,String>>() {
			@Override
			public UnaryFunction<String, String> newInstance() {
				return new UnaryFunction<String, String>() {
					@Override
					public String evaluate(String arg) {
						return "mapped-" + arg;
					}
				};
			}
		}; 
		mappedResultSet = new MappedResultSet(null, new ThreadSafeUnaryFunction<String, String>(functionFactory), serviceResolver);
		mappedResultSet.setResultSet(resultSet);

		for (String s : mappedResultSet.getResult(1, 10)) {
			assertNotNull("null result", s);
			assertFalse("empty result", s.isEmpty());
			assertNotNull("null element", s);
			assertTrue("transformed correctly", s.startsWith("mapped-"));	
		}
	}
}

