package org.iri_research.renkan.test.rest;

import java.io.IOException;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;
import java.util.UUID;

import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.model.Resource;
import org.glassfish.jersey.test.JerseyTest;
import org.iri_research.renkan.models.Space;
import org.iri_research.renkan.repositories.SpacesRepository;
import org.iri_research.renkan.rest.RestApplication;
import org.iri_research.renkan.rest.SpacesResource;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
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;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.joda.JodaModule;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("rest-context.xml")
public class SpaceRestTest extends JerseyTest {

    private Logger logger = LoggerFactory.getLogger(SpaceRestTest.class);

    @Autowired
    private SpacesRepository spacesRepository;

    private Map<String, Space> spacesList = new HashMap<String, Space>();
    private String firstSpaceUUID = null;
    
    public SpaceRestTest() {
    }

    // @Override
    // protected AppDescriptor configure() {
    // return new WebAppDescriptor.Builder("org.iri_research.renkan.rest")
    // .contextPath("rest")
    // .contextParam("contextConfigLocation",
    // "classpath:/org/iri_research/renkan/test/rest/rest-context.xml")
    // .initParam("com.sun.jersey.config.property.packages",
    // "org.iri_research.renkan.rest")
    // .servletClass(SpringServlet.class)
    // .contextListenerClass(ContextLoaderListener.class)
    // .build();
    // };

    @Override
    protected Application configure() {
        TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
        ResourceConfig rc = new RestApplication()
                .property("contextConfigLocation",
                        "classpath:/org/iri_research/renkan/test/rest/rest-context.xml");
        rc.setApplicationName("rest");
        return rc;
    };

    @Before
    public void setup() {

        logger.debug("Setup");
        spacesRepository.deleteAll();
        DateTime creationDate = new DateTime();
        this.firstSpaceUUID = UUID.randomUUID().toString();
        Space testSpace = new Space(firstSpaceUUID, "test", "Test space", "{}",
                "http://ldt.iri.centrepompidou.fr", "#ababab", "test_user",
                "http://ldt.iri.centrepompidou.fr", creationDate);
        testSpace = spacesRepository.save(testSpace);
        this.spacesList.put(firstSpaceUUID, testSpace);

        Resource resource = Resource.builder(SpacesResource.class).build();
        String baseUri = resource.getPath();
        logger.debug("Path is " + baseUri);
        for (Resource cres : resource.getChildResources()) {
            logger.debug(cres.getAllMethods().toString() + " at " + baseUri
                    + "/" + cres.getPath());
        }

    }

    @After
    public void teardown() {
        spacesRepository.deleteAll();
    }

    @Test
    public void testSetup() throws JsonProcessingException, IOException {

        WebTarget webTarget = this.target("spaces");
        String respString = webTarget.request().get(String.class);

        Assert.assertNotNull(
                "The response string for the list of spaces must not be null",
                respString);

        logger.debug("RESPONSE : " + respString);

        Assert.assertTrue(
                "The length of the space list resp. string must be > 0",
                respString.length() > 0);

        ObjectMapper mapper = getObjectMapper();
        
        JsonNode spacesList = mapper.readTree(respString);

        Assert.assertTrue("The spaceList must be an array",
                spacesList.isArray());
        Assert.assertEquals(
                "The spaceList length must be = " + this.spacesList.size(),
                this.spacesList.size(), spacesList.size());

        for (JsonNode jsonNode : spacesList) {
            Assert.assertTrue("the space must have an id",
                    jsonNode.hasNonNull("id"));
            String id = jsonNode.get("id").asText();
            Assert.assertTrue("The id must be in the spacesList",
                    this.spacesList.containsKey(id));
            Space space = this.spacesList.get(id);
            Assert.assertNotNull(
                    "The object must in the spacesList must not be null", space);

        }

    }

