/*
 * Copyright 2016-present Open Networking Foundation
 *
 * 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 org.hamcrest.Description;
import org.hamcrest.Matchers;
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.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.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.net.group.GroupServiceAdapter;

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.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.assertEquals;
import static org.junit.Assert.assertThat;
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, "0x111", 1);
    final MockGroup group2 = new MockGroup(deviceId1, 2, "0x222", 2);

    final MockGroup group3 = new MockGroup(deviceId2, 3, "0x333", 3);
    final MockGroup group4 = new MockGroup(deviceId2, 4, "0x444", 4);

    final MockGroup group5 = new MockGroup(deviceId3, 5, "0x555", 5);
    final MockGroup group6 = new MockGroup(deviceId3, 6, "0x666", 6);

    /**
     * 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 * 100L;
            this.bucketList = new ArrayList<>();
            this.buckets = new GroupBuckets(bucketList);
        }

        @Override
        public GroupId id() {
            return new GroupId((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 int age() {
            return 0;
        }

        @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;
        }

        @Override
        public int failedRetryCount() {
            return 0;
        }
    }

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

        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 Long jsonId = jsonGroup.get("id").asLong();
            final String groupId = group.id().id().toString();
            if (!jsonId.equals(Long.valueOf(groupId))) {
                reason = "id " + group.id().id().toString();
                return false;
            }

            // check application id
            final String jsonAppId = jsonGroup.get("appId").asString();
            final String appId = group.appId().name();
            if (!jsonAppId.equals(appId)) {
                reason = "appId " + group.appId().name();
                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().id().toString();
                final Long jsonGroupId = jsonGroup.get("id").asLong();
                if (jsonGroupId.equals(Long.valueOf(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().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 WebTarget wt = target();
        final String response = wt.path("groups").request().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 WebTarget wt = target();
        final String response = wt.path("groups").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("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 WebTarget wt = target();
        final String response = wt.path("groups/" + deviceId3).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("groups"));
        final JsonArray jsonGroups = result.get("groups").asArray();
        assertThat(jsonGroups, notNullValue());
        assertThat(jsonGroups, hasGroup(group5));
        assertThat(jsonGroups, 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 WebTarget wt = target();
        final String response = wt.path("groups/" + deviceId3 + "/" + "0x111")
                .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("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 WebTarget wt = target();
        final Response response = wt.path("groups/" + deviceId3 + "/" + "0x222").request().get();

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

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

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

        Response response = wt.path("groups/of:0000000000000001")
                .request(MediaType.APPLICATION_JSON_TYPE)
                .post(Entity.json(jsonStream));
        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
        String location = response.getLocation().getPath();
        assertThat(location, Matchers.startsWith("/groups/of:0000000000000001/"));
    }

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

        WebTarget wt = target();

        String location = "/groups/1/0x111";

        Response deleteResponse = wt.path(location)
                .request(MediaType.APPLICATION_JSON_TYPE)
                .delete();
        assertThat(deleteResponse.getStatus(),
                is(HttpURLConnection.HTTP_NO_CONTENT));
    }

    private JsonArray fetchAndCheckBuckets(DeviceId deviceId, int expectedBucketCount) {
        WebTarget wt = target();
        final String fetchGroupPath = wt.path("groups/" + deviceId).request().get(String.class);
        final JsonObject result = Json.parse(fetchGroupPath).asObject();
        assertThat(result, notNullValue());
        assertThat(result.names(), hasSize(1));
        assertThat(result.names().get(0), is("groups"));
        JsonArray jsonGroups = result.get("groups").asArray();
        assertThat(jsonGroups, notNullValue());
        JsonObject group = jsonGroups.get(0).asObject();
        JsonArray buckets = group.get("buckets").asArray();
        assertThat(buckets.size(), is(expectedBucketCount));
        return buckets;
    }

    private void removeBucketsViaRest(String endpointPath) {
        WebTarget wt = target();
        Response removeResponse = wt.path(endpointPath)
                .request(MediaType.APPLICATION_JSON_TYPE)
                .delete();
        assertThat(removeResponse.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
    }


    class TestGroupService extends GroupServiceAdapter {
        @Override
        public void addBucketsToGroup(DeviceId deviceId, GroupKey oldCookie, GroupBuckets buckets,
                                      GroupKey newCookie, ApplicationId appId) {
            group1.buckets = buckets;
        }

        @Override
        public void removeBucketsFromGroup(DeviceId deviceId, GroupKey oldCookie, GroupBuckets buckets,
                                      GroupKey newCookie, ApplicationId appId) {
            if (!group1.buckets.buckets().isEmpty()) {
                ArrayList<GroupBucket> newList = new ArrayList<>(group1.buckets.buckets());
                for (GroupBucket bucketToRemove : buckets.buckets()) {
                    for (GroupBucket bucketToCheck : group1.buckets.buckets()) {
                        if (bucketToCheck.equals(bucketToRemove)) {
                            newList.remove(bucketToCheck);
                        }
                    }
                }
                group1.buckets = new GroupBuckets(newList);
            }
        }

        @Override
        public Group getGroup(DeviceId deviceId, GroupKey appCookie) {
            return group1;
        }

        @Override
        public Iterable<Group> getGroups(DeviceId deviceId) {
            return ImmutableList.of(group1);
        }
    }

    /**
     * Tests adding and removing buckets.
     */
    @Test
    public void testAddRemoveBucket() {
        String deviceIdBasePath = "groups/%s/";
        String endpointBasePath = deviceIdBasePath + "%s/buckets/";
        TestGroupService groupService = new TestGroupService();
        expect(mockGroupService.getGroup(anyObject(), anyObject()))
                .andDelegateTo(groupService).anyTimes();
        expect(mockGroupService.getGroups(anyObject()))
                .andDelegateTo(groupService).anyTimes();
        mockGroupService.addBucketsToGroup(anyObject(), anyObject(), anyObject(), anyObject(), anyObject());
        expectLastCall().andDelegateTo(groupService).anyTimes();
        mockGroupService.removeBucketsFromGroup(anyObject(), anyObject(), anyObject(), anyObject(), anyObject());
        expectLastCall().andDelegateTo(groupService).anyTimes();
        replay(mockGroupService);

        WebTarget wt = target();

        // Add buckets
        String addEndpointPath = String.format(endpointBasePath, group1.deviceId(), group1.appCookie());
        InputStream addJsonStream = GroupsResourceTest.class
                .getResourceAsStream("post-group-add-buckets.json");

        Response addResponse = wt.path(addEndpointPath)
                .request(MediaType.APPLICATION_JSON_TYPE)
                .post(Entity.json(addJsonStream));
        assertThat(addResponse.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));

        // Check that buckets are there
        JsonArray bucketsAfterAdd = fetchAndCheckBuckets(deviceId1, 4);

        String bucketId1 = Long.toString(bucketsAfterAdd.get(0).asObject().get("bucketId").asLong());
        String bucketId2 = Long.toString(bucketsAfterAdd.get(1).asObject().get("bucketId").asLong());
        String bucketId3 = Long.toString(bucketsAfterAdd.get(2).asObject().get("bucketId").asLong());
        String bucketId4 = Long.toString(bucketsAfterAdd.get(3).asObject().get("bucketId").asLong());

        // Remove one bucket
        String removeEndpointPath = addEndpointPath + bucketId1;
        removeBucketsViaRest(removeEndpointPath);
        fetchAndCheckBuckets(deviceId1, 3);

        // Remove two buckets
        String removeTwoEndpointPath = addEndpointPath + bucketId2 + ',' + bucketId3;
        removeBucketsViaRest(removeTwoEndpointPath);
        fetchAndCheckBuckets(deviceId1, 1);

        // Remove nothing - non-existent bucket id
        String removeNothingEndpointPath = addEndpointPath + "no-such-bucket";
        removeBucketsViaRest(removeNothingEndpointPath);
        fetchAndCheckBuckets(deviceId1, 1);

        // Remove last bucket - bucket list should be empty
        String lastOneEndpointPath = addEndpointPath + bucketId4;
        removeBucketsViaRest(lastOneEndpointPath);
        fetchAndCheckBuckets(deviceId1, 0);
    }

}
