package it.cnr.isti.driver.web;

import static org.mockito.Mockito.stub;
import static org.mockito.Mockito.verify;
import it.cnr.isti.driver.test.CommonRSTestCase;
import it.cnr.isti.driver.utils.ODL_EPR;
import it.cnr.isti.driver.utils.ResultSet;
import it.cnr.isti.driver.utils.ResultSetClient;
import it.cnr.isti.driver.utils.SearchClient;
import it.cnr.isti.driver.utils.SearchServiceLocator;
import it.cnr.isti.driver.utils.StaticSearchServiceLocator;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;

import org.mockito.MockitoAnnotations.Mock;

public class AsynchronousSearchEngineTest extends CommonRSTestCase {

	private static final String cqlQuery = "test=AsynchronousSearchEngineTest";
	private static final String rsId = "rs-1206811804711-656";
	
	@Mock
	protected SearchClient searchClient;
	
	@Mock
	protected ResultSetClient rsClient;

	protected SearchServiceLocator searchLocator;
	protected AsynchronousSearchEngine searchEngine;

	protected CacheManager cacheManager = CacheManager.create();
	protected Cache resultSetByQueryCache;
	protected Cache resultSetByEprCache;
	
	protected ODL_EPR equivalentEpr;
	
	protected void setUp() throws Exception {
		super.setUp();

		equivalentEpr = new ODL_EPR();
		equivalentEpr.setAddress(epr.getAddress());
		equivalentEpr.setResourceIdentifier(epr.getResourceIdentifier());
		
		resultSetByQueryCache = new Cache("byQuery", 100, false, false, 1000, 1000);
		resultSetByEprCache = new Cache("byEpr", 100, false, false, 1000, 1000);
		cacheManager.addCache(resultSetByQueryCache);
		cacheManager.addCache(resultSetByEprCache);
		
		stub(searchClient.search(cqlQuery)).toReturn(epr);
		stub(rsClient.getNumberOfElements(rsId)).toReturn(2);
		stub(rsClient.getResult(rsId, 1, 2, "waiting", "")).toReturn(new String[] {"one", "two"});
		
		StaticSearchServiceLocator locator = new StaticSearchServiceLocator();
		locator.setService(searchClient);
		this.searchLocator = locator;

		this.searchEngine = new AsynchronousSearchEngine() {
			/* inject rsClient */
			protected ResultSet createResultSet(ODL_EPR epr) {
				ResultSet rs = super.createResultSet(epr);
				rs.setResultSetClient(rsClient);
				return rs;
			}
		};
		searchEngine.setSearchLocator(searchLocator);
		searchEngine.setResultSetByQueryCache(resultSetByQueryCache);
		searchEngine.setResultSetByEprCache(resultSetByEprCache);
	}
	
	protected void tearDown() {
		cacheManager.removalAll();
	}

	public void testResultSetForQuery() {
		searchEngine.prepareQuery(cqlQuery);
		ResultSet rs = searchEngine.resultSetForQueryOrEpr(cqlQuery, null);
		
		verifyResultSet(rs);
	}
	
	public void testResultSetForEpr() {
		searchEngine.prepareQuery(cqlQuery);		
		searchEngine.resultSetForQueryOrEpr(cqlQuery, null);
		ResultSet rs = searchEngine.resultSetForQueryOrEpr(null, equivalentEpr);
		
		verifyResultSet(rs);
	}
	
	protected void verifyResultSet(ResultSet rs) {
		verify(searchClient).search(cqlQuery);
		assertEquals(epr, rs.getEpr());
		assertEquals(2, rs.getNumberOfElements());
	}

	public void testPrepareQuery() throws InterruptedException, ExecutionException {
		searchEngine.prepareQuery(cqlQuery);
		Future<ResultSet> frs = searchEngine.getFutureResultSetByQuery(cqlQuery);
		
		// force synchronization
		ResultSet rs = frs.get();
		verify(searchClient).search(cqlQuery);
		
		verifyResultSet(rs);
	}
	
}
