/*
 * Copyright 2018-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.drivers.server.gui;

import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.primitives.Floats;

import org.onosproject.drivers.server.behavior.MonitoringStatisticsDiscovery;
import org.onosproject.drivers.server.devices.RestServerSBDevice;
import org.onosproject.drivers.server.stats.CpuStatistics;
import org.onosproject.drivers.server.stats.MonitoringStatistics;
import org.onosproject.drivers.server.stats.MonitoringUnit.ThroughputUnit;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.device.DeviceService;
import org.onosproject.ui.RequestHandler;
import org.onosproject.ui.chart.ChartModel;

import org.apache.commons.lang3.ArrayUtils;
import org.joda.time.LocalDateTime;
import org.slf4j.Logger;

import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.Set;

import static org.slf4j.LoggerFactory.getLogger;
import static org.onosproject.drivers.server.gui.MetricType.THROUGHPUT;
import static com.google.common.base.Preconditions.checkNotNull;

/**
 * Message handler for passing throughput data to the Web UI.
 */
public class ThroughputViewMessageHandler extends BaseViewMessageHandler {

    private static final Logger log = getLogger(ThroughputViewMessageHandler.class);

    private static final String THROUGHPUT_DATA_REQ = "throughputDataRequest";
    private static final String THROUGHPUT_DATA_RESP = "throughputDataResponse";
    private static final String THROUGHPUT_LABEL = "throughputs";

    @Override
    protected Collection<RequestHandler> createRequestHandlers() {
        return ImmutableSet.of(new ThroughputMessageRequest());
    }

    private final class ThroughputMessageRequest extends BaseViewMessageHandler.ControlMessageRequest {

        private ThroughputMessageRequest() {
            super(THROUGHPUT_DATA_REQ, THROUGHPUT_DATA_RESP, THROUGHPUT_LABEL);
        }

        @Override
        protected String[] getSeries() {
            return createSeries(THROUGHPUT, MAX_COLUMNS_NB);
        }

        @Override
        protected void populateChart(ChartModel cm, ObjectNode payload) {
            DeviceService ds = get(DeviceService.class);
            if ((ds == null) || (ds.getAvailableDeviceCount() == 0)) {
                fillDataWhenNoDevicePresent(cm, THROUGHPUT, MAX_COLUMNS_NB);
                return;
            }

            String uri = string(payload, "devId");

            // Project only one device over time
            if (!Strings.isNullOrEmpty(uri)) {
                DeviceId deviceId = DeviceId.deviceId(uri);
                RestServerSBDevice serverDev =
                    (RestServerSBDevice) basicDriver.getController().getDevice(deviceId);

                Map<Integer, Float[]> data = null;
                MonitoringStatistics monStats = serverDriver.getGlobalMonitoringStatistics(deviceId);
                if (monStats == null) {
                    data = populateZeroDataHistory(deviceId, MAX_COLUMNS_NB);
                } else {
                    data = populateThroughputDataHistory(deviceId, serverDev.numberOfCpus(), monStats);
                }
                checkNotNull(data, "No throughput data history to visualize");

                // Generate a timestamp
                LocalDateTime ldt = new LocalDateTime(timestamp);

                // Project the data
                populateMetrics(cm, data, ldt, THROUGHPUT, NUM_OF_DATA_POINTS);

                Set<DeviceId> deviceIds = Sets.newHashSet();
                for (Device device : ds.getAvailableDevices()) {
                    // Only devices that support this type of monitoring behaviour are considered
                    if (device.is(MonitoringStatisticsDiscovery.class) && serverDev.isActive()) {
                        deviceIds.add(device.id());
                    }
                }

                // Drop down list to select devices
                attachDeviceList(cm, deviceIds);
            } else {
                for (Device device : ds.getAvailableDevices()) {
                    // Only devices that support this type of monitoring behaviour are considered
                    if (!device.is(MonitoringStatisticsDiscovery.class)) {
                        continue;
                    }

                    DeviceId deviceId = device.id();
                    RestServerSBDevice serverDev =
                        (RestServerSBDevice) basicDriver.getController().getDevice(deviceId);

                    Map<Integer, Float> data = null;
                    MonitoringStatistics monStats = serverDriver.getGlobalMonitoringStatistics(deviceId);
                    if (monStats == null) {
                        data = populateZeroData(deviceId, MAX_COLUMNS_NB);
                    } else {
                        data = populateThroughputData(deviceId, serverDev.numberOfCpus(), monStats);
                    }
                    checkNotNull(data, "No throughput data to visualize");

                    // Map them to the CPU cores
                    Map<String, Object> local = Maps.newHashMap();
                    for (int i = 0; i < data.size(); i++) {
                        local.put(getLabel(THROUGHPUT, i), data.get(i));
                    }

                    // Last piece of data is the device ID
                    if (serverDev.isActive()) {
                        local.put(LABEL, deviceId);
                        populateMetric(cm.addDataPoint(deviceId), local);
                    } else {
                        local.put(LABEL, "");
                        populateMetric(cm.addDataPoint(""), local);
                    }
                }
            }
        }