    @Test
    public void testTitle() throws JsonProcessingException, IOException {

        WebTarget WebTarget = this.target();
        String respString = WebTarget.path("spaces").request()
                .get(String.class);
        logger.debug("RESPONSE : " + respString);
        ObjectMapper mapper = getObjectMapper();
        JsonNode spacesList = mapper.readTree(respString);

        for (JsonNode jsonNode : spacesList) {
            String id = jsonNode.get("_id").asText();
            Space space = this.spacesList.get(id);

            Assert.assertTrue("the space must have a title",
                    jsonNode.hasNonNull("title"));
            String title = jsonNode.get("title").asText();
            Assert.assertEquals(
                    "space title must be equals to " + space.getTitle(),
                    space.getTitle(), title);
        }

    }

    @Test
    public void testDescription() throws JsonProcessingException, IOException {

        WebTarget WebTarget = this.target();
        String respString = WebTarget.path("spaces").request()
                .get(String.class);
        logger.debug("RESPONSE : " + respString);
        ObjectMapper mapper = getObjectMapper();
        JsonNode spacesList = mapper.readTree(respString);

        for (JsonNode jsonNode : spacesList) {
            String id = jsonNode.get("id").asText();
            Space space = this.spacesList.get(id);

            Assert.assertTrue("the space must have a description",
                    jsonNode.hasNonNull("description"));
            String description = jsonNode.get("description").asText();
            Assert.assertEquals(
                    "space description must be equals to "
                            + space.getDescription(), space.getDescription(),
                    description);
        }

    }

    @Test
    public void testUri() throws JsonProcessingException, IOException {

        WebTarget WebTarget = this.target();
        String respString = WebTarget.path("spaces").request()
                .get(String.class);
        logger.debug("RESPONSE : " + respString);
        ObjectMapper mapper = getObjectMapper();
        JsonNode spacesList = mapper.readTree(respString);

        for (JsonNode jsonNode : spacesList) {
            String id = jsonNode.get("id").asText();
            Space space = this.spacesList.get(id);

            Assert.assertTrue("the space must have a uri",
                    jsonNode.hasNonNull("uri"));
            String uri = jsonNode.get("uri").asText();
            Assert.assertEquals(
                    "space uri must be equals to " + space.getUri(),
                    space.getUri(), uri);
        }

    }

    @Test
    public void testColor() throws JsonProcessingException, IOException {

        WebTarget WebTarget = this.target();
        String respString = WebTarget.path("spaces").request()
                .get(String.class);
        logger.debug("RESPONSE : " + respString);
        ObjectMapper mapper = getObjectMapper();
        mapper.registerModule(new JodaModule());
        JsonNode spacesList = mapper.readTree(respString);

        for (JsonNode jsonNode : spacesList) {
            String id = jsonNode.get("id").asText();
            Space space = this.spacesList.get(id);

            Assert.assertTrue("the space must have a color",
                    jsonNode.hasNonNull("color"));
            String color = jsonNode.get("color").asText();
            Assert.assertEquals(
                    "space color must be equals to " + space.getColor(),
                    space.getColor(), color);
        }

    }

    @Test
    public void testBinConfig() throws JsonProcessingException, IOException {

        WebTarget WebTarget = this.target();
        String respString = WebTarget.path("spaces").request()
                .get(String.class);
        logger.debug("RESPONSE : " + respString);
        ObjectMapper mapper = getObjectMapper();
        
        JsonNode spacesList = mapper.readTree(respString);

        for (JsonNode jsonNode : spacesList) {
            String id = jsonNode.get("id").asText();
            Space space = this.spacesList.get(id);

            Assert.assertTrue("the space must have a bin_config",
                    jsonNode.hasNonNull("bin_config"));
            String binConfig = jsonNode.get("bin_config").asText();
            Assert.assertEquals(
                    "space bin_config must be equals to "
                            + space.getBinConfig(), space.getBinConfig(),
                    binConfig);
        }

    }

