/*
 * 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 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.onlab.rest.BaseResource;
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.DeviceId;
import org.onosproject.net.MastershipRole;

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

    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(CodecService.class, codecService);

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

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