/*
 * Copyright 2014-2015 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.ImmutableSet;
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.After;
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.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.codec.impl.GroupCodec;
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.net.DefaultDevice;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.NetTestTools;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.group.DefaultGroupKey;
import org.onosproject.net.group.Group;
import org.onosproject.net.group.GroupBucket;
import org.onosproject.net.group.GroupBuckets;
import org.onosproject.net.group.GroupDescription;
import org.onosproject.net.group.GroupKey;
import org.onosproject.net.group.GroupService;
import org.onosproject.rest.resources.CoreWebApplication;

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

import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.anyShort;
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;
import static org.junit.Assert.assertEquals;
import static org.onosproject.net.NetTestTools.APP_ID;

/**
 * Unit tests for Groups REST APIs.
 */
public class GroupsResourceTest extends ResourceTest {
    final GroupService mockGroupService = createMock(GroupService.class);
    CoreService mockCoreService = createMock(CoreService.class);
    final DeviceService mockDeviceService = createMock(DeviceService.class);

    final HashMap<DeviceId, Set<Group>> groups = new HashMap<>();


    final DeviceId deviceId1 = DeviceId.deviceId("1");
    final DeviceId deviceId2 = DeviceId.deviceId("2");
    final DeviceId deviceId3 = DeviceId.deviceId("3");
    final Device device1 = new DefaultDevice(null, deviceId1, Device.Type.OTHER,
            "", "", "", "", null);
    final Device device2 = new DefaultDevice(null, deviceId2, Device.Type.OTHER,
            "", "", "", "", null);

    final MockGroup group1 = new MockGroup(deviceId1, 1, "111", 1);
    final MockGroup group2 = new MockGroup(deviceId1, 2, "222", 2);

    final MockGroup group3 = new MockGroup(deviceId2, 3, "333", 3);
    final MockGroup group4 = new MockGroup(deviceId2, 4, "444", 4);

    final MockGroup group5 = new MockGroup(deviceId3, 5, "555", 5);
    final MockGroup group6 = new MockGroup(deviceId3, 6, "666", 6);

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

    /**
     * Mock class for a group.
     */
    private static class MockGroup implements Group {

        final DeviceId deviceId;
        final ApplicationId appId;
        final GroupKey appCookie;
        final long baseValue;
        final List<GroupBucket> bucketList;
        GroupBuckets buckets;

        public MockGroup(DeviceId deviceId, int appId, String appCookie, int id) {
            this.deviceId = deviceId;
            this.appId = new DefaultApplicationId(appId, String.valueOf(appId));
            this.appCookie = new DefaultGroupKey(appCookie.getBytes());
            this.baseValue = id * 100;
            this.bucketList = new ArrayList<>();
            this.buckets = new GroupBuckets(bucketList);
        }

        @Override
        public GroupId id() {
            return new DefaultGroupId((int) baseValue + 55);
        }

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

        @Override
        public long life() {
            return baseValue + 11;
        }

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

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

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

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

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

        @Override
        public ApplicationId appId() {
            return this.appId;
        }

        @Override
        public GroupKey appCookie() {
            return this.appCookie;
        }

        @Override
        public Integer givenGroupId() {
            return (int) baseValue + 55;
        }

        @Override
        public GroupBuckets buckets() {
            return this.buckets;
        }
    }

    /**
     * Populates some groups used as testing data.
     */
    private void setupMockGroups() {
        final Set<Group> groups1 = new HashSet<>();
        groups1.add(group1);
        groups1.add(group2);

        final Set<Group> groups2 = new HashSet<>();
        groups2.add(group3);
        groups2.add(group4);

        groups.put(deviceId1, groups1);
        groups.put(deviceId2, groups2);

        expect(mockGroupService.getGroups(deviceId1))
                .andReturn(groups.get(deviceId1)).anyTimes();
        expect(mockGroupService.getGroups(deviceId2))
                .andReturn(groups.get(deviceId2)).anyTimes();
    }