        /**
         * Turn the current monitoring data into a data
         * structure that can feed the Throughput UI memory.
         *
         * @param deviceId the device ID being monitored
         * @param length the length of the array
         * @param monStats a MonitoringStatistics object
         * @return a map of throughput metrics to their values
         */
        private Map<Integer, Float> populateThroughputData(
                DeviceId deviceId, int length, MonitoringStatistics monStats) {
            Map<Integer, Float> data = initializeData(MAX_COLUMNS_NB);

            for (CpuStatistics stats : monStats.cpuStatisticsAll()) {
                int index = stats.id();

                Float value = null;
                if ((stats.averageThroughput().isPresent()) && (stats.load() > MIN_CPU_LOAD)) {
                    value = stats.averageThroughput().get();
                } else {
                    value = new Float(0);
                }

                // Unit conversion
                ThroughputUnit throughputUnit = null;
                if (stats.throughputUnit().isPresent()) {
                    throughputUnit = (ThroughputUnit) stats.throughputUnit().get();
                } else {
                    throughputUnit = ThroughputUnit.BPS;
                }
                value = ThroughputUnit.toGbps(value, throughputUnit);

                // Store it locally
                addToCache(deviceId, length, index, value);

                // And into the map
                data.put(index, value);
            }

            return data;
        }

        /**
         * Turn the monitoring data history into a
         * data structure that can feed the Throughput UI memory.
         *
         * @param deviceId the device ID being monitored
         * @param length the length of the array
         * @param monStats a MonitoringStatistics object
         * @return a map of throughput metrics to their arrays of values
         */
        private Map<Integer, Float[]> populateThroughputDataHistory(
                DeviceId deviceId, int length, MonitoringStatistics monStats) {
            Map<Integer, Float[]> data = initializeDataHistory(MAX_COLUMNS_NB);

            for (CpuStatistics stats : monStats.cpuStatisticsAll()) {
                int index = stats.id();

                Float value = null;
                if ((stats.averageThroughput().isPresent()) && (stats.load() > MIN_CPU_LOAD)) {
                    value = stats.averageThroughput().get();
                } else {
                    value = new Float(0);
                }

                // Unit conversion
                ThroughputUnit throughputUnit = null;
                if (stats.throughputUnit().isPresent()) {
                    throughputUnit = (ThroughputUnit) stats.throughputUnit().get();
                } else {
                    throughputUnit = ThroughputUnit.BPS;
                }
                value = ThroughputUnit.toGbps(value, throughputUnit);

                // Store it locally
                addToCache(deviceId, length, index, value);

                LruCache<Float> loadCache = getDataHistory(deviceId, index);
                if (loadCache == null) {
                    continue;
                }
                float[] floatArray = Floats.toArray(Arrays.asList(loadCache.values().toArray(new Float[0])));

                // Fill the missing points
                float[] filledLoadArray = fillData(floatArray, NUM_OF_DATA_POINTS);

                // Set the data
                data.put(index, ArrayUtils.toObject(filledLoadArray));
            }

            // Keep a timestamp
            timestamp = System.currentTimeMillis();

            return data;
        }

    }

}
