/*
 * 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 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);
    }
}
