/*
 * 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.cpman.impl;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import org.junit.Before;
import org.junit.Test;
import org.onosproject.cpman.ControlMetricType;
import org.onosproject.cpman.ControlResource;
import org.onosproject.cpman.MetricsDatabase;
import org.onosproject.net.DeviceId;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;

/**
 * Unit test for control plane metrics back-end database.
 */
public class MetricsDatabaseTest {

    private MetricsDatabase mdb;
    private static final String CPU_METRIC = "cpu";
    private static final String CPU_LOAD = "load";
    private static final String DEFAULT_RES = "resource";
    private static final String MEMORY_METRIC = "memory";
    private static final String MEMORY_FREE_PERC = "freePerc";
    private static final String MEMORY_USED_PERC = "usedPerc";
    private Map<DeviceId, MetricsDatabase> devMetricsMap;

    /**
     * Initializes metrics database instance.
     */
    @Before
    public void setUp() {
        mdb = new DefaultMetricsDatabase.Builder()
                .withMetricName(CPU_METRIC)
                .withResourceName(DEFAULT_RES)
                .addMetricType(CPU_LOAD)
                .build();
    }

    /**
     * Tests the metric update function.
     */
    @Test
    public void testMetricUpdate() {
        long currentTime = System.currentTimeMillis() / 1000L;

        mdb.updateMetric(CPU_LOAD, 30, currentTime);
        assertThat(30D, is(mdb.recentMetric(CPU_LOAD)));

        mdb.updateMetric(CPU_LOAD, 40, currentTime + 60);
        assertThat(40D, is(mdb.recentMetric(CPU_LOAD)));

        mdb.updateMetric(CPU_LOAD, 50, currentTime + 120);
        assertThat(50D, is(mdb.recentMetric(CPU_LOAD)));
    }

    /**
     * Tests the metric range fetch function.
     */
    @Test
    public void testMetricRangeFetch() {
        // full range fetch
        assertThat(mdb.metrics(CPU_LOAD).length, is(60 * 24));

        // query one minute time range
        assertThat(mdb.recentMetrics(CPU_LOAD, 1, TimeUnit.MINUTES).length, is(1));

        // query one hour time range
        assertThat(mdb.recentMetrics(CPU_LOAD, 1, TimeUnit.HOURS).length, is(60));

        // query one day time range
        assertThat(mdb.recentMetrics(CPU_LOAD, 1, TimeUnit.DAYS).length, is(60 * 24));

        // query a specific time range
        long endTime = System.currentTimeMillis() / 1000L;
        long startTime = endTime - 60 * 5;
        assertThat(mdb.metrics(CPU_LOAD, startTime, endTime).length, is(5));
    }

    /**
     * Test the projected time range.
     */
    @Test(expected = IllegalArgumentException.class)
    public void testExceededTimeRange() {
        // query 25 hours time range
        assertThat(mdb.recentMetrics(CPU_LOAD, 25, TimeUnit.HOURS).length, is(60 * 24));
    }

    /**
     * Test the projected time range.
     */
    @Test(expected = IllegalArgumentException.class)
    public void testInsufficientTimeRange() {
        // query 50 seconds time range
        assertThat(mdb.recentMetrics(CPU_LOAD, 50, TimeUnit.SECONDS).length, is(1));
    }

    /**
     * Test multiple metrics update and query.
     */
    @Test
    public void testMultipleMetrics() {
        MetricsDatabase multiMdb = new DefaultMetricsDatabase.Builder()
                        .withMetricName(MEMORY_METRIC)
                        .withResourceName(DEFAULT_RES)
                        .addMetricType(MEMORY_FREE_PERC)
                        .addMetricType(MEMORY_USED_PERC)
                        .build();

        Map<String, Double> metrics = new HashMap<>();
        metrics.putIfAbsent(MEMORY_FREE_PERC, 30D);
        metrics.putIfAbsent(MEMORY_USED_PERC, 70D);
        multiMdb.updateMetrics(metrics);

        assertThat(30D, is(multiMdb.recentMetric(MEMORY_FREE_PERC)));
        assertThat(70D, is(multiMdb.recentMetric(MEMORY_USED_PERC)));
    }

    /**
     * Tests device metrics map update and query.
     */
    @Test
    public void testDeviceMetricsMap() {
        ControlResource.Type type = ControlResource.Type.CONTROL_MESSAGE;
        DeviceId devId1 = DeviceId.deviceId("of:0000000000000101");
        DeviceId devId2 = DeviceId.deviceId("of:0000000000000102");

        devMetricsMap = Maps.newHashMap();

        Set<DeviceId> devices = ImmutableSet.of(devId1, devId2);
        devices.forEach(dev ->
            devMetricsMap.putIfAbsent(dev,
                    genMDbBuilder(type, ControlResource.CONTROL_MESSAGE_METRICS)
                            .withResourceName(dev.toString())
                            .build()));

        Map<String, Double> metrics1 = new HashMap<>();
        ControlResource.CONTROL_MESSAGE_METRICS.forEach(msgType ->
                metrics1.putIfAbsent(msgType.toString(), 10D));

        Map<String, Double> metrics2 = new HashMap<>();
        ControlResource.CONTROL_MESSAGE_METRICS.forEach(msgType ->
                metrics2.putIfAbsent(msgType.toString(), 20D));


        devMetricsMap.get(devId1).updateMetrics(metrics1);
        devMetricsMap.get(devId2).updateMetrics(metrics2);

        ControlResource.CONTROL_MESSAGE_METRICS.forEach(msgType ->
                assertThat(10D, is(devMetricsMap.get(devId1).recentMetric(msgType.toString())))
        );

        ControlResource.CONTROL_MESSAGE_METRICS.forEach(msgType ->
                assertThat(20D, is(devMetricsMap.get(devId2).recentMetric(msgType.toString())))
        );
    }

    private MetricsDatabase.Builder genMDbBuilder(ControlResource.Type resourceType,
                                          Set<ControlMetricType> metricTypes) {
        MetricsDatabase.Builder builder = new DefaultMetricsDatabase.Builder();
        builder.withMetricName(resourceType.toString());
        metricTypes.forEach(type -> builder.addMetricType(type.toString()));
        return builder;
    }
}
