/**
 * Copyright 2008-2009 DRIVER PROJECT (ICM UW)
 * Original author: Marek Horst
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package eu.dnetlib.resultset.impl;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.util.ArrayList;
import java.util.List;

import javax.xml.ws.wsaddressing.W3CEndpointReference;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;

import eu.dnetlib.resultset.api.IResultSet;
import eu.dnetlib.resultset.impl.containers.ResultSetObjectMemoryContainer;
import eu.dnetlib.common.utils.EprUtils;
import eu.dnetlib.data.index.ws.dataprov.IIndexDataProvider;
import eu.dnetlib.data.index.utils.SpringUtils;

/**
 * Test class for IndexResultSet.
 * @author mhorst
 *
 */
public class IndexPushResultSetTest {

	ApplicationContext ctx;
	IResultSet resultSet;
	IIndexDataProvider dataProvider;
		
	@Before
	public void setUp() throws Exception {
		ctx = SpringUtils.getSpringContext(SpringUtils.DEFAULT_JUNIT_RESOURCE);
		resultSet = (IResultSet) ctx.getBean("InternalResultSet");
		dataProvider = (IIndexDataProvider) ctx.getBean("SimpleIndexDataProvider");
		setUpSupportedResultSetObjectContainer(resultSet);
	}
	
	/**
	 * Required for setting ResultSetObjectMemoryContainer which is the only IResultSetObjectContainer
	 * instance supporting PushRS objects.
	 * @param resultSet
	 */
	private void setUpSupportedResultSetObjectContainer(IResultSet resultSet) {
		if (resultSet instanceof IndexResultSet) {
			IndexResultSet indexResultSet = (IndexResultSet) resultSet;
			if (!(indexResultSet.getRsObjectContainer() 
					instanceof ResultSetObjectMemoryContainer)) {
//				setting up supported ResultSetObjectMemoryContainer for PushRS objects.
				ResultSetObjectMemoryContainer rsObjectContainer = new ResultSetObjectMemoryContainer();
				rsObjectContainer.setIndexDataProvider(indexResultSet.getIndexDataProvider());
				indexResultSet.setRsObjectContainer(rsObjectContainer);
			}
		}
	}

	@After
	public void tearDown() throws Exception {
	}

	List<String> prepareResult(int count) {
		List<String> result = new ArrayList<String>();
		
		for (int i = 0; i < count; i++) {
			result.add("dummyResult"+i);
		}
		return result;
	}
	
	@Test
	public void testIdentify() {
		String identify = resultSet.identify();
		assertNotNull(identify);
		assertTrue(identify.length()>0);
	}
	
	@Test
	public void testCreatePushRS() throws IndexResultSetFaultMessage {
		int expiryTime = 0;
		W3CEndpointReference rsEPR = resultSet.createPushRS(expiryTime, null);
		assertNotNull(rsEPR);
		assertTrue(rsEPR.toString().length()>0);
		System.out.println(rsEPR);
	}
	
	@Test
	public void testDeleteRS() throws IndexResultSetFaultMessage {
		int expiryTime = Integer.MAX_VALUE;
		W3CEndpointReference epr = resultSet.createPushRS(expiryTime, null);
		String rsId = EprUtils.extractResultSetId(epr.toString());
		assertEquals(resultSet.populateRS(rsId, prepareResult(2)),rsId);
		assertTrue(resultSet.deleteRS(rsId));
		try {
			resultSet.getResult(rsId, 0, ResultSetConstants.RESULT_SET_END_POSITION_UNSPECIFIED, null, null);
			fail("Exception should be thrown!");
		} catch (IndexResultSetFaultMessage e) {
//			ok
		}
	}

	@Test
	public void testGetNumberOfElements() throws IndexResultSetFaultMessage {
		int expiryTime = Integer.MAX_VALUE;
		W3CEndpointReference epr = resultSet.createPushRS(expiryTime, null);
		String rsId = EprUtils.extractResultSetId(epr.toString());
		assertEquals(resultSet.populateRS(rsId, prepareResult(2)),rsId);
		assertEquals(resultSet.getNumberOfElements(rsId), 2);
		assertTrue(resultSet.deleteRS(rsId));
	}

	@Test
	public void testGetRSStatus() throws IndexResultSetFaultMessage {
		String rsId = null;
		try {
			int expiryTime = Integer.MAX_VALUE;
			W3CEndpointReference epr = resultSet.createPushRS(expiryTime, null);
			rsId = EprUtils.extractResultSetId(epr.toString());
			assertEquals(ResultSetConstants.RESULT_SET_STATUS_CLOSED, resultSet.getRSStatus(rsId));
		} finally {
			if (rsId!=null)
				resultSet.deleteRS(rsId);
		}
	}
	
