package eu.dnetlib.functionality.collection.app;

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

import java.util.Arrays;
import java.util.List;

import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.junit.BeforeClass;
import org.junit.Test;

import eu.dnetlib.api.functionality.CollectionService;
import eu.dnetlib.api.functionality.CollectionServiceException;
import eu.dnetlib.clients.functionality.collection.ws.CollectionWebService;
import eu.dnetlib.clients.functionality.collection.ws.CollectionWebServiceClient;
import eu.dnetlib.domain.functionality.Collection;

public class TestCollectionService {
	private static CollectionService collectionService = new CollectionWebServiceClient();

	@BeforeClass
	public static void setup() throws Throwable {
		try {
			JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
			factory.setServiceClass(CollectionWebService.class);
			factory.setAddress("http://localhost:8080/uoa-collection-latest/services/collectionWebService");

			CollectionWebService webService = (CollectionWebService) factory.create();

			((CollectionWebServiceClient) collectionService).setWebService(webService);
		} catch (Throwable t) {
			t.printStackTrace();

			throw t;
		}
	}
	
	@Test
	public void testCreateCollection() throws Exception {
		String collectionId = null;
		try {
			Collection collection = createValidCollection();
			assertNotNull(collection);
			collectionId = collectionService.createCollection(collection);
			assertNotNull(collectionId);
			Collection result = collectionService.getCollection(collectionId);
			assertNotNull(result);
			assertEquals(collectionId, result.getResourceId());
			
			assertEquals(collection.getSubject(), result.getSubject());
			assertEquals(collection.getName(), result.getName());
			assertEquals(collection.getDescription().size(), result.getDescription().size());
			assertEquals(collection.getOwner(), result.getOwner());
			assertEquals(collection.isFrozen(), result.isFrozen());
			assertEquals(collection.isPrivate(), result.isPrivate());
			assertEquals(collection.isVisible(), result.isVisible());
			assertEquals(collection.isContainer(), result.isContainer());

		} finally {
			if (collectionId!=null)
				collectionService.deleteCollection(collectionId);
		}
	}

	@Test
	public void testGetCollection() throws Exception {
		testCreateCollection();
	}
	
	@Test
	public void testGetNonExistingCollection() {
		String collectionId = "nonExistingCollectionId";
		try {
			collectionService.getCollection(collectionId);
			fail("Exception should be thrown when getting non existing collection!");
		} catch(CollectionServiceException e) {
//			ok
		}
	}
	
	@Test
	public void testRemoveCollection() throws Exception {
		String collectionId = null;
		Collection collection = createValidCollection();
		collectionId = collectionService.createCollection(collection);
		assertNotNull(collectionId);
		Collection result = collectionService.getCollection(collectionId);
		assertNotNull(result);
		assertEquals(collectionId, result.getResourceId());
		collectionService.deleteCollection(collectionId);
		try {
			collectionService.getCollection(collectionId);
			fail("Exception should be thrown when getting non existing collection!");
		} catch(CollectionServiceException e) {
//			ok
		}
	}
	
	@Test
	public void testRemoveNonExistingCollection() {
		String collectionId = "nonExistingCollectionId";
		try {
			collectionService.deleteCollection(collectionId);
			fail("Exception should be thrown when removing non existing collection!");
		} catch(CollectionServiceException e) {
//			ok
		}
	}
	
	@Test
	public void testUpdateCollection() throws Exception {
		String collectionId = null;
		try {
			Collection collectionReq = createValidCollection();
			collectionId = collectionService.createCollection(collectionReq);
			assertNotNull(collectionId);
						
			Collection collectionUpdReq = new Collection();
			collectionUpdReq.setResourceId(collectionId);
			collectionUpdReq.setSubject("someSubject2");
			collectionUpdReq.setName("someCollectionName2");
			collectionUpdReq.setDescription(Arrays.asList(new String[]{"someDescContent3"}));
			collectionUpdReq.setOwner("someOwner2");
			collectionUpdReq.setFrozen(true);
			collectionUpdReq.setPrivate(true);
			collectionUpdReq.setVisible(false);
			collectionUpdReq.setContainer(false);
			collectionUpdReq.setQuery("query");
			collectionService.updateCollection(collectionUpdReq);
			
			Collection result = collectionService.getCollection(collectionId);
			assertNotNull(result);
			assertEquals(collectionId, result.getResourceId());
			assertEquals(collectionUpdReq.getSubject(), result.getSubject());
			assertEquals(collectionUpdReq.getName(), result.getName());
			assertEquals(collectionUpdReq.getDescription().size(), result.getDescription().size());
			assertEquals(collectionUpdReq.getOwner(), result.getOwner());
			assertEquals(collectionUpdReq.isFrozen(), result.isFrozen());
			assertEquals(collectionUpdReq.isPrivate(), result.isPrivate());
			assertEquals(collectionUpdReq.isVisible(), result.isVisible());
			assertEquals(collectionUpdReq.isContainer(), result.isContainer());

		} finally {
			if (collectionId!=null)
				collectionService.deleteCollection(collectionId);
		}
	}
	
	@Test
	public void testUpdateNonExistingCollection() {
		try {
			Collection collection = createValidCollection();
			collectionService.updateCollection(collection);
			fail("Exception should be thrown when updating non existing collection!");
		} catch(CollectionServiceException e) {
//			ok
		} 
	}

	@Test
	public void testGetCollections() throws Exception {
		String collectionId1 = null;
		String collectionId2 = null;
		try {
			Collection collection = createValidCollection();
			collectionId1 = collectionService.createCollection(collection);
			assertNotNull(collectionId1);
			collectionId2 = collectionService.createCollection(collection);
			assertNotNull(collectionId2);
			
			List<Collection> results = collectionService.getCollections(Arrays.asList(
					new String[] {collectionId1, collectionId2}));
			assertNotNull(results);
			assertEquals(2, results.size());
			
			for (Collection result : results) {
				assertEquals(collection.getSubject(), result.getSubject());
				assertEquals(collection.getName(), result.getName());
				assertEquals(collection.getDescription().size(), result.getDescription().size());
				assertEquals(collection.getOwner(), result.getOwner());
				assertEquals(collection.isFrozen(), result.isFrozen());
				assertEquals(collection.isPrivate(), result.isPrivate());
				assertEquals(collection.isVisible(), result.isVisible());
				assertEquals(collection.isContainer(), result.isContainer());
			}

		} finally {
			if (collectionId1!=null)
				collectionService.deleteCollection(collectionId1);
			if (collectionId2!=null)
				collectionService.deleteCollection(collectionId2);
		}
	}
	
	@Test
	public void testGetCollectionsForNullIds() {
		try {
			collectionService.getCollections(null);
			fail("Exception should be thrown when getting collections for null ids!");
		} catch(CollectionServiceException e) {
//			ok
		}
	}
	
	private Collection createValidCollection() {
		Collection collection = new Collection();
		
		collection.setName("Collection Name");
		collection.setOwner("Antonis");
		collection.getDescription().add("Description");
		collection.setQuery("Query");
		collection.setSubject("Collection subject");
		
		return  collection;
	}
}
