/*
 * Copyright 2016 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;

import com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonArray;
import com.eclipsesource.json.JsonObject;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;
import org.junit.Before;
import org.junit.Test;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
import org.onlab.rest.BaseResource;
import org.onosproject.cluster.NodeId;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.net.DeviceId;
import org.onosproject.net.region.Region;
import org.onosproject.net.region.RegionAdminService;
import org.onosproject.net.region.RegionId;
import org.onosproject.net.region.RegionService;
import org.onosproject.rest.resources.CoreWebApplication;

import javax.ws.rs.core.MediaType;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.util.List;
import java.util.Set;

import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;

/**
 * Unit tests for region REST APIs.
 */
public class RegionsResourceTest extends ResourceTest {

    final RegionService mockRegionService = createMock(RegionService.class);
    final RegionAdminService mockRegionAdminService = createMock(RegionAdminService.class);

    final RegionId regionId1 = RegionId.regionId("1");
    final RegionId regionId2 = RegionId.regionId("2");
    final RegionId regionId3 = RegionId.regionId("3");

    final MockRegion region1 = new MockRegion(regionId1, "r1", Region.Type.RACK);
    final MockRegion region2 = new MockRegion(regionId2, "r2", Region.Type.ROOM);
    final MockRegion region3 = new MockRegion(regionId3, "r3", Region.Type.CAMPUS);

    public RegionsResourceTest() {
        super(CoreWebApplication.class);
    }

    /**
     * Mock class for a region.
     */
    private static class MockRegion implements Region {

        private final RegionId id;
        private final String name;
        private final Type type;
        private final List<Set<NodeId>> masters;

        public MockRegion(RegionId id, String name, Type type) {
            this.id = id;
            this.name = name;
            this.type = type;

            final NodeId nodeId1 = NodeId.nodeId("1");
            final NodeId nodeId2 = NodeId.nodeId("2");
            final NodeId nodeId3 = NodeId.nodeId("3");
            final NodeId nodeId4 = NodeId.nodeId("4");

            Set<NodeId> nodeIds1 = ImmutableSet.of(nodeId1);
            Set<NodeId> nodeIds2 = ImmutableSet.of(nodeId1, nodeId2);
            Set<NodeId> nodeIds3 = ImmutableSet.of(nodeId1, nodeId2, nodeId3);
            Set<NodeId> nodeIds4 = ImmutableSet.of(nodeId1, nodeId2, nodeId3, nodeId4);

            this.masters = ImmutableList.of(nodeIds1, nodeIds2, nodeIds3, nodeIds4);
        }

        @Override
        public RegionId id() {
            return this.id;
        }

        @Override
        public String name() {
            return this.name;
        }

        @Override
        public Type type() {
            return this.type;
        }

        @Override
        public List<Set<NodeId>> masters() {
            return this.masters;
        }
    }

    /**
     * Sets up the global values for all the tests.
     */
    @Before
    public void setupTest() {
        final CodecManager codecService = new CodecManager();
        codecService.activate();
        ServiceDirectory testDirectory =
                new TestServiceDirectory()
                .add(RegionService.class, mockRegionService)
                .add(RegionAdminService.class, mockRegionAdminService)
                .add(CodecService.class, codecService);
        BaseResource.setServiceDirectory(testDirectory);
    }

    /**
     * Hamcrest matcher to check that a region representation in JSON matches
     * the actual region.
     */
    public static class RegionJsonMatcher extends TypeSafeMatcher<JsonObject> {
        private final Region region;
        private String reason = "";

        public RegionJsonMatcher(Region regionValue) {
            this.region = regionValue;
        }

        @Override
        protected boolean matchesSafely(JsonObject jsonRegion) {

            // check id
            String jsonRegionId = jsonRegion.get("id").asString();
            String regionId = region.id().toString();
            if (!jsonRegionId.equals(regionId)) {
                reason = "region id was " + jsonRegionId;
                return false;
            }

            // check type
            String jsonType = jsonRegion.get("type").asString();
            String type = region.type().toString();
            if (!jsonType.equals(type)) {
                reason = "type was " + jsonType;
                return false;
            }

            // check name
            String jsonName = jsonRegion.get("name").asString();
            String name = region.name();
            if (!jsonName.equals(name)) {
                reason = "name was " + jsonName;
                return false;
            }

            // check size of master array
            JsonArray jsonMasters = jsonRegion.get("masters").asArray();
            if (jsonMasters.size() != region.masters().size()) {
                reason = "masters size was " + jsonMasters.size();
                return false;
            }

            // check master
            for (Set<NodeId> set : region.masters()) {
                boolean masterFound = false;
                for (int masterIndex = 0; masterIndex < jsonMasters.size(); masterIndex++) {
                    masterFound = checkEquality(jsonMasters.get(masterIndex).asArray(), set);
                }

                if (!masterFound) {
                    reason = "master not found " + set.toString();
                    return false;
                }
            }

            return true;
        }

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

