package org.iri_research.renkan.test.repositories;

import java.util.ArrayList;
import java.util.TimeZone;
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.joda.time.DateTime;
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");
        TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
        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 DateTime()));
        pl.add(new Project(testSpace.getId(), null, "test2", "desc2",
                "http://localhost:8080/rest/projects/id2", new DateTime()));
        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);
    }

}
