/*
 * Copyright 2016 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.cpman.rest;

import com.google.common.collect.ImmutableSet;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Before;
import org.junit.Test;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
import org.onlab.packet.IpAddress;
import org.onlab.rest.BaseResource;
import org.onosproject.cluster.ClusterService;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.NodeId;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.cpman.ControlLoad;
import org.onosproject.cpman.ControlPlaneMonitorService;
import org.onosproject.cpman.codec.ControlLoadCodec;

import javax.ws.rs.client.WebTarget;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.anyString;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;

/**
 * Unit test for ControlMetrics REST API.
 */
public class ControlMetricsResourceTest extends JerseyTest {

    final ControlPlaneMonitorService mockControlPlaneMonitorService =
            createMock(ControlPlaneMonitorService.class);
    final ClusterService mockClusterService = createMock(ClusterService.class);
    Set<String> resourceSet = ImmutableSet.of("resource1", "resource2");
    NodeId nodeId;
    ControlLoad mockControlLoad;

    private static final String PREFIX = "metrics";

    /**
     * Constructs a control metrics resource test instance.
     */
    public ControlMetricsResourceTest() {
        super(ResourceConfig.forApplicationClass(CPManWebApplication.class));
    }

    /**
     * Mock class for a controller node.
     */
    private static class MockControllerNode implements ControllerNode {
        final NodeId id;

        public MockControllerNode(NodeId id) {
            this.id = id;
        }

        @Override
        public NodeId id() {
            return this.id;
        }

        @Override
        public IpAddress ip() {
            return null;
        }

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

    private static class MockControlLoad implements ControlLoad {

        @Override
        public long average(int duration, TimeUnit unit) {
            return 0;
        }

        @Override
        public long average() {
            return 10L;
        }

        @Override
        public long[] recent(int duration, TimeUnit unit) {
            return new long[0];
        }

        @Override
        public long[] all() {
            return new long[0];
        }

        @Override
        public long rate() {
            return 0;
        }

        @Override
        public long latest() {
            return 10L;
        }

        @Override
        public boolean isValid() {
            return false;
        }

        @Override
        public long time() {
            return 20L;
        }
    }

    /**
     * Sets up the global values for all the tests.
     */
    @Before
    public void setUpTest() {
        final CodecManager codecService = new CodecManager();
        codecService.activate();
        codecService.registerCodec(ControlLoad.class, new ControlLoadCodec());
        ServiceDirectory testDirectory =
                new TestServiceDirectory()
                        .add(ControlPlaneMonitorService.class,
                                mockControlPlaneMonitorService)
                        .add(ClusterService.class, mockClusterService)
                        .add(CodecService.class, codecService);
        BaseResource.setServiceDirectory(testDirectory);

        nodeId = new NodeId("1");
        mockControlLoad = new MockControlLoad();
        ControllerNode mockControllerNode = new MockControllerNode(nodeId);

        expect(mockClusterService.getLocalNode()).andReturn(mockControllerNode).anyTimes();
        replay(mockClusterService);
    }

    /**
     * Tests the results of the REST API GET when there are no active entries.
     */
    @Test
    public void testResourceEmptyArray() {
        expect(mockControlPlaneMonitorService.availableResources(anyObject()))
                .andReturn(ImmutableSet.of()).once();
        replay(mockControlPlaneMonitorService);
        final WebTarget wt = target();
        final String response = wt.path(PREFIX + "/disk_metrics").request().get(String.class);
        assertThat(response, is("{\"disks\":[]}"));

        verify(mockControlPlaneMonitorService);
    }

    /**
     * Tests the results of the rest api GET when there are active metrics.
     */
    @Test
    public void testResourcePopulatedArray() {
        expect(mockControlPlaneMonitorService.availableResources(anyObject()))
                .andReturn(resourceSet).once();
        expect(mockControlPlaneMonitorService.getLocalLoad(anyObject(),
                anyString())).andReturn(null).times(4);
        replay(mockControlPlaneMonitorService);

        final WebTarget wt = target();
        final String response = wt.path(PREFIX + "/disk_metrics").request().get(String.class);
        assertThat(response, is("{\"disks\":[{\"name\":\"resource1\",\"value\":{\"metrics\":[]}}," +
                "{\"name\":\"resource2\",\"value\":{\"metrics\":[]}}]}"));
    }
}