    private ObjectMapper getObjectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JodaModule());
        return mapper;
    }

    @Test
    public void testCreatedBy() throws JsonProcessingException, IOException {

        WebTarget WebTarget = this.target();
        String respString = WebTarget.path("spaces").request()
                .get(String.class);
        logger.debug("RESPONSE : " + respString);
        ObjectMapper mapper = getObjectMapper();
        JsonNode spacesList = mapper.readTree(respString);

        for (JsonNode jsonNode : spacesList) {
            String id = jsonNode.get("id").asText();
            Space space = this.spacesList.get(id);

            Assert.assertTrue("the space must have a created_by",
                    jsonNode.hasNonNull("created_by"));
            String createdBy = jsonNode.get("created_by").asText();
            Assert.assertEquals(
                    "space created_by must be equals to "
                            + space.getCreatedBy(), space.getCreatedBy(),
                    createdBy);
        }

    }

    @Test
    public void testCreated() throws JsonProcessingException, IOException {

        WebTarget WebTarget = this.target();
        String respString = WebTarget.path("spaces").request()
                .get(String.class);
        logger.debug("RESPONSE : " + respString);
        ObjectMapper mapper = getObjectMapper();
        JsonNode spacesList = mapper.readTree(respString);

        for (JsonNode jsonNode : spacesList) {
            String id = jsonNode.get("id").asText();
            Space space = this.spacesList.get(id);

            Assert.assertTrue("the space must have a created",
                    jsonNode.hasNonNull("created"));

            String dateStr = jsonNode.get("created").asText();

            DateTimeFormatter fmt = ISODateTimeFormat.dateTime();
            DateTime date = fmt.parseDateTime(dateStr);

            Assert.assertEquals("Created date must be the same",
                    space.getCreated(), date);

        }

    }

    @Test
    public void testImage() throws JsonProcessingException, IOException {

        WebTarget WebTarget = this.target();
        String respString = WebTarget.path("spaces").request()
                .get(String.class);
        logger.debug("RESPONSE : " + respString);
        ObjectMapper mapper = getObjectMapper();
        JsonNode spacesList = mapper.readTree(respString);

        for (JsonNode jsonNode : spacesList) {
            String id = jsonNode.get("id").asText();
            Space space = this.spacesList.get(id);

            Assert.assertTrue("the space must have a image",
                    jsonNode.hasNonNull("image"));
            String image = jsonNode.get("image").asText();
            Assert.assertEquals(
                    "space image must be equals to " + space.getImage(),
                    space.getImage(), image);
        }

    }

    @Test
    public void testSingleCreated() throws JsonProcessingException, IOException {

        Space space = this.spacesList.get(this.firstSpaceUUID);
        WebTarget WebTarget = this.target();
        String respString = WebTarget.path("spaces").path(this.firstSpaceUUID)
                .request().accept(MediaType.APPLICATION_JSON).get(String.class);
        logger.debug("RESPONSE : " + respString);
        ObjectMapper mapper = getObjectMapper();
        JsonNode jsonNode = mapper.readTree(respString);

        String id = jsonNode.get("id").asText();
        Assert.assertEquals("id must be equals", space.getId(), id);

        Assert.assertTrue("the space must have a created",
                jsonNode.hasNonNull("created"));

        String dateStr = jsonNode.get("created").asText();

        DateTimeFormatter fmt = ISODateTimeFormat.dateTime();
        DateTime date = fmt.parseDateTime(dateStr);

        Assert.assertEquals("Created date must be the same",
                space.getCreated(), date);

    }

    @Test
    public void testSingleTitle() throws JsonProcessingException, IOException {

        Space space = this.spacesList.get(this.firstSpaceUUID);
        WebTarget WebTarget = this.target();
        String respString = WebTarget.path("spaces").path(this.firstSpaceUUID)
                .request().accept(MediaType.APPLICATION_JSON).get(String.class);
        logger.debug("RESPONSE : " + respString);
        ObjectMapper mapper = getObjectMapper();
        JsonNode jsonNode = mapper.readTree(respString);

        Assert.assertTrue("the space must have a title",
                jsonNode.hasNonNull("title"));
        String title = jsonNode.get("title").asText();
        Assert.assertEquals(
                "space title must be equals to " + space.getTitle(),
                space.getTitle(), title);
    }

    @Test
    public void testSingleDescription() throws JsonProcessingException,
            IOException {

        Space space = this.spacesList.get(this.firstSpaceUUID);
        WebTarget WebTarget = this.target();
        String respString = WebTarget.path("spaces").path(this.firstSpaceUUID)
                .request().accept(MediaType.APPLICATION_JSON).get(String.class);
        logger.debug("RESPONSE : " + respString);
        ObjectMapper mapper = getObjectMapper();
        JsonNode jsonNode = mapper.readTree(respString);

        Assert.assertTrue("the space must have a description",
                jsonNode.hasNonNull("description"));
        String description = jsonNode.get("description").asText();
        Assert.assertEquals(
                "space description must be equals to " + space.getDescription(),
                space.getDescription(), description);
    }

    @Test
    public void testSingleUri() throws JsonProcessingException, IOException {

        Space space = this.spacesList.get(this.firstSpaceUUID);
        WebTarget WebTarget = this.target();
        String respString = WebTarget.path("spaces").path(this.firstSpaceUUID)
                .request().accept(MediaType.APPLICATION_JSON).get(String.class);
        logger.debug("RESPONSE : " + respString);
        ObjectMapper mapper = getObjectMapper();
        JsonNode jsonNode = mapper.readTree(respString);

        Assert.assertTrue("the space must have a uri",
                jsonNode.hasNonNull("uri"));
        String uri = jsonNode.get("uri").asText();
        Assert.assertEquals("space uri must be equals to " + space.getUri(),
                space.getUri(), uri);
    }

    @Test
    public void testSingleColor() throws JsonProcessingException, IOException {

        Space space = this.spacesList.get(this.firstSpaceUUID);
        WebTarget WebTarget = this.target();
        String respString = WebTarget.path("spaces").path(this.firstSpaceUUID)
                .request().accept(MediaType.APPLICATION_JSON).get(String.class);
        logger.debug("RESPONSE : " + respString);
        ObjectMapper mapper = getObjectMapper();
        JsonNode jsonNode = mapper.readTree(respString);

        Assert.assertTrue("the space must have a color",
                jsonNode.hasNonNull("color"));
        String color = jsonNode.get("color").asText();
        Assert.assertEquals(
                "space color must be equals to " + space.getColor(),
                space.getColor(), color);
    }

    @Test
    public void testSingleBinConfig() throws JsonProcessingException,
            IOException {

        Space space = this.spacesList.get(this.firstSpaceUUID);
        WebTarget WebTarget = this.target();
        String respString = WebTarget.path("spaces").path(this.firstSpaceUUID)
                .request().accept(MediaType.APPLICATION_JSON).get(String.class);
        logger.debug("RESPONSE : " + respString);
        ObjectMapper mapper = getObjectMapper();
        JsonNode jsonNode = mapper.readTree(respString);

        Assert.assertTrue("the space must have a bin_config",
                jsonNode.hasNonNull("bin_config"));
        String binConfig = jsonNode.get("bin_config").asText();
        Assert.assertEquals(
                "space bin_config must be equals to " + space.getBinConfig(),
                space.getBinConfig(), binConfig);
    }

    @Test
    public void testSingleCreatedBy() throws JsonProcessingException,
            IOException {

        Space space = this.spacesList.get(this.firstSpaceUUID);
        WebTarget WebTarget = this.target();
        String respString = WebTarget.path("spaces").path(this.firstSpaceUUID)
                .request().accept(MediaType.APPLICATION_JSON).get(String.class);
        logger.debug("RESPONSE : " + respString);
        ObjectMapper mapper = getObjectMapper();
        JsonNode jsonNode = mapper.readTree(respString);

        Assert.assertTrue("the space must have a created_by",
                jsonNode.hasNonNull("created_by"));
        String createdBy = jsonNode.get("created_by").asText();
        Assert.assertEquals(
                "space created_by must be equals to " + space.getCreatedBy(),
                space.getCreatedBy(), createdBy);
    }

    @Test
    public void testSingleImage() throws JsonProcessingException, IOException {

        Space space = this.spacesList.get(this.firstSpaceUUID);
        WebTarget WebTarget = this.target();
        String respString = WebTarget.path("spaces").path(this.firstSpaceUUID)
                .request().accept(MediaType.APPLICATION_JSON).get(String.class);
        logger.debug("RESPONSE : " + respString);
        ObjectMapper mapper = getObjectMapper();
        JsonNode jsonNode = mapper.readTree(respString);

        Assert.assertTrue("the space must have a image",
                jsonNode.hasNonNull("image"));
        String image = jsonNode.get("image").asText();
        Assert.assertEquals(
                "space image must be equals to " + space.getImage(),
                space.getImage(), image);
    }

    @Test
    public void testPost() throws JsonProcessingException, IOException {

        String title = "test_post";
        String description = "test space post";
        String uri = "http://ldt.iri.centrepompidou.fr/test_post";
        String color = "#bcbcbc";
        String image = "http://ldt.iri.centrepompidou.fr/test_post/image";
        String created = "2013-01-01T01:01:01.001+0000";
        String expectedCreated = "2013-01-01T01:01:01.001Z";
        String bin_config = "{name: 'test_post_config'}";
        String created_by = "test_user_post";

        String spaceJson = String.format("{" + "\"title\":\"%s\","
                + "\"description\":\"%s\"," + "\"uri\":\"%s\","
                + "\"color\":\"%s\"," + "\"image\":\"%s\","
                + "\"created\":\"%s\"," + "\"bin_config\":\"%s\","
                + "\"created_by\":\"%s\"" + "}", title, description, uri,
                color, image, created, bin_config, created_by);

        WebTarget webTarget = this.target();
        Response resp = webTarget.path("spaces").request()
                .accept(MediaType.APPLICATION_JSON)
                .post(Entity.entity(spaceJson, MediaType.APPLICATION_JSON));

        String respStr = resp.readEntity(String.class);

        Assert.assertEquals("Resp status = created : " + respStr,
                Status.CREATED.getStatusCode(), resp.getStatus());
        Assert.assertTrue("Resp must be application/json", resp.getMediaType()
                .isCompatible(MediaType.APPLICATION_JSON_TYPE));

        ObjectMapper mapper = getObjectMapper();
        JsonNode objNode = mapper.readTree(respStr);

        Assert.assertTrue("the space must have an id", objNode.hasNonNull("id"));
        String idStr = objNode.get("id").asText();
        Assert.assertFalse("The id str must not be empty", idStr.length() == 0);

        Assert.assertTrue("the space must have a title",
                objNode.hasNonNull("title"));
        String titleStr = objNode.get("title").asText();
        Assert.assertEquals("space title must be equals to " + title, title,
                titleStr);

        Assert.assertTrue("the space must have a description",
                objNode.hasNonNull("description"));
        String descriptionStr = objNode.get("description").asText();
        Assert.assertEquals("space description must be equals to "
                + description, description, descriptionStr);

        Assert.assertTrue("the space must have a uri",
                objNode.hasNonNull("uri"));
        String uriStr = objNode.get("uri").asText();
        Assert.assertEquals("space uri must be equals to " + uri, uri, uriStr);

        Assert.assertTrue("the space must have a color",
                objNode.hasNonNull("color"));
        String colorStr = objNode.get("color").asText();
        Assert.assertEquals("space color must be equals to " + color, color,
                colorStr);

        Assert.assertTrue("the space must have a bin_config",
                objNode.hasNonNull("bin_config"));
        String bin_configStr = objNode.get("bin_config").asText();
        Assert.assertEquals("space bin_config must be equals to " + bin_config,
                bin_config, bin_configStr);

        Assert.assertTrue("the space must have a created_by",
                objNode.hasNonNull("created_by"));
        String created_byStr = objNode.get("created_by").asText();
        Assert.assertEquals("space created_by must be equals to " + created_by,
                created_by, created_byStr);

        Assert.assertTrue("the space must have a created",
                objNode.hasNonNull("created"));
        String createdStr = objNode.get("created").asText();
        Assert.assertEquals("space created must be equals to " + expectedCreated,
                expectedCreated, createdStr);

        // object must be created
        Space sp = this.spacesRepository.findOne(idStr);

        Assert.assertNotNull("Space object must be in rep", sp);

        Assert.assertEquals("space title must be equals to " + title, title,
                sp.getTitle());
        Assert.assertEquals("space description must be equals to "
                + description, description, sp.getDescription());
        Assert.assertEquals("space uri must be equals to " + uri, uri,
                sp.getUri());
        Assert.assertEquals("space color must be equals to " + color, color,
                sp.getColor());
        Assert.assertEquals("space bin_config must be equals to " + bin_config,
                bin_config, sp.getBinConfig());
        Assert.assertEquals("space created_by must be equals to " + created_by,
                created_by, sp.getCreatedBy());
        DateTimeFormatter fmt = ISODateTimeFormat.dateTime();
        DateTime created_date = fmt.parseDateTime(created);
        Assert.assertEquals("space created must be equals to " + created,
                created_date, sp.getCreated());

    }

    @Test
    public void testPostWithId() {

        String id = UUID.randomUUID().toString();
        String title = "test_post";
        String description = "test space post";
        String uri = "http://ldt.iri.centrepompidou.fr/test_post";
        String color = "#bcbcbc";
        String image = "http://ldt.iri.centrepompidou.fr/test_post/image";
        String created = "2013-01-01T01:01:01.001+0000";
        String bin_config = "{name: 'test_post_config'}";
        String created_by = "test_user_post";

        String spaceJson = String.format("{" + "\"id\":\"%s\","
                + "\"title\":\"%s\"," + "\"description\":\"%s\","
                + "\"uri\":\"%s\"," + "\"color\":\"%s\"," + "\"image\":\"%s\","
                + "\"created\":\"%s\"," + "\"bin_config\":\"%s\","
                + "\"created_by\":\"%s\"" + "}", id, title, description, uri,
                color, image, created, bin_config, created_by);

        WebTarget WebTarget = this.target();
        Response resp = WebTarget.path("spaces").request()
                .accept(MediaType.APPLICATION_JSON)
                .post(Entity.entity(spaceJson, MediaType.APPLICATION_JSON));

        String respStr = resp.readEntity(String.class);

        Assert.assertEquals("Resp status = Bad Request : " + respStr,
                Status.BAD_REQUEST.getStatusCode(), resp.getStatus());
        Assert.assertEquals("Error message", "Id in JSON must be null", respStr);

    }

    @Test
    public void testPut() throws JsonProcessingException, IOException {

        String id = this.firstSpaceUUID;
        String title = "test_post";
        String description = "test space put";
        String uri = "http://ldt.iri.centrepompidou.fr/test_put";
        String color = "#bcbcbc";
        String image = "http://ldt.iri.centrepompidou.fr/test_put/image";
        String created = "2013-01-01T01:01:01.001+0000";
        String bin_config = "{name: 'test_put_config'}";
        String created_by = "test_user_put";

        String spaceJson = String.format("{" + "\"id\":\"%s\","
                + "\"title\":\"%s\"," + "\"description\":\"%s\","
                + "\"uri\":\"%s\"," + "\"color\":\"%s\"," + "\"image\":\"%s\","
                + "\"created\":\"%s\"," + "\"bin_config\":\"%s\","
                + "\"created_by\":\"%s\"" + "}", id, title, description, uri,
                color, image, created, bin_config, created_by);

        WebTarget WebTarget = this.target();
        Response resp = WebTarget.path("spaces").path(this.firstSpaceUUID)
                .request()// type(MediaType.APPLICATION_JSON)
                .accept(MediaType.APPLICATION_JSON)// .entity(spaceJson)
                .put(Entity.entity(spaceJson, MediaType.APPLICATION_JSON));

        String respStr = "";

        if (resp.getStatus() != 204) {
            respStr = resp.readEntity(String.class);
        }

        Assert.assertEquals("Resp status = created : " + respStr,
                Status.NO_CONTENT.getStatusCode(), resp.getStatus());
        Assert.assertNull("Resp type must be null", resp.getMediaType());

        // object must be updated
        Space sp = this.spacesRepository.findOne(id);

        Assert.assertNotNull("Space object must be in rep", sp);

        Assert.assertEquals("space title must be equals to " + title, title,
                sp.getTitle());
        Assert.assertEquals("space description must be equals to "
                + description, description, sp.getDescription());
        Assert.assertEquals("space uri must be equals to " + uri, uri,
                sp.getUri());
        Assert.assertEquals("space color must be equals to " + color, color,
                sp.getColor());
        Assert.assertEquals("space bin_config must be equals to " + bin_config,
                bin_config, sp.getBinConfig());
        Assert.assertEquals("space created_by must be equals to " + created_by,
                created_by, sp.getCreatedBy());
        DateTimeFormatter fmt = ISODateTimeFormat.dateTime();
        DateTime created_date = fmt.parseDateTime(created);
        Assert.assertEquals("space created must be equals to " + created,
                created_date, sp.getCreated());

    }

    @Test
    public void testPutWithoutId() {

        String title = "test_put";
        String description = "test space put";
        String uri = "http://ldt.iri.centrepompidou.fr/test_put";
        String color = "#bcbcbc";
        String image = "http://ldt.iri.centrepompidou.fr/test_put/image";
        String created = "2013-01-01T01:01:01.001+0000";
        String bin_config = "{name: 'test_put_config'}";
        String created_by = "test_user_put";

        String spaceJson = String.format("{" + "\"title\":\"%s\","
                + "\"description\":\"%s\"," + "\"uri\":\"%s\","
                + "\"color\":\"%s\"," + "\"image\":\"%s\","
                + "\"created\":\"%s\"," + "\"bin_config\":\"%s\","
                + "\"created_by\":\"%s\"" + "}", title, description, uri,
                color, image, created, bin_config, created_by);

        WebTarget WebTarget = this.target();
        Response resp = WebTarget.path("spaces").path(this.firstSpaceUUID)
                .request().accept(MediaType.APPLICATION_JSON)
                .put(Entity.entity(spaceJson, MediaType.APPLICATION_JSON));

        String respStr = resp.readEntity(String.class);

        Assert.assertEquals("Resp status = Bad Request : " + respStr,
                Status.BAD_REQUEST.getStatusCode(), resp.getStatus());
        Assert.assertEquals("Error message",
                "Id parameter and id in JSON do not match", respStr);
    }

    @Test
    public void testPutBadId() {

        String id = UUID.randomUUID().toString();
        String title = "test_post";
        String description = "test space put";
        String uri = "http://ldt.iri.centrepompidou.fr/test_put";
        String color = "#bcbcbc";
        String image = "http://ldt.iri.centrepompidou.fr/test_put/image";
        String created = "2013-01-01T01:01:01.001+0000";
        String bin_config = "{name: 'test_put_config'}";
        String created_by = "test_user_put";

        String spaceJson = String.format("{" + "\"id\":\"%s\","
                + "\"title\":\"%s\"," + "\"description\":\"%s\","
                + "\"uri\":\"%s\"," + "\"color\":\"%s\"," + "\"image\":\"%s\","
                + "\"created\":\"%s\"," + "\"bin_config\":\"%s\","
                + "\"created_by\":\"%s\"" + "}", id, title, description, uri,
                color, image, created, bin_config, created_by);

        WebTarget WebTarget = this.target();
        Response resp = WebTarget.path("spaces").path(id)
                .request(MediaType.APPLICATION_JSON)
                .accept(MediaType.APPLICATION_JSON)
                .put(Entity.entity(spaceJson, MediaType.APPLICATION_JSON));

        String respStr = resp.readEntity(String.class);

        Assert.assertEquals("Resp status = Bad Request : " + respStr,
                Status.NOT_FOUND.getStatusCode(), resp.getStatus());

    }

    @Test
    public void testDelete() {

        WebTarget WebTarget = this.target();
        Response resp = WebTarget.path("spaces").path(this.firstSpaceUUID)
                .request().accept(MediaType.TEXT_PLAIN).delete();

        String respStr = resp.readEntity(String.class);
        URI reqUri = WebTarget.getUriBuilder().path("spaces")
                .path(this.firstSpaceUUID).build();

        Assert.assertEquals("Status must be deleted : " + respStr,
                Status.OK.getStatusCode(), resp.getStatus());
        Assert.assertEquals(
                String.format("Message must be \"%s deleted\"", reqUri),
                String.format("%s deleted", reqUri), respStr);

        // object must be updated
        Space sp = this.spacesRepository.findOne(this.firstSpaceUUID);

        Assert.assertNull("Space object must be in rep", sp);

    }

    @Test
    public void testSingleGetJsonp() throws JsonProcessingException,
            IOException {
        WebTarget WebTarget = this.target();
        Response resp = WebTarget.path("spaces").path(this.firstSpaceUUID)
                .queryParam("callback", "callback_func").request()
                .accept("application/javascript").get();
        Assert.assertEquals("return type must be application/javascript",
                "application/javascript", resp.getMediaType().toString());

        String respStr = resp.readEntity(String.class);

        Assert.assertTrue("resp must start with callback call",
                respStr.startsWith("callback_func("));
        Assert.assertTrue("resp must start with callback call",
                respStr.endsWith(")"));

        String jsonStr = respStr.substring("callback_func(".length(),
                respStr.length() - 1);
        ObjectMapper mapper = getObjectMapper();
        JsonNode jsonNode = mapper.readTree(jsonStr);

        Space space = this.spacesList.get(this.firstSpaceUUID);

        String id = jsonNode.get("id").asText();
        Assert.assertEquals("id must be equals", space.getId(), id);

        Assert.assertTrue("the space must have a created",
                jsonNode.hasNonNull("created"));

        String dateStr = jsonNode.get("created").asText();

        DateTimeFormatter fmt = ISODateTimeFormat.dateTime();
        DateTime date = fmt.parseDateTime(dateStr);

        Assert.assertEquals("Created date must be the same",
                space.getCreated(), date);

        Assert.assertEquals("title must be the same", space.getTitle(),
                jsonNode.get("title").asText());

    }

    @Test
    public void testSingleGetJsonpAcceptAll() throws JsonProcessingException,
            IOException {
        WebTarget WebTarget = this.target();
        Response resp = WebTarget.path("spaces").path(this.firstSpaceUUID)
                .queryParam("callback", "callback_func").request()
                .accept("*/*").get();
        Assert.assertEquals("return type must be application/javascript",
                "application/javascript", resp.getMediaType().toString());

        String respStr = resp.readEntity(String.class);

        Assert.assertTrue("resp must start with callback call",
                respStr.startsWith("callback_func("));
        Assert.assertTrue("resp must start with callback call",
                respStr.endsWith(")"));

        String jsonStr = respStr.substring("callback_func(".length(),
                respStr.length() - 1);
        ObjectMapper mapper = getObjectMapper();
        JsonNode jsonNode = mapper.readTree(jsonStr);

        Space space = this.spacesList.get(this.firstSpaceUUID);

        String id = jsonNode.get("id").asText();
        Assert.assertEquals("id must be equals", space.getId(), id);

        Assert.assertTrue("the space must have a created",
                jsonNode.hasNonNull("created"));

        String dateStr = jsonNode.get("created").asText();

        DateTimeFormatter fmt = ISODateTimeFormat.dateTime();
        DateTime date = fmt.parseDateTime(dateStr);

        Assert.assertEquals("Created date must be the same",
                space.getCreated(), date);

        Assert.assertEquals("title must be the same", space.getTitle(),
                jsonNode.get("title").asText());

    }
}
