/*
 * 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.apache.commons.lang3.StringUtils;
import org.hamcrest.Description;
import org.hamcrest.Matchers;
import org.hamcrest.TypeSafeMatcher;
import org.junit.Before;
import org.junit.Test;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
import org.onosproject.cluster.NodeId;
import org.onosproject.cluster.RoleInfo;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.mastership.MastershipAdminService;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.MastershipRole;
import org.onosproject.net.device.DeviceService;

import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
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.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.MastershipRole.MASTER;

/**
 * Unit tests for Mastership REST APIs.
 */
public final class MastershipResourceTest extends ResourceTest {

    private final MastershipService mockService = createMock(MastershipService.class);
    private final DeviceService mockDeviceService = createMock(DeviceService.class);
    private final MastershipAdminService mockAdminService =
                  createMock(MastershipAdminService.class);

    private final DeviceId deviceId1 = DeviceId.deviceId("dev:1");
    private final DeviceId deviceId2 = DeviceId.deviceId("dev:2");
    private final DeviceId deviceId3 = DeviceId.deviceId("dev:3");

    final Device device1 = new DefaultDevice(null, deviceId1, Device.Type.OTHER,
            "", "", "", "", null);
    private final NodeId nodeId1 = NodeId.nodeId("node:1");
    private final NodeId nodeId2 = NodeId.nodeId("node:2");
    private final NodeId nodeId3 = NodeId.nodeId("node:3");
    private final MastershipRole role1 = MASTER;

    /**
     * Creates a mock role info which is comprised of one master and three backups.
     *
     * @return a mock role info instance
     */
    private RoleInfo createMockRoleInfo() {
        NodeId master = NodeId.nodeId("master");
        List<NodeId> backups = ImmutableList.of(nodeId1, nodeId2, nodeId3);

        return new RoleInfo(master, backups);
    }

    private static final class RoleInfoJsonMatcher extends TypeSafeMatcher<JsonObject> {
        private final RoleInfo roleInfo;
        private String reason = "";

        private RoleInfoJsonMatcher(RoleInfo roleInfo) {
            this.roleInfo = roleInfo;
        }

        @Override
        protected boolean matchesSafely(JsonObject jsonNode) {

            // check master node identifier
            String jsonNodeId = jsonNode.get("master") != null ?
                                jsonNode.get("master").asString() : null;
            String nodeId = roleInfo.master().id();
            if (!StringUtils.equals(jsonNodeId, nodeId)) {
                reason = "master's node id was " + jsonNodeId;
                return false;
            }

            // check backup nodes size
            final JsonArray jsonBackupNodeIds = jsonNode.get("backups").asArray();
            if (jsonBackupNodeIds.size() != roleInfo.backups().size()) {
                reason = "backup nodes size was " + jsonBackupNodeIds.size();
                return false;
            }

            // check backup nodes' identifier
            for (NodeId backupNodeId : roleInfo.backups()) {
                boolean backupFound = false;
                for (int idx = 0; idx < jsonBackupNodeIds.size(); idx++) {
                    if (backupNodeId.id().equals(jsonBackupNodeIds.get(idx).asString())) {
                        backupFound = true;
                        break;
                    }
                }
                if (!backupFound) {
                    reason = "backup not found " + backupNodeId.id();
                    return false;
                }
            }

            return true;
        }

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

    /**
     * Factory to allocate a role info json matcher.
     *
     * @param roleInfo role info object we are looking for
     * @return matcher
     */
    private static RoleInfoJsonMatcher matchesRoleInfo(RoleInfo roleInfo) {
        return new RoleInfoJsonMatcher(roleInfo);
    }

    /**
     * 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(MastershipService.class, mockService)
                        .add(MastershipAdminService.class, mockAdminService)
                        .add(DeviceService.class, mockDeviceService)
                        .add(CodecService.class, codecService);

        setServiceDirectory(testDirectory);
    }

    /**
     * Tests the result of the REST API GET when there are active master roles.
     */
    @Test
    public void testGetLocalRole() {
        expect(mockService.getLocalRole(anyObject())).andReturn(role1).anyTimes();
        replay(mockService);

        final WebTarget wt = target();
        final String response = wt.path("mastership/" + deviceId1.toString() +
                                "/local").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("role"));

        final String role = result.get("role").asString();
        assertThat(role, notNullValue());
        assertThat(role, is("MASTER"));
    }