        private Set<NodeId> jsonToSet(JsonArray nodes) {
            final Set<NodeId> nodeIds = Sets.newHashSet();
            nodes.forEach(node -> nodeIds.add(NodeId.nodeId(node.asString())));
            return nodeIds;
        }

        private boolean checkEquality(JsonArray nodes, Set<NodeId> nodeIds) {
            Set<NodeId> jsonSet = jsonToSet(nodes);
            if (jsonSet.size() == nodes.size()) {
                return jsonSet.containsAll(nodeIds);
            }
            return false;
        }
    }

    private static RegionJsonMatcher matchesRegion(Region region) {
        return new RegionJsonMatcher(region);
    }

    /**
     * Hamcrest matcher to check that a region is represented properly in a JSON
     * array of regions.
     */
    public static class RegionJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
        private final Region region;
        private String reason = "";

        public RegionJsonArrayMatcher(Region regionValue) {
            this.region = regionValue;
        }

        @Override
        protected boolean matchesSafely(JsonArray json) {
            boolean regionFound = false;
            for (int jsonRegionIndex = 0; jsonRegionIndex < json.size(); jsonRegionIndex++) {
                final JsonObject jsonRegion = json.get(jsonRegionIndex).asObject();

                final String regionId = region.id().toString();
                final String jsonRegionId = jsonRegion.get("id").asString();
                if (jsonRegionId.equals(regionId)) {
                    regionFound = true;
                    assertThat(jsonRegion, matchesRegion(region));
                }
            }

            if (!regionFound) {
                reason = "Region with id " + region.id().toString() + " not found";
                return false;
            } else {
                return true;
            }
        }

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

    /**
     * Factory to allocate a region array matcher.
     *
     * @param region region object we are looking for
     * @return matcher
     */
    private static RegionJsonArrayMatcher hasRegion(Region region) {
        return new RegionJsonArrayMatcher(region);
    }

    @Test
    public void testRegionEmptyArray() {
        expect(mockRegionService.getRegions()).andReturn(ImmutableSet.of()).anyTimes();
        replay((mockRegionService));
        final WebResource rs = resource();
        final String response = rs.path("regions").get(String.class);
        assertThat(response, is("{\"regions\":[]}"));

        verify(mockRegionService);
    }

    /**
     * Tests the results of the REST API GET when there are active regions.
     */
    @Test
    public void testRegionsPopulatedArray() {
        final Set<Region> regions = ImmutableSet.of(region1, region2, region3);
        expect(mockRegionService.getRegions()).andReturn(regions).anyTimes();
        replay(mockRegionService);

        final WebResource rs = resource();
        final String response = rs.path("regions").get(String.class);
        final JsonObject result = Json.parse(response).asObject();
        assertThat(result, notNullValue());

        assertThat(result.names(), hasSize(1));
        assertThat(result.names().get(0), is("regions"));
        final JsonArray jsonRegions = result.get("regions").asArray();
        assertThat(jsonRegions, notNullValue());
        assertThat(jsonRegions, hasRegion(region1));
        assertThat(jsonRegions, hasRegion(region2));
        assertThat(jsonRegions, hasRegion(region3));

        verify(mockRegionService);

    }

    /**
     * Tests the result of a REST API GET for a region with region id.
     */
    @Test
    public void testGetRegionById() {
        expect(mockRegionService.getRegion(anyObject())).andReturn(region1).anyTimes();
        replay(mockRegionService);

        final WebResource rs = resource();
        final String response = rs.path("regions/" + regionId1.toString()).get(String.class);
        final JsonObject result = Json.parse(response).asObject();
        assertThat(result, notNullValue());
        assertThat(result, matchesRegion(region1));

        verify(mockRegionService);
    }

