package fr.iri.thd.sonyengine.test;


import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.ws.rs.core.MediaType;

import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.representation.Form;

import fr.iri.thd.sonyengine.core.DataAccessor;
import fr.iri.thd.sonyengine.core.DbEnv;

public class TestTagResource {

	public static final String BASE_URL = "http://localhost:9080/sonyengine/";
	public static final String DATABASE_PATH = "/Users/ymh/dev/tmp/db";

	private DbEnv dbenv = null;
	private File databasePathFile = null;
	private String baseurl = null;
			
	@Before
	public void setup()
	{
		String databasepath = System.getProperty("database_path");
		if(databasepath == null)
			databasepath = DATABASE_PATH;
		databasePathFile = new File(databasepath);
		
		this.baseurl = System.getProperty("baseurl");
		if(this.baseurl == null)
			this.baseurl = BASE_URL;
	}
	
	@After
	public void teardown() {
	
		if(dbenv != null)
			dbenv.close();
	}
	
	@Test
	public void testCreateTag() {

		String movieName = "movie" + System.currentTimeMillis();
		String tagName = "tag" + System.currentTimeMillis();;
		
		Client c = Client.create();
		WebResource res = c.resource(this.baseurl + "segment/create/" + movieName);
		String response = res.accept(MediaType.APPLICATION_JSON_TYPE).post(String.class);
				
		Assert.assertNotNull(response);
		
		res = c.resource(this.baseurl).path("tag").path("add").path(tagName).path(movieName);
		response = res.accept(MediaType.APPLICATION_JSON_TYPE).post(String.class);

		Assert.assertNotNull(response);

		dbenv = new DbEnv();
		dbenv.setup(databasePathFile, true, true);

		DataAccessor da = new DataAccessor(this.dbenv.getEntityStore());
		
		Assert.assertTrue(da.tagByName.contains(tagName));
		
	}

	@Test
	public void testCreateTagRetrain() throws InterruptedException, JsonParseException, JsonMappingException, IOException {

		List<String> tagNames = new ArrayList<String>();
		
		Client c = Client.create();
		ObjectMapper mapper = new ObjectMapper();

		WebResource res = null;
		String response = null;
		String tagName = null;
		Map<String, Object> resMap = null;
		
		String movieName = "movie" + System.currentTimeMillis();
		tagName = "tag" + System.currentTimeMillis();
		tagNames.add(tagName);
		
		res = c.resource(this.baseurl + "segment/create/" + movieName);
		response = res.accept(MediaType.APPLICATION_JSON_TYPE).post(String.class);
				
		Assert.assertNotNull(response);
		resMap = mapper.readValue(response, new TypeReference<Map<String, Object>>(){} );
		Assert.assertEquals(movieName, resMap.get("id"));
		
		res = c.resource(this.baseurl).path("tag").path("add").path(tagName).path(movieName).path("true");
		response = res.accept(MediaType.APPLICATION_JSON_TYPE).post(String.class);

		Assert.assertNotNull(response);
		resMap = mapper.readValue(response, new TypeReference<Map<String, Object>>(){} );
		Assert.assertEquals(tagName,resMap.get("name"));
		Assert.assertEquals(movieName, resMap.get("segment"));

		Thread.sleep(1);
		tagName = "tag" + System.currentTimeMillis();
		tagNames.add(tagName);
				
		res = c.resource(this.baseurl).path("tag").path("add").path(tagName).path(movieName).path("false");
		response = res.accept(MediaType.APPLICATION_JSON_TYPE).post(String.class);

		Assert.assertNotNull(response);
		resMap = mapper.readValue(response, new TypeReference<Map<String, Object>>(){} );
		Assert.assertEquals(tagName,resMap.get("name"));
		Assert.assertEquals(movieName, resMap.get("segment"));

		Thread.sleep(1);
		tagName = "tag" + System.currentTimeMillis();
		tagNames.add(tagName);
				
		res = c.resource(this.baseurl).path("tag").path("add").path(tagName).path(movieName).path("foo");
		response = res.accept(MediaType.APPLICATION_JSON_TYPE).post(String.class);

		Assert.assertNotNull(response);
		resMap = mapper.readValue(response, new TypeReference<Map<String, Object>>(){} );
		Assert.assertEquals(tagName,resMap.get("name"));
		Assert.assertEquals(movieName, resMap.get("segment"));

		Thread.sleep(1);
		tagName = "tag" + System.currentTimeMillis();
		tagNames.add(tagName);
				
		res = c.resource(this.baseurl).path("tag").path("add").path(tagName).path(movieName).path("1");
		response = res.accept(MediaType.APPLICATION_JSON_TYPE).post(String.class);

		Assert.assertNotNull(response);
		resMap = mapper.readValue(response, new TypeReference<Map<String, Object>>(){} );
		Assert.assertEquals(tagName,resMap.get("name"));
		Assert.assertEquals(movieName, resMap.get("segment"));

		
		dbenv = new DbEnv();
		dbenv.setup(databasePathFile, true, true);

		DataAccessor da = new DataAccessor(this.dbenv.getEntityStore());
		
		for (String tag : tagNames) {
			Assert.assertTrue(da.tagByName.contains(tag));
		}
		
	}
	
	
	@SuppressWarnings("unchecked")
	@Test
	public void testCreateTagList() throws JsonParseException, JsonMappingException, IOException {

		String movieName = "movie" + System.currentTimeMillis();
		
		List<String> tagNames = new ArrayList<String>();
		
		for(int i=0; i< 10; i++) {
			try {
				Thread.sleep(1);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			tagNames.add("tag" + System.currentTimeMillis());
		}
		
		Client c = Client.create();
		WebResource res = c.resource(this.baseurl + "segment/create/" + movieName);
		String response = res.accept(MediaType.APPLICATION_XML_TYPE).post(String.class);
				
		Assert.assertNotNull(response);
		
		String xml = "<tags>";
		for(String tagName: tagNames) {
			xml += String.format("<tag name=\"%s\" segment=\"%s\"/>", tagName, movieName);
		}
		xml += "</tags>";
		
		res = c.resource(this.baseurl).path("tag").path("add");
		Form form = new Form();
		form.add("xml", xml);
		response = res.type(MediaType.APPLICATION_FORM_URLENCODED).accept(MediaType.APPLICATION_JSON_TYPE).post(String.class, form);

		Assert.assertNotNull(response);
		
		ObjectMapper mapper = new ObjectMapper();
		TypeReference<Map<String, Object>> typeref = new TypeReference<Map<String, Object>>(){};
		Map<String,Object> resList = mapper.readValue(response, typeref);
		
		Assert.assertNotNull(resList);
				
		List<Map<String,Object>> tagList = (List<Map<String,Object>>)resList.get("tag");
		
		Assert.assertEquals(tagNames.size(), tagList.size());
		for (Map<String, Object> map : tagList) {
			Assert.assertEquals(movieName,map.get("segment"));
			Assert.assertTrue(tagNames.contains(map.get("name")));
		}

		dbenv = new DbEnv();
		dbenv.setup(databasePathFile, true, true);

		DataAccessor da = new DataAccessor(this.dbenv.getEntityStore());

		Assert.assertTrue(da.tagBySegment.contains(movieName));

		for(String tagName: tagNames) {		
			Assert.assertTrue(da.tagByName.contains(tagName));
		}
		
	}

}
