/*
 * Copyright 2016-present Open Networking Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.onosproject.rest.resources;

import com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonArray;
import com.eclipsesource.json.JsonObject;
import com.eclipsesource.json.JsonValue;
import org.hamcrest.Description;
import org.hamcrest.Matchers;
import org.hamcrest.TypeSafeMatcher;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
import org.onlab.packet.MacAddress;
import org.onlab.rest.BaseResource;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.core.DefaultApplicationId;
import org.onosproject.core.DefaultGroupId;
import org.onosproject.core.GroupId;
import org.onosproject.core.IdGenerator;
import org.onosproject.net.DeviceId;
import org.onosproject.net.NetworkResource;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowId;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.FlowRuleExtPayLoad;
import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.intent.FakeIntentManager;
import org.onosproject.net.intent.FlowRuleIntent;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.IntentState;
import org.onosproject.net.intent.Key;

import javax.ws.rs.NotFoundException;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static java.util.concurrent.TimeUnit.SECONDS;
import static org.easymock.EasyMock.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.onosproject.net.intent.IntentTestsMocks.MockIntent;
import static org.onosproject.net.intent.MockIdGenerator.bindNewGenerator;

/**
 * Unit tests for Intents REST APIs.
 */
public class IntentsResourceTest extends ResourceTest {


    private static final String APPID = "appId";
    private static final String CRITERIA = "criteria";
    private static final String DEVICE_ID = "deviceId";
    private static final String ID = "id";
    private static final String INSTRUCTIONS = "instructions";
    private static final String PATHS = "paths";
    private static final String SELECTOR = "selector";
    private static final String SPACE = " ";
    private static final String TREATMENT = "treatment";
    private static final String TYPE = "type";

    final IntentService mockIntentService = createMock(IntentService.class);
    final CoreService mockCoreService = createMock(CoreService.class);
    final FlowRuleService mockFlowService = createMock(FlowRuleService.class);
    final HashSet<Intent> intents = new HashSet<>();
    final List<org.onosproject.net.intent.Intent> installableIntents = new ArrayList<>();
    private static final ApplicationId APP_ID = new DefaultApplicationId(1, "test");
    private IdGenerator mockGenerator;

    final DeviceId deviceId1 = DeviceId.deviceId("1");

    final TrafficTreatment treatment1 = DefaultTrafficTreatment.builder()
            .setEthDst(MacAddress.BROADCAST)
            .build();
    final TrafficTreatment treatment2 = DefaultTrafficTreatment.builder()
            .setEthDst(MacAddress.IPV4_MULTICAST)
            .build();

    final TrafficSelector selector1 = DefaultTrafficSelector.builder()
            .matchEthType((short) 3)
            .matchIPProtocol((byte) 9)
            .build();
    final TrafficSelector selector2 = DefaultTrafficSelector.builder()
            .matchEthType((short) 4)
            .matchIPProtocol((byte) 10)
            .build();

    final MockFlowEntry flow1 = new MockFlowEntry(deviceId1, 1, treatment1, selector1);
    final MockFlowEntry flow2 = new MockFlowEntry(deviceId1, 2, treatment2, selector2);

    final MockFlowRule flowRule1 = new MockFlowRule(deviceId1, 1, treatment1, selector1);
    final MockFlowRule flowRule2 = new MockFlowRule(deviceId1, 2, treatment2, selector2);

    private class MockResource implements NetworkResource {
        int id;

        MockResource(int id) {
            this.id = id;
        }

        @Override
        public String toString() {
            return "Resource " + Integer.toString(id);
        }
    }

    /**
     * Mock class for a flow entry.
     */
    private static class MockFlowEntry implements FlowEntry {
        final DeviceId deviceId;
        final long baseValue;
        TrafficTreatment treatment;
        TrafficSelector selector;

        public MockFlowEntry(DeviceId deviceId, long id,
                             TrafficTreatment treatment,
                             TrafficSelector selector) {
            this.deviceId = deviceId;
            this.baseValue = id * 100;
            this.treatment = treatment;
            this.selector = selector;
        }