    /**
     * Sets up the global values for all the tests.
     */
    @Before
    public void setUpTest() {
        // Mock device service
        expect(mockDeviceService.getDevice(deviceId1))
                .andReturn(device1);
        expect(mockDeviceService.getDevice(deviceId2))
                .andReturn(device2);
        expect(mockDeviceService.getDevices())
                .andReturn(ImmutableSet.of(device1, device2));

        // Mock Core Service
        expect(mockCoreService.getAppId(anyShort()))
                .andReturn(NetTestTools.APP_ID).anyTimes();
        expect(mockCoreService.registerApplication(GroupCodec.REST_APP_ID))
                .andReturn(APP_ID).anyTimes();
        replay(mockCoreService);

        // Register the services needed for the test
        final CodecManager codecService = new CodecManager();
        codecService.activate();
        ServiceDirectory testDirectory =
                new TestServiceDirectory()
                        .add(GroupService.class, mockGroupService)
                        .add(DeviceService.class, mockDeviceService)
                        .add(CodecService.class, codecService)
                        .add(CoreService.class, mockCoreService);

        BaseResource.setServiceDirectory(testDirectory);
    }

    /**
     * Cleans up and verifies the mocks.
     */
    @After
    public void tearDownTest() {
        verify(mockGroupService);
        verify(mockCoreService);
    }

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

        public GroupJsonMatcher(Group groupValue, String expectedAppIdValue) {
            group = groupValue;
            expectedAppId = expectedAppIdValue;
        }

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

            // check application id
            final String jsonAppId = jsonGroup.get("appId").asString();
            final String appId = group.appId().toString();
            if (!jsonAppId.equals(appId)) {
                reason = "appId " + group.appId().toString();
                return false;
            }

            // check device id
            final String jsonDeviceId = jsonGroup.get("deviceId").asString();
            if (!jsonDeviceId.equals(group.deviceId().toString())) {
                reason = "deviceId " + group.deviceId();
                return false;
            }

            // check bucket array
            if (group.buckets().buckets() != null) {
                final JsonArray jsonBuckets = jsonGroup.get("buckets").asArray();
                if (group.buckets().buckets().size() != jsonBuckets.size()) {
                    reason = "buckets array size of " +
                            Integer.toString(group.buckets().buckets().size());
                    return false;
                }
                for (final GroupBucket groupBucket : group.buckets().buckets()) {
                    boolean groupBucketFound = false;
                    for (int groupBucketIndex = 0; groupBucketIndex < jsonBuckets.size(); groupBucketIndex++) {
                        final String jsonType = jsonBuckets.get(groupBucketIndex).asObject().get("type").asString();
                        final String bucketType = groupBucket.type().name();
                        if (jsonType.equals(bucketType)) {
                            groupBucketFound = true;
                        }
                    }
                    if (!groupBucketFound) {
                        reason = "group bucket " + groupBucket.toString();
                        return false;
                    }
                }
            }

