package org.iri_research.renkan.test.repositories;


import java.util.ArrayList;
import java.util.Date;
import java.util.UUID;

import org.iri_research.renkan.RenkanException;
import org.iri_research.renkan.models.Project;
import org.iri_research.renkan.models.ProjectSync;
import org.iri_research.renkan.models.Space;
import org.iri_research.renkan.repositories.ProjectSyncsRepository;
import org.iri_research.renkan.repositories.ProjectsRepository;
import org.iri_research.renkan.repositories.SpacesRepository;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("repositories-context.xml")
public class ProjectSyncsRepositoryTest {

	private Logger logger = LoggerFactory.getLogger(ProjectSyncsRepositoryTest.class);
	
	@Autowired
	private ProjectsRepository projectRepository;

	@Autowired
	private ProjectSyncsRepository projectSyncsRepository;
	
	@Autowired
	private SpacesRepository spacesRepository;
	
	
	private ArrayList<Project> testProjects = new ArrayList<Project>();
	
	public ProjectSyncsRepositoryTest() {
	}
	
	@Before
	public void setup() {
		
		logger.debug("Setup");
		Space testSpace = new Space(UUID.randomUUID().toString(), "test", "Test space", null, null, null, "test_user", null, null);
		testSpace = spacesRepository.save(testSpace);
		ArrayList<Project> pl = new ArrayList<Project>();
		pl.add(new Project(testSpace.getId(), null, "test1", "desc1", "http://localhost:8080/rest/projects/id1", new Date()));
		pl.add(new Project(testSpace.getId(), null, "test2", "desc2", "http://localhost:8080/rest/projects/id2", new Date()));
		logger.debug("Setup : new Project ");
		for(Project p: projectRepository.save(pl)) {
			this.testProjects.add(p);
		}
	}
	
	@After
	public void teardown() {
		logger.debug("Teardown");
		projectRepository.deleteAll();
		projectSyncsRepository.deleteAll();
	}
	

	@Test
	public void testGetCollection() {
		String collectionName = this.projectSyncsRepository.getCollection().getName();
		
		Assert.assertEquals("The collection name should be projectSyncs", "projectSyncs", collectionName);
		
	}
	
	@Test
	public void testGetProjectSync() throws RenkanException {
		
		Project p = projectRepository.findOne(this.testProjects.get(0).getId());
		
		String data = "{\"example\":\"this is an example\"}";
		
		ProjectSync ps = projectSyncsRepository.getProjectSync(data, p, "user1");
		
		ps = this.projectSyncsRepository.save(ps);
				
		
		ps = this.projectSyncsRepository.findOne(ps.getId());
		
		Assert.assertNotNull(ps);
		Assert.assertEquals(data, ps.getData());
				
	}
	
	
	@Test
	public void testGetProjectSyncRevision() throws RenkanException {
		
		Project p = projectRepository.findOne(this.testProjects.get(0).getId());
		
		String data = "{\"example\":\"this is an example\"}";
		
		ProjectSync ps = projectSyncsRepository.getProjectSync(data, p, "user1");
		
		ps = this.projectSyncsRepository.save(ps);
		ps = this.projectSyncsRepository.findOne(ps.getId());
				
		p = projectRepository.findOne(this.testProjects.get(0).getId());
		
		Assert.assertNotNull(ps.getProject());
		Assert.assertEquals(p.getId(), ps.getProject().getId());
		Assert.assertEquals("Revision of the project sync mustbe one less tha the rev counter pf the project", p.getRevCounter()-1, ps.getRevision());
		
		Assert.assertEquals("Revision of the project sync mustbe one less tha the rev counter of its project", ps.getProject().getRevCounter()-1, ps.getRevision());
		
	}
	
	@Test(expected=RenkanException.class)
	public void testGetProjectSyncExceptionNullProject() throws RenkanException {
		
		String data = "{\"example\":\"this is an example\"}";
		Project p = null;
		ProjectSync ps = projectSyncsRepository.getProjectSync(data, p, "user1");
		
		// should never be executed.
		Assert.assertNull(ps);
	}
	
	@Test(expected=RenkanException.class)
	public void testGetProjectSyncExceptionNullId() throws RenkanException {
		
		String data = "{\"example\":\"this is an example\"}";
		String project_id = null;
		ProjectSync ps = projectSyncsRepository.getProjectSync(data, project_id, "user1");
		
		// should never be executed.
		Assert.assertNull(ps);
	}
	
	@Test(expected=RenkanException.class)
	public void testGetProjectSyncExceptionEmptyId() throws RenkanException {
		
		String data = "{\"example\":\"this is an example\"}";
		String project_id = "";
		ProjectSync ps = projectSyncsRepository.getProjectSync(data, project_id, "user1");
		
		// should never be executed.
		Assert.assertNull(ps);
	}
	
	@Test(expected=RenkanException.class)
	public void testGetProjectSyncExceptionBadId() throws RenkanException {
		
		String data = "{\"example\":\"this is an example\"}";
		String project_id = "BAD_ID";
		ProjectSync ps = projectSyncsRepository.getProjectSync(data, project_id, "user1");
		
		// should never be executed.
		Assert.assertNull(ps);
	}
	
}