        @Override
        public FlowEntryState state() {
            return FlowEntryState.ADDED;
        }

        @Override
        public long life() {
            return life(SECONDS);
        }

        @Override
        public FlowLiveType liveType() {
            return null;
        }

        @Override
        public long life(TimeUnit timeUnit) {
            return SECONDS.convert(baseValue + 11, timeUnit);
        }

        @Override
        public long packets() {
            return baseValue + 22;
        }

        @Override
        public long bytes() {
            return baseValue + 33;
        }

        @Override
        public long lastSeen() {
            return baseValue + 44;
        }

        @Override
        public int errType() {
            return 0;
        }

        @Override
        public int errCode() {
            return 0;
        }

        @Override
        public FlowId id() {
            final long id = baseValue + 55;
            return FlowId.valueOf(id);
        }

        @Override
        public GroupId groupId() {
            return new DefaultGroupId(3);
        }

        @Override
        public short appId() {
            return 1;
        }

        @Override
        public int priority() {
            return (int) (baseValue + 66);
        }

        @Override
        public DeviceId deviceId() {
            return deviceId;
        }

        @Override
        public TrafficSelector selector() {
            return selector;
        }

        @Override
        public TrafficTreatment treatment() {
            return treatment;
        }

        @Override
        public int timeout() {
            return (int) (baseValue + 77);
        }

        @Override
        public int hardTimeout() {
            return 0;
        }

        @Override
        public FlowRule.FlowRemoveReason reason() {
            return  FlowRule.FlowRemoveReason.NO_REASON;
        }

        @Override
        public boolean isPermanent() {
            return false;
        }

        @Override
        public int tableId() {
            return 0;
        }

        @Override
        public boolean exactMatch(FlowRule rule) {
            return this.appId() == rule.appId() &&
                    this.deviceId().equals(rule.deviceId()) &&
                    this.id().equals(rule.id()) &&
                    this.treatment.equals(rule.treatment()) &&
                    this.selector().equals(rule.selector());
        }

        @Override
        public FlowRuleExtPayLoad payLoad() {
            return null;
        }

        @Override
        public String toString() {
            return id().id().toString();
        }
    }

    /**
     * Mock class for a flow rule.
     */
    private static class MockFlowRule implements FlowRule {

        final DeviceId deviceId;
        final long baseValue;
        TrafficTreatment treatment;
        TrafficSelector selector;

        public MockFlowRule(DeviceId deviceId,
                            long id,
                            TrafficTreatment treatment,
                            TrafficSelector selector) {
            this.deviceId = deviceId;
            this.baseValue = id * 100;
            this.treatment = treatment;
            this.selector = selector;
        }

        @Override
        public FlowId id() {
            long id = baseValue + 55;
            return FlowId.valueOf(id);
        }

        @Override
        public short appId() {
            return 1;
        }

        @Override
        public GroupId groupId() {
            return new DefaultGroupId(3);
        }

        @Override
        public int priority() {
            return 0;
        }

        @Override
        public DeviceId deviceId() {
            return deviceId;
        }

        @Override
        public TrafficSelector selector() {
            return selector;
        }

        @Override
        public TrafficTreatment treatment() {
            return treatment;
        }

        @Override
        public int timeout() {
            return (int) (baseValue + 77);
        }

        @Override
        public int hardTimeout() {
            return 0;
        }

        @Override
        public FlowRemoveReason reason() {
            return FlowRemoveReason.NO_REASON;
        }

        @Override
        public boolean isPermanent() {
            return false;
        }

        @Override
        public int tableId() {
            return 0;
        }

        @Override
        public boolean exactMatch(FlowRule rule) {
            return false;
        }

        @Override
        public FlowRuleExtPayLoad payLoad() {
            return null;
        }
    }