    /**
     * Tests the result of the REST API GET when there is no active master.
     */
    @Test
    public void testGetMasterForNull() {
        expect(mockService.getMasterFor(anyObject())).andReturn(null).anyTimes();
        replay(mockService);

        final WebTarget wt = target();
        final Response response = wt.path("mastership/" + deviceId1.toString() +
                "/master").request().get();
        assertEquals(404, response.getStatus());
    }

    /**
     * Tests the result of the REST API GET when there is active master.
     */
    @Test
    public void testGetMasterFor() {
        expect(mockService.getMasterFor(anyObject())).andReturn(nodeId1).anyTimes();
        replay(mockService);

        final WebTarget wt = target();
        final String response = wt.path("mastership/" + deviceId1.toString() +
                                "/master").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("nodeId"));

        final String node = result.get("nodeId").asString();
        assertThat(node, notNullValue());
        assertThat(node, is("node:1"));
    }

    /**
     * Tests the result of the REST API GET when there are no active nodes.
     */
    @Test
    public void testGetNodesForNull() {
        expect(mockService.getNodesFor(anyObject())).andReturn(null).anyTimes();
        replay(mockService);

        final WebTarget wt = target();
        final Response response = wt.path("mastership/" + deviceId1.toString() +
                "/role").request().get();
        assertEquals(404, response.getStatus());
    }

    /**
     * Tests the result of the REST API GET when there are active nodes.
     */
    @Test
    public void testGetNodesFor() {
        RoleInfo mockRoleInfo = createMockRoleInfo();
        expect(mockService.getNodesFor(anyObject())).andReturn(mockRoleInfo).anyTimes();
        replay(mockService);

        final WebTarget wt = target();
        final String response = wt.path("mastership/" + deviceId1.toString() +
                                "/role").request().get(String.class);
        final JsonObject result = Json.parse(response).asObject();
        assertThat(result, notNullValue());

        assertThat(result, matchesRoleInfo(mockRoleInfo));
    }

    /**
     * Tests the result of the REST API GET when there are active devices.
     */
    @Test
    public void testGetDevicesOf() {
        Set<DeviceId> deviceIds = ImmutableSet.of(deviceId1, deviceId2, deviceId3);
        expect(mockService.getDevicesOf(anyObject())).andReturn(deviceIds).anyTimes();
        replay(mockService);

        final WebTarget wt = target();
        final String response = wt.path("mastership/" + deviceId1.toString() +
                                "/device").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 jsonDevices = result.get("deviceIds").asArray();
        assertThat(jsonDevices, notNullValue());
        assertThat(jsonDevices.size(), is(3));
    }

    /**
     * Tests the result of the REST API GET for requesting mastership role.
     */
    @Test
    public void testRequestRoleFor() {
        expect(mockService.requestRoleForSync(anyObject())).andReturn(role1).anyTimes();
        replay(mockService);

        expect(mockDeviceService.getDevice(deviceId1)).andReturn(device1);
        replay(mockDeviceService);

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

        final String role = result.get("role").asString();
        assertThat(role, notNullValue());
        assertThat(role, is("MASTER"));
    }

    /**
     * Tests the result of the REST API GET for relinquishing mastership role.
     */
    @Test
    public void testRelinquishMastership() {
        mockService.relinquishMastershipSync(anyObject());
        expectLastCall();
        replay(mockService);

        final WebTarget wt = target();
        final Response response = wt.path("mastership/" + deviceId1.toString() +
                "/relinquish").request().get();
        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
        String location = response.getLocation().toString();
        assertThat(location, Matchers.startsWith(deviceId1.toString()));
    }

    /**
     * Tests the result of the REST API PUT for setting role.
     */
    @Test
    public void testSetRole() {
        mockAdminService.setRoleSync(anyObject(), anyObject(), anyObject());
        expectLastCall();
        replay(mockAdminService);

        final WebTarget wt = target();
        final InputStream jsonStream = MetersResourceTest.class
                .getResourceAsStream("put-set-roles.json");
        final Response response = wt.path("mastership")
                                    .request().put(Entity.json(jsonStream));
        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
    }

    /**
     * Tests the result of the REST API GET for balancing roles.
     */
    @Test
    public void testBalanceRoles() {
        mockAdminService.balanceRoles();
        expectLastCall();
        replay(mockAdminService);

        final WebTarget wt = target();
        final Response response = wt.path("mastership").request().get();
        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
    }
}
