/*
 * 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.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import org.glassfish.jersey.client.ClientProperties;
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_NO_CONTENT));

        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 creating a flow with POST.
     */
    @Test
    public void testAddDevicesPostWithoutRegion() {
        expect(mockRegionService.getRegion(anyObject())).andReturn(null).anyTimes();
        replay(mockRegionService);

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

        Response response = wt.path("regions/" + region1.id() + "/devices")
                .request(MediaType.APPLICATION_JSON_TYPE)
                .post(Entity.json(jsonStream));
        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NOT_FOUND));

        verify(mockRegionService);
    }

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

        expect(mockRegionService.getRegion(anyObject())).andReturn(region1).anyTimes();
        replay(mockRegionService);

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

        expect(mockRegionService.getRegion(anyObject())).andReturn(region1).anyTimes();
        replay(mockRegionService);

        WebTarget wt = target()
                .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
        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().method("DELETE", Entity.json(jsonStream));
        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
        verify(mockRegionAdminService);
    }
}