    /**
     * Hamcrest matcher to check that an intent representation in JSON matches
     * the actual intent.
     */
    public static class IntentJsonMatcher extends TypeSafeMatcher<JsonObject> {
        private final Intent intent;
        private String reason = "";

        public IntentJsonMatcher(Intent intentValue) {
            intent = intentValue;
        }

        @Override
        public boolean matchesSafely(JsonObject jsonIntent) {
            // check id
            final String jsonId = jsonIntent.get("id").asString();
            if (!jsonId.equals(intent.id().toString())) {
                reason = "id " + intent.id().toString();
                return false;
            }

            // check application id

            final String jsonAppId = jsonIntent.get("appId").asString();
            final String appId = intent.appId().name();
            if (!jsonAppId.equals(appId)) {
                reason = "appId was " + jsonAppId;
                return false;
            }

            // check intent type
            final String jsonType = jsonIntent.get("type").asString();
            if (!jsonType.equals("MockIntent")) {
                reason = "type MockIntent";
                return false;
            }

            // check state field
            final String jsonState = jsonIntent.get("state").asString();
            if (!jsonState.equals("INSTALLED")) {
                reason = "state INSTALLED";
                return false;
            }

            // check resources array
            final JsonArray jsonResources = jsonIntent.get("resources").asArray();
            if (intent.resources() != null) {
                if (intent.resources().size() != jsonResources.size()) {
                    reason = "resources array size of " + Integer.toString(intent.resources().size());
                    return false;
                }
                for (final NetworkResource resource : intent.resources()) {
                    boolean resourceFound = false;
                    final String resourceString = resource.toString();
                    for (int resourceIndex = 0; resourceIndex < jsonResources.size(); resourceIndex++) {
                        final JsonValue value = jsonResources.get(resourceIndex);
                        if (value.asString().equals(resourceString)) {
                            resourceFound = true;
                        }
                    }
                    if (!resourceFound) {
                        reason = "resource " + resourceString;
                        return false;
                    }
                }
            } else if (jsonResources.size() != 0) {
                reason = "resources array empty";
                return false;
            }
            return true;
        }

        @Override
        public void describeTo(Description description) {
            description.appendText(reason);
        }
    }

    /**
     * Factory to allocate an intent matcher.
     *
     * @param intent intent object we are looking for
     * @return matcher
     */
    private static IntentJsonMatcher matchesIntent(Intent intent) {
        return new IntentJsonMatcher(intent);
    }

    /**
     * Factory to allocate an IntentRelatedFlows matcher.
     *
     * @param pathEntries list of path conatining flow entries of a particular intent
     * @param expectedAppId expected app id we are looking for
     * @return matcher
     */
    private static IntentStatsJsonMatcher matchesRelatedFlowEntries(
            List<List<FlowEntry>> pathEntries,
            final String expectedAppId) {
        return new IntentStatsJsonMatcher(pathEntries, expectedAppId);
    }