    /**
     * Tests creating a region with POST.
     */
    @Test
    public void testRegionPost() {
        mockRegionAdminService.createRegion(anyObject(), anyObject(),
                anyObject(), anyObject());
        expectLastCall().andReturn(region2).anyTimes();
        replay(mockRegionAdminService);

        WebResource rs = resource();
        InputStream jsonStream = RegionsResourceTest.class
                .getResourceAsStream("post-region.json");

        ClientResponse response = rs.path("regions")
                .type(MediaType.APPLICATION_JSON_TYPE)
                .post(ClientResponse.class, jsonStream);
        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));

        verify(mockRegionAdminService);
    }

    /**
     * Tests updating a region with PUT.
     */
    @Test
    public void testRegionPut() {
        mockRegionAdminService.updateRegion(anyObject(), anyObject(),
                anyObject(), anyObject());
        expectLastCall().andReturn(region1).anyTimes();
        replay(mockRegionAdminService);

        WebResource rs = resource();
        InputStream jsonStream = RegionsResourceTest.class
                .getResourceAsStream("post-region.json");

        ClientResponse response = rs.path("regions/" + region1.id().toString())
                .type(MediaType.APPLICATION_JSON_TYPE)
                .put(ClientResponse.class, jsonStream);
        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));

        verify(mockRegionAdminService);
    }

    /**
     * Tests deleting a region with DELETE.
     */
    @Test
    public void testRegionDelete() {
        mockRegionAdminService.removeRegion(anyObject());
        expectLastCall();
        replay(mockRegionAdminService);

        WebResource rs = resource();
        ClientResponse response = rs.path("regions/" + region1.id().toString())
                .delete(ClientResponse.class);
        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));

        verify(mockRegionAdminService);
    }

    /**
     * Tests retrieving device ids that are associated with the given region.
     */
    @Test
    public void testGetRegionDevices() {
        final DeviceId deviceId1 = DeviceId.deviceId("1");
        final DeviceId deviceId2 = DeviceId.deviceId("2");
        final DeviceId deviceId3 = DeviceId.deviceId("3");

        final Set<DeviceId> deviceIds = ImmutableSet.of(deviceId1, deviceId2, deviceId3);

        expect(mockRegionService.getRegionDevices(anyObject()))
                .andReturn(deviceIds).anyTimes();
        replay(mockRegionService);

        final WebResource rs = resource();
        final String response = rs.path("regions/" +
                region1.id().toString() + "/devices").get(String.class);
        final JsonObject result = Json.parse(response).asObject();
        assertThat(result, notNullValue());

        assertThat(result.names(), hasSize(1));
        assertThat(result.names().get(0), is("deviceIds"));
        final JsonArray jsonDeviceIds = result.get("deviceIds").asArray();
        assertThat(jsonDeviceIds.size(), is(3));
        assertThat(jsonDeviceIds.get(0).asString(), is("1"));
        assertThat(jsonDeviceIds.get(1).asString(), is("2"));
        assertThat(jsonDeviceIds.get(2).asString(), is("3"));

        verify(mockRegionService);
    }

    /**
     * Tests adding a set of devices in region with POST.
     */
    @Test
    public void testAddDevicesPost() {
        mockRegionAdminService.addDevices(anyObject(), anyObject());
        expectLastCall();
        replay(mockRegionAdminService);

        WebResource rs = resource();
        InputStream jsonStream = RegionsResourceTest.class
                .getResourceAsStream("region-deviceIds.json");

        ClientResponse response = rs.path("regions/" +
                region1.id().toString() + "/devices")
                .type(MediaType.APPLICATION_JSON_TYPE)
                .post(ClientResponse.class, jsonStream);
        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));

        verify(mockRegionAdminService);
    }

    /**
     * Tests deleting a set of devices contained in the given region with DELETE.
     */
    @Test
    public void testRemoveDevicesDelete() {
        mockRegionAdminService.removeDevices(anyObject(), anyObject());
        expectLastCall();
        replay(mockRegionAdminService);

        WebResource rs = resource();
        InputStream jsonStream = RegionsResourceTest.class
                .getResourceAsStream("region-deviceIds.json");

        ClientResponse response = rs.path("regions/" +
                region1.id().toString() + "/devices")
                .type(MediaType.APPLICATION_JSON_TYPE)
                .delete(ClientResponse.class, jsonStream);
        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));

        verify(mockRegionAdminService);
    }
}
