/*
 * 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.resources;

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 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 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.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);

    /**
     * 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 WebTarget wt = target();
        final String response = wt.path("regions").request().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 WebTarget wt = target();
        final String response = wt.path("regions").request().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 WebTarget wt = target();
        final String response = wt.path("regions/" + regionId1.toString()).request().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);

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

        Response response = wt.path("regions")
                .request(MediaType.APPLICATION_JSON_TYPE)
                .post(Entity.json(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);

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

        Response response = wt.path("regions/" + region1.id().toString())
                .request(MediaType.APPLICATION_JSON_TYPE)
                .put(Entity.json(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);

        WebTarget wt = target();
        Response response = wt.path("regions/" + region1.id().toString())
                .request().delete();
        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 WebTarget wt = target();
        final String response = wt.path("regions/" +
                region1.id().toString() + "/devices").request().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);

        WebTarget wt = target();
        InputStream jsonStream = RegionsResourceTest.class
                .getResourceAsStream("region-deviceIds.json");

        Response response = wt.path("regions/" +
                region1.id().toString() + "/devices")
                .request(MediaType.APPLICATION_JSON_TYPE)
                .post(Entity.json(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);


        WebTarget wt = target();
        InputStream jsonStream = RegionsResourceTest.class
                .getResourceAsStream("region-deviceIds.json");

        // FIXME: need to consider whether to use jsonStream for entry deletion
        Response response = wt.path("regions/" +
                region1.id().toString() + "/devices")
                .request(MediaType.APPLICATION_JSON_TYPE)
                .delete();
        // assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
        // verify(mockRegionAdminService);
    }
}