    /**
     * Hamcrest matcher to check that an list of flowEntries in JSON matches
     * the actual list of flow entries.
     */
    public static class IntentStatsJsonMatcher extends
            TypeSafeMatcher<JsonObject> {

        private final List<List<FlowEntry>> pathEntries;
        private final String expectedAppId;
        private String reason = "";

        public IntentStatsJsonMatcher(
                final List<List<FlowEntry>> pathEntries,
                final String expectedAppId) {
            this.pathEntries = pathEntries;
            this.expectedAppId = expectedAppId;
        }

        @Override
        public boolean matchesSafely(JsonObject jsonIntent) {
            int jsonPathIndex = 0;
            JsonArray jsonPaths = jsonIntent.get(PATHS).asArray();

            if (pathEntries != null) {

                if (pathEntries.size() != jsonPaths.size()) {
                    reason = "path entries array size of " +
                            Integer.toString(pathEntries.size());
                    return false;
                }

                for (List<FlowEntry> flowEntries : pathEntries) {
                    JsonArray jsonFlowEntries = jsonPaths.get(
                            jsonPathIndex++).asArray();

                    if (flowEntries.size() != jsonFlowEntries.size()) {
                        reason = "flow entries array size of " +
                                Integer.toString(pathEntries.size());

                        return false;
                    }

                    int jsonFlowEntryIndex = 0;
                    for (FlowEntry flow : flowEntries) {

                        JsonObject jsonFlow = jsonFlowEntries.get(
                                jsonFlowEntryIndex++).asObject();

                        String jsonId = jsonFlow.get(ID).asString();
                        String flowId = Long.toString(flow.id().value());
                        if (!jsonId.equals(flowId)) {
                            reason = ID + SPACE + flow.id();
                            return false;
                        }

                        // check application id
                        String jsonAppId = jsonFlow.get(APPID).asString();
                        if (!jsonAppId.equals(expectedAppId)) {
                            reason = APPID + SPACE + Short.toString(flow.appId());
                            return false;
                        }

                        // check device id
                        String jsonDeviceId =
                                jsonFlow.get(DEVICE_ID).asString();

                        if (!jsonDeviceId.equals(flow.deviceId().toString())) {
                            reason = DEVICE_ID + SPACE + flow.deviceId();
                            return false;
                        }

                        if (!checkFlowTreatment(flow, jsonFlow)) {
                            return false;
                        }

                        if (!checkFlowSelector(flow, jsonFlow)) {
                            return false;
                        }

                    }

                }
            } else if (pathEntries.size() != 0) {
                reason = "pathEntries array empty";
                return false;
            }

            return true;
        }

        // check treatment and instructions array.
        private boolean checkFlowTreatment(FlowEntry flow, JsonObject jsonFlow) {

            if (flow.treatment() != null) {
                JsonObject jsonTreatment =
                        jsonFlow.get(TREATMENT).asObject();
                JsonArray jsonInstructions =
                        jsonTreatment.get(INSTRUCTIONS).asArray();

                if (flow.treatment().immediate().size() !=
                        jsonInstructions.size()) {
                    reason = "instructions array size of " +
                            flow.treatment().immediate().size();

                    return false;
                }
                for (Instruction instruction :
                        flow.treatment().immediate()) {
                    boolean instructionFound = false;
                    for (int instructionIndex = 0;
                         instructionIndex < jsonInstructions.size();
                         instructionIndex++) {
                        String jsonType =
                                jsonInstructions.get(instructionIndex)
                                        .asObject().get(TYPE).asString();

                        String instructionType =
                                instruction.type().name();

                        if (jsonType.equals(instructionType)) {
                            instructionFound = true;
                        }
                    }
                    if (!instructionFound) {
                        reason = INSTRUCTIONS + SPACE + instruction;
                        return false;
                    }
                }
            }
            return true;
        }

        // check selector and criteria array.
        private boolean checkFlowSelector(FlowEntry flow, JsonObject jsonFlow) {

            if (flow.selector() != null) {
                JsonObject jsonTreatment =
                        jsonFlow.get(SELECTOR).asObject();

                JsonArray jsonCriteria =
                        jsonTreatment.get(CRITERIA).asArray();

                if (flow.selector().criteria().size() != jsonCriteria.size()) {
                    reason = CRITERIA + " array size of " +
                            Integer.toString(flow.selector().criteria().size());
                    return false;
                }
                for (Criterion criterion : flow.selector().criteria()) {
                    boolean criterionFound = false;

                    for (int criterionIndex = 0;
                         criterionIndex < jsonCriteria.size();
                         criterionIndex++) {
                        String jsonType =
                                jsonCriteria.get(criterionIndex)
                                        .asObject().get(TYPE).asString();
                        String criterionType = criterion.type().name();
                        if (jsonType.equals(criterionType)) {
                            criterionFound = true;
                        }
                    }
                    if (!criterionFound) {
                        reason = "criterion " + criterion;
                        return false;
                    }
                }
            }
            return true;
        }

        @Override
        public void describeTo(Description description) {
            description.appendText(reason);
        }
    }