            return true;
        }

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

    /**
     * Factory to allocate a group matcher.
     *
     * @param group group object we are looking for
     * @return matcher
     */
    private static GroupJsonMatcher matchesGroup(Group group, String expectedAppName) {
        return new GroupJsonMatcher(group, expectedAppName);
    }

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

        public GroupJsonArrayMatcher(Group groupValue) {
            group = groupValue;
        }

        @Override
        public boolean matchesSafely(JsonArray json) {
            boolean groupFound = false;
            for (int jsonGroupIndex = 0; jsonGroupIndex < json.size();
                 jsonGroupIndex++) {

                final JsonObject jsonGroup = json.get(jsonGroupIndex).asObject();

                final String groupId = group.id().toString();
                final String jsonGroupId = jsonGroup.get("id").asString();
                if (jsonGroupId.equals(groupId)) {
                    groupFound = true;

                    //  We found the correct group, check attribute values
                    assertThat(jsonGroup, matchesGroup(group, APP_ID.name()));
                }
            }
            if (!groupFound) {
                reason = "Group with id " + group.id().toString() + " not found";
                return false;
            } else {
                return true;
            }
        }

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

    /**
     * Factory to allocate a group array matcher.
     *
     * @param group group object we are looking for
     * @return matcher
     */
    private static GroupJsonArrayMatcher hasGroup(Group group) {
        return new GroupJsonArrayMatcher(group);
    }

    /**
     * Tests the result of the rest api GET when there are no groups.
     */
    @Test
    public void testGroupsEmptyArray() {
        expect(mockGroupService.getGroups(deviceId1)).andReturn(null).anyTimes();
        expect(mockGroupService.getGroups(deviceId2)).andReturn(null).anyTimes();
        replay(mockGroupService);
        replay(mockDeviceService);
        final WebResource rs = resource();
        final String response = rs.path("groups").get(String.class);
        assertThat(response, is("{\"groups\":[]}"));
    }

    /**
     * Tests the result of the rest api GET when there are active groups.
     */
    @Test
    public void testGroupsPopulatedArray() {
        setupMockGroups();
        replay(mockGroupService);
        replay(mockDeviceService);
        final WebResource rs = resource();
        final String response = rs.path("groups").get(String.class);
        final JsonObject result = Json.parse(response).asObject();
        assertThat(result, notNullValue());

        assertThat(result.names(), hasSize(1));
        assertThat(result.names().get(0), is("groups"));
        final JsonArray jsonGroups = result.get("groups").asArray();
        assertThat(jsonGroups, notNullValue());
        assertThat(jsonGroups, hasGroup(group1));
        assertThat(jsonGroups, hasGroup(group2));
        assertThat(jsonGroups, hasGroup(group3));
        assertThat(jsonGroups, hasGroup(group4));
    }

    /**
     * Tests the result of a rest api GET for a device.
     */
    @Test
    public void testGroupsSingleDevice() {
        setupMockGroups();
        final Set<Group> groups = new HashSet<>();
        groups.add(group5);
        groups.add(group6);
        expect(mockGroupService.getGroups(anyObject()))
                .andReturn(groups).anyTimes();
        replay(mockGroupService);
        replay(mockDeviceService);
        final WebResource rs = resource();
        final String response = rs.path("groups/" + deviceId3).get(String.class);
        final JsonObject result = Json.parse(response).asObject();
        assertThat(result, notNullValue());

        assertThat(result.names(), hasSize(1));
        assertThat(result.names().get(0), is("groups"));
        final JsonArray jsonFlows = result.get("groups").asArray();
        assertThat(jsonFlows, notNullValue());
        assertThat(jsonFlows, hasGroup(group5));
        assertThat(jsonFlows, hasGroup(group6));
    }

    /**
     * Test the result of a rest api GET with specifying device id and appcookie.
     */
    @Test
    public void testGroupByDeviceIdAndAppCookie() {
        setupMockGroups();
        expect(mockGroupService.getGroup(anyObject(), anyObject()))
                .andReturn(group5).anyTimes();
        replay(mockGroupService);
        final WebResource rs = resource();
        final String response = rs.path("groups/" + deviceId3 + "/" + "111").get(String.class);
        final JsonObject result = Json.parse(response).asObject();
        assertThat(result, notNullValue());

        assertThat(result.names(), hasSize(1));
        assertThat(result.names().get(0), is("groups"));
        final JsonArray jsonFlows = result.get("groups").asArray();
        assertThat(jsonFlows, notNullValue());
        assertThat(jsonFlows, hasGroup(group5));
    }

    /**
     * Test whether the REST API returns 404 if no entry has been found.
     */
    @Test
    public void testGroupByDeviceIdAndAppCookieNull() {
        setupMockGroups();
        expect(mockGroupService.getGroup(anyObject(), anyObject()))
                .andReturn(null).anyTimes();
        replay(mockGroupService);
        final WebResource rs = resource();
        final ClientResponse response = rs.path("groups/" + deviceId3 + "/" + "222").get(ClientResponse.class);

        assertEquals(404, response.getStatus());
    }

    /**
     * Tests creating a group with POST.
     */
    @Test
    public void testPost() {
        mockGroupService.addGroup(anyObject());
        expectLastCall();
        replay(mockGroupService);

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

        ClientResponse response = rs.path("groups/of:0000000000000001")
                .type(MediaType.APPLICATION_JSON_TYPE)
                .post(ClientResponse.class, jsonStream);
        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
    }

    /**
     * Tests deleting a group.
     */
    @Test
    public void testDelete() {
        setupMockGroups();
        mockGroupService.removeGroup(anyObject(), anyObject(), anyObject());
        expectLastCall();
        replay(mockGroupService);

        WebResource rs = resource();

        String location = "/groups/1/111";

        ClientResponse deleteResponse = rs.path(location)
                .type(MediaType.APPLICATION_JSON_TYPE)
                .delete(ClientResponse.class);
        assertThat(deleteResponse.getStatus(),
                is(HttpURLConnection.HTTP_NO_CONTENT));
    }
}