	@Test
	public void testGetProperty() throws IndexResultSetFaultMessage {
		String rsId = null;
		try {
			int expiryTime = Integer.MAX_VALUE;
			W3CEndpointReference epr = resultSet.createPushRS(expiryTime, null);
			rsId = EprUtils.extractResultSetId(epr.toString());
			String getExpiryTime = resultSet.getProperty(rsId,"expiryTime");
			assertEquals(""+expiryTime,getExpiryTime );
		} finally {
			if (rsId!=null)
				resultSet.deleteRS(rsId);
		}
	}
	
	@Test
	public void testGetResult() throws IndexResultSetFaultMessage {
		String rsId = null;
		try {
			int expiryTime = Integer.MAX_VALUE;
			W3CEndpointReference epr = resultSet.createPushRS(expiryTime, null);
			rsId = EprUtils.extractResultSetId(epr.toString());
			assertEquals(resultSet.populateRS(rsId, prepareResult(3)),rsId);
			assertEquals(resultSet.getNumberOfElements(rsId), 3);
			List<String> results = resultSet.getResult(rsId, 1, 2, null, null);
			assertEquals(results.size(),2);
		} finally {
			if (rsId!=null)
				assertTrue(resultSet.deleteRS(rsId));
		}
	}

	@Test
	public void testSimpleGetResult() throws IndexResultSetFaultMessage {
		String rsId = null;
		try {
			int expiryTime = Integer.MAX_VALUE;
			W3CEndpointReference epr = resultSet.createPushRS(expiryTime, null);
			rsId = EprUtils.extractResultSetId(epr.toString());
			assertEquals(resultSet.populateRS(rsId, prepareResult(3)),rsId);
			assertEquals(resultSet.getNumberOfElements(rsId), 3);
			String[] results = resultSet.simpleGetResult(rsId, 1, 2, null);
			assertEquals(results.length,2);
		} finally {
			if (rsId!=null)
				assertTrue(resultSet.deleteRS(rsId));
		}
	}
	
	@Test
	public void testPopulateRS() throws IndexResultSetFaultMessage {
		String rsId = null;
		try {
			int expiryTime = Integer.MAX_VALUE;
			W3CEndpointReference epr = resultSet.createPushRS(expiryTime, null);
			rsId = EprUtils.extractResultSetId(epr.toString());
			assertEquals(resultSet.populateRS(rsId, prepareResult(2)),rsId);
			assertEquals(resultSet.getNumberOfElements(rsId), 2);
			List<String> results = resultSet.getResult(rsId, 0, ResultSetConstants.RESULT_SET_END_POSITION_UNSPECIFIED, null, null);
			assertEquals(results.size(), 2);
			assertEquals(resultSet.populateRS(rsId, prepareResult(2)),rsId);
			assertEquals(resultSet.getNumberOfElements(rsId), 4);
			results = resultSet.getResult(rsId, 0, ResultSetConstants.RESULT_SET_END_POSITION_UNSPECIFIED, null, null);
			assertEquals(results.size(), 4);
		} finally {
			if (rsId!=null)
				assertTrue(resultSet.deleteRS(rsId));
		}
		
	}

	@Test
	public void testRefreshExpiryTime() throws IndexResultSetFaultMessage {
		String rsId = null;
		try {
			int expiryTime = Integer.MAX_VALUE;
			W3CEndpointReference epr = resultSet.createPushRS(expiryTime, null);
			rsId = EprUtils.extractResultSetId(epr.toString());
			assertNotNull(rsId);
			if (resultSet instanceof IndexResultSet) {
				IndexResultSet indexResultSet = (IndexResultSet) resultSet;
				ResultSetObject rsObj = indexResultSet.getRsObjectContainer().get(rsId);
				assertNotNull(rsObj);
				assertEquals(expiryTime, rsObj.getExpiryTime());
				int newExpiryTime = 5000;
				resultSet.refreshExpiryTime(rsId, newExpiryTime);
				rsObj = indexResultSet.getRsObjectContainer().get(rsId);
				assertNotNull(rsObj);
				assertEquals(newExpiryTime, rsObj.getExpiryTime());
			}else
				fail("Cannot perform tests, result set is not IndexResultSet instance!");
		} finally {
			if (rsId!=null)
				assertTrue(resultSet.deleteRS(rsId));
		}
	}
}