    /**
     * Hamcrest matcher to check that an intent is represented properly in a JSON
     * array of intents.
     */
    public static class IntentJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
        private final Intent intent;
        private String reason = "";

        public IntentJsonArrayMatcher(Intent intentValue) {
            intent = intentValue;
        }

        @Override
        public boolean matchesSafely(JsonArray json) {
            boolean intentFound = false;
            final int expectedAttributes = 5;
            for (int jsonIntentIndex = 0; jsonIntentIndex < json.size();
                 jsonIntentIndex++) {

                final JsonObject jsonIntent = json.get(jsonIntentIndex).asObject();

                if (jsonIntent.names().size() != expectedAttributes) {
                    reason = "Found an intent with the wrong number of attributes";
                    return false;
                }

                final String jsonIntentId = jsonIntent.get("id").asString();
                if (jsonIntentId.equals(intent.id().toString())) {
                    intentFound = true;

                    //  We found the correct intent, check attribute values
                    assertThat(jsonIntent, matchesIntent(intent));
                }
            }
            if (!intentFound) {
                reason = "Intent with id " + intent.id().toString() + " not found";
                return false;
            } else {
                return true;
            }
        }

        @Override
        public void describeTo(Description description) {
            description.appendText(reason);
        }
    }

    /**
     * Factory to allocate an intent array matcher.
     *
     * @param intent intent object we are looking for
     * @return matcher
     */
    private static IntentJsonArrayMatcher hasIntent(Intent intent) {
        return new IntentJsonArrayMatcher(intent);
    }

    /**
     * Initializes test mocks and environment.
     */
    @Before
    public void setUpTest() {
        expect(mockIntentService.getIntents()).andReturn(intents).anyTimes();
        expect(mockIntentService.getIntentState(anyObject()))
                .andReturn(IntentState.INSTALLED)
                .anyTimes();
        // Register the services needed for the test
        final CodecManager codecService =  new CodecManager();
        codecService.activate();
        ServiceDirectory testDirectory =
                new TestServiceDirectory()
                        .add(IntentService.class, mockIntentService)
                        .add(FlowRuleService.class, mockFlowService)
                        .add(CodecService.class, codecService)
                        .add(CoreService.class, mockCoreService);

        BaseResource.setServiceDirectory(testDirectory);

        bindNewGenerator();
    }

    /**
     * Tears down and verifies test mocks and environment.
     */
    @After
    public void tearDownTest() {
        verify(mockIntentService);
    }

    /**
     * Tests the result of the rest api GET when there are no intents.
     */
    @Test
    public void testIntentsEmptyArray() {
        replay(mockIntentService);
        final WebTarget wt = target();
        final String response = wt.path("intents").request().get(String.class);
        assertThat(response, is("{\"intents\":[]}"));
    }

    /**
     * Tests the result of the rest api GET when intents are defined.
     */
    @Test
    public void testIntentsArray() {
        replay(mockIntentService);

        final Intent intent1 = new MockIntent(1L, Collections.emptyList());
        final HashSet<NetworkResource> resources = new HashSet<>();
        resources.add(new MockResource(1));
        resources.add(new MockResource(2));
        resources.add(new MockResource(3));
        final Intent intent2 = new MockIntent(2L, resources);

        intents.add(intent1);
        intents.add(intent2);
        final WebTarget wt = target();
        final String response = wt.path("intents").request().get(String.class);
        assertThat(response, containsString("{\"intents\":["));

        final JsonObject result = Json.parse(response).asObject();
        assertThat(result, notNullValue());

        assertThat(result.names(), hasSize(1));
        assertThat(result.names().get(0), is("intents"));

        final JsonArray jsonIntents = result.get("intents").asArray();
        assertThat(jsonIntents, notNullValue());

        assertThat(jsonIntents, hasIntent(intent1));
        assertThat(jsonIntents, hasIntent(intent2));
    }

    /**
     * Tests the result of a rest api GET for a single intent.
     */
    @Test
    public void testIntentsSingle() {
        final HashSet<NetworkResource> resources = new HashSet<>();
        resources.add(new MockResource(1));
        resources.add(new MockResource(2));
        resources.add(new MockResource(3));
        final Intent intent = new MockIntent(3L, resources);

        intents.add(intent);

        expect(mockIntentService.getIntent(Key.of(0, APP_ID)))
                .andReturn(intent)
                .anyTimes();
        expect(mockIntentService.getIntent(Key.of("0", APP_ID)))
                .andReturn(intent)
                .anyTimes();
        expect(mockIntentService.getIntent(Key.of(0, APP_ID)))
                .andReturn(intent)
                .anyTimes();
        expect(mockIntentService.getIntent(Key.of("0x0", APP_ID)))
                .andReturn(null)
                .anyTimes();
        replay(mockIntentService);
        expect(mockCoreService.getAppId(APP_ID.name()))
                .andReturn(APP_ID).anyTimes();
        replay(mockCoreService);
        final WebTarget wt = target();

        // Test get using key string
        final String response = wt.path("intents/" + APP_ID.name()
                + "/0").request().get(String.class);
        final JsonObject result = Json.parse(response).asObject();
        assertThat(result, matchesIntent(intent));

        // Test get using numeric value
        final String responseNumeric = wt.path("intents/" + APP_ID.name()
                + "/0x0").request().get(String.class);
        final JsonObject resultNumeric = Json.parse(responseNumeric).asObject();
        assertThat(resultNumeric, matchesIntent(intent));
    }

    /**
     * Tests the result of a rest api GET for related flows for single intent.
     */
    @Test
    public void testRelatedFlowsForIntents() {
        List<FlowEntry> flowEntries = new ArrayList<>();
        flowEntries.add(flow1);
        flowEntries.add(flow2);
        List<List<FlowEntry>> paths = new ArrayList<>();
        paths.add(flowEntries);
        List<FlowRule> flowRules = new ArrayList<>();
        flowRules.add(flowRule1);
        flowRules.add(flowRule2);
        FlowRuleIntent flowRuleIntent = new FlowRuleIntent(
                APP_ID,
                flowRules,
                new HashSet<NetworkResource>());
        Intent intent = new MockIntent(3L);
        installableIntents.add(flowRuleIntent);
        intents.add(intent);

        expect(mockIntentService.getIntent(Key.of(0, APP_ID)))
                .andReturn(intent)
                .anyTimes();
        expect(mockIntentService.getIntent(Key.of("0", APP_ID)))
                .andReturn(intent)
                .anyTimes();
        expect(mockIntentService.getIntent(Key.of(0, APP_ID)))
                .andReturn(intent)
                .anyTimes();
        expect(mockIntentService.getIntent(Key.of("0x0", APP_ID)))
                .andReturn(null)
                .anyTimes();
        expect(mockIntentService.getInstallableIntents(intent.key()))
                .andReturn(installableIntents)
                .anyTimes();
        replay(mockIntentService);

        expect(mockFlowService.getFlowEntries(deviceId1))
                .andReturn(flowEntries).anyTimes();
        replay(mockFlowService);

        expect(mockCoreService.getAppId(APP_ID.name()))
                .andReturn(APP_ID).anyTimes();
        expect(mockCoreService.getAppId(APP_ID.id()))
                .andReturn(APP_ID).anyTimes();
        replay(mockCoreService);

        final WebTarget wt = target();

        // Test get using key string
        final String response = wt.path("intents/relatedflows/" + APP_ID.name()
                + "/0").request().get(String.class);
        final JsonObject result = Json.parse(response).asObject();
        assertThat(result, matchesRelatedFlowEntries(paths, APP_ID.name()));

        // Test get using numeric value
        final String responseNumeric = wt.path("intents/relatedflows/" + APP_ID.name()
                + "/0x0").request().get(String.class);
        final JsonObject resultNumeric = Json.parse(responseNumeric).asObject();
        assertThat(resultNumeric, matchesRelatedFlowEntries(paths, APP_ID.name()));
    }

    /**
     * Tests that a fetch of a non-existent intent object throws an exception.
     */
    @Test
    public void testBadGet() {

        expect(mockIntentService.getIntent(Key.of(0, APP_ID)))
                .andReturn(null)
                .anyTimes();
        replay(mockIntentService);

        WebTarget wt = target();
        try {
            wt.path("intents/0").request().get(String.class);
            fail("Fetch of non-existent intent did not throw an exception");
        } catch (NotFoundException ex) {
            assertThat(ex.getMessage(),
                    containsString("HTTP 404 Not Found"));
        }
    }

    /**
     * Tests creating an intent with POST.
     */
    @Test
    public void testPost() {
        ApplicationId testId = new DefaultApplicationId(2, "myApp");
        expect(mockCoreService.getAppId("myApp"))
                .andReturn(testId);
        replay(mockCoreService);

        mockIntentService.submit(anyObject());
        expectLastCall();
        replay(mockIntentService);

        InputStream jsonStream = IntentsResourceTest.class
                .getResourceAsStream("post-intent.json");
        WebTarget wt = target();

        Response response = wt.path("intents")
                .request(MediaType.APPLICATION_JSON_TYPE)
                .post(Entity.json(jsonStream));
        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
        String location = response.getLocation().getPath();
        assertThat(location, Matchers.startsWith("/intents/myApp/"));
    }

    /**
     * Tests creating an intent with POST and illegal JSON.
     */
    @Test
    public void testBadPost() {
        replay(mockCoreService);
        replay(mockIntentService);

        String json = "this is invalid!";
        WebTarget wt = target();

        Response response = wt.path("intents")
                .request(MediaType.APPLICATION_JSON_TYPE)
                .post(Entity.json(json));
        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_BAD_REQUEST));
    }

    /**
     * Tests removing an intent with DELETE.
     */
    @Test
    public void testRemove() {
        final HashSet<NetworkResource> resources = new HashSet<>();
        resources.add(new MockResource(1));
        resources.add(new MockResource(2));
        resources.add(new MockResource(3));
        final Intent intent = new MockIntent(3L, resources);
        final ApplicationId appId = new DefaultApplicationId(2, "app");
        IntentService fakeManager = new FakeIntentManager();

        expect(mockCoreService.getAppId("app"))
                .andReturn(appId).once();
        replay(mockCoreService);

        mockIntentService.withdraw(anyObject());
        expectLastCall().andDelegateTo(fakeManager).once();
        expect(mockIntentService.getIntent(Key.of(2, appId)))
                .andReturn(intent)
                .once();
        expect(mockIntentService.getIntent(Key.of("0x2", appId)))
                .andReturn(null)
                .once();

        mockIntentService.addListener(anyObject());
        expectLastCall().andDelegateTo(fakeManager).once();
        mockIntentService.removeListener(anyObject());
        expectLastCall().andDelegateTo(fakeManager).once();

        replay(mockIntentService);

        WebTarget wt = target();

        Response response = wt.path("intents/app/0x2")
                .request(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN)
                .delete();
        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
    }

    /**
     * Tests removal of a non existent intent with DELETE.
     */
    @Test
    public void testBadRemove() {
        final ApplicationId appId = new DefaultApplicationId(2, "app");

        expect(mockCoreService.getAppId("app"))
                .andReturn(appId).once();
        replay(mockCoreService);

        expect(mockIntentService.getIntent(Key.of(2, appId)))
                .andReturn(null)
                .once();
        expect(mockIntentService.getIntent(Key.of("0x2", appId)))
                .andReturn(null)
                .once();

        replay(mockIntentService);

        WebTarget wt = target();

        Response response = wt.path("intents/app/0x2")
                .request(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN)
                .delete();
        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
    }

}
