package brooklyn.rest.resources;

import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;

import java.net.URI;
import java.util.Set;
import java.util.concurrent.TimeoutException;

import javax.ws.rs.core.Response;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.Test;

import brooklyn.entity.basic.Lifecycle;
import brooklyn.rest.domain.ApplicationSpec;
import brooklyn.rest.domain.ApplicationSummary;
import brooklyn.rest.domain.EntitySpec;
import brooklyn.rest.domain.EntitySummary;
import brooklyn.rest.domain.SensorSummary;
import brooklyn.rest.testing.BrooklynRestResourceTest;

import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.GenericType;

@Test(singleThreaded = true)
public class ApplicationResourceIntegrationTest extends BrooklynRestResourceTest {

    @SuppressWarnings("unused")
    private static final Logger log = LoggerFactory.getLogger(ApplicationResourceIntegrationTest.class);

    private final ApplicationSpec redisSpec = ApplicationSpec.builder().name("redis-app").
            entities(ImmutableSet.of(new EntitySpec("redis-ent", "brooklyn.entity.nosql.redis.RedisStore"))).
            locations(ImmutableSet.of("localhost")).
            build();

    @Override
    protected void setUpResources() throws Exception {
        addResources();
    }

    @Test(groups="Integration")
    public void testDeployRedisApplication() throws InterruptedException, TimeoutException {
        ClientResponse response = client().resource("/v1/applications")
                .post(ClientResponse.class, redisSpec);

        assertEquals(response.getStatus(), 201);
        assertEquals(getManagementContext().getApplications().size(), 1);
        assertTrue(response.getLocation().getPath().startsWith("/v1/applications/"), "path="+response.getLocation().getPath()); // path uses id, rather than app name

        waitForApplicationToBeRunning(response.getLocation());
    }

    @Test(groups="Integration", dependsOnMethods = "testDeployRedisApplication")
    public void testListEntities() {
        Set<EntitySummary> entities = client().resource("/v1/applications/redis-app/entities")
                .get(new GenericType<Set<EntitySummary>>() {
                });

        for (EntitySummary entity : entities) {
            client().resource(entity.getLinks().get("self")).get(ClientResponse.class);
            // TODO assertions on the above call?

            Set<EntitySummary> children = client().resource(entity.getLinks().get("children"))
                    .get(new GenericType<Set<EntitySummary>>() {
                    });
            assertEquals(children.size(), 0);
        }
    }

    @Test(groups="Integration", dependsOnMethods = "testDeployRedisApplication")
    public void testListSensorsRedis() {
        Set<SensorSummary> sensors = client().resource("/v1/applications/redis-app/entities/redis-ent/sensors")
                .get(new GenericType<Set<SensorSummary>>() {
                });
        assertTrue(sensors.size() > 0);
        SensorSummary uptime = Iterables.find(sensors, new Predicate<SensorSummary>() {
            @Override
            public boolean apply(SensorSummary sensorSummary) {
                return sensorSummary.getName().equals("redis.uptime");
            }
        });
        assertEquals(uptime.getType(), "java.lang.Integer");
    }

    @Test(groups="Integration", dependsOnMethods = { "testListSensorsRedis", "testListEntities" })
    public void testTriggerRedisStopEffector() throws InterruptedException {
        ClientResponse response = client().resource("/v1/applications/redis-app/entities/redis-ent/effectors/stop")
                .post(ClientResponse.class, ImmutableMap.of());

        assertEquals(response.getStatus(), Response.Status.ACCEPTED.getStatusCode());

        URI stateSensor = URI.create("/v1/applications/redis-app/entities/redis-ent/sensors/service.state");
        while (!client().resource(stateSensor).get(String.class).equals(Lifecycle.STOPPED.toString())) {
            Thread.sleep(5000);
        }
    }
    @Test(groups="Integration", dependsOnMethods = "testTriggerRedisStopEffector" )
    public void testDeleteRedisApplication() throws TimeoutException, InterruptedException {
        int size = getManagementContext().getApplications().size();
        ClientResponse response = client().resource("/v1/applications/redis-app")
                .delete(ClientResponse.class);

        waitForPageNotFoundResponse("/v1/applications/redis-app", ApplicationSummary.class);

        assertEquals(response.getStatus(), Response.Status.ACCEPTED.getStatusCode());
        assertEquals(getManagementContext().getApplications().size(), size-1);
    }

}

@@ -134,120 +134,350 @@
 ava.
-net.URI;%0Aimport java.util.Set;%0Aimport java.util.concurrent.TimeoutException;%0A%0Aimport javax.ws.rs.core.Response;%0A
+io.UnsupportedEncodingException;%0Aimport java.net.URI;%0Aimport java.nio.charset.Charset;%0Aimport java.util.Set;%0Aimport java.util.concurrent.TimeoutException;%0A%0Aimport javax.ws.rs.core.MediaType;%0Aimport javax.ws.rs.core.Response;%0A%0Aimport brooklyn.test.Asserts;%0Aimport brooklyn.util.collections.MutableMap;%0Aimport com.google.common.base.Throwables;
 %0Aimp
@@ -1978,16 +1978,29 @@
 ications
+/createLegacy
 %22)%0A     
@@ -4286,16 +4286,22 @@
         
+final 
 URI stat
@@ -4405,152 +4405,342 @@
     
-while (!client().resource(stateSensor).get(String.class).equals(Lifecycle.STOPPED.toString())) %7B%0A            Thread.sleep(5000);%0A        %7D%0A    %7D
+final String expectedStatus = String.format(%22%5C%22%25s%5C%22%22, Lifecycle.STOPPED.toString());%0A        Asserts.succeedsEventually(MutableMap.of(%22timeout%22, 60 * 1000), new Runnable() %7B%0A            public void run() %7B%0A                assertEquals(client().resource(stateSensor).get(String.class), expectedStatus);%0A            %7D%0A        %7D);%0A    %7D%0A
 %0A   

Fix failures in ApplicationResourceIntegrationTest