/*
 * Copyright 2017-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;

import org.onosproject.drivers.server.behavior.CpuStatisticsDiscovery;
import org.onosproject.drivers.server.behavior.MonitoringStatisticsDiscovery;
import org.onosproject.drivers.server.devices.CpuDevice;
import org.onosproject.drivers.server.devices.CpuVendor;
import org.onosproject.drivers.server.devices.nic.NicDevice;
import org.onosproject.drivers.server.devices.nic.NicRxFilter;
import org.onosproject.drivers.server.devices.nic.NicRxFilter.RxFilter;
import org.onosproject.drivers.server.devices.ServerDeviceDescription;
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.TimingStatistics;

import org.onosproject.drivers.server.impl.devices.DefaultCpuDevice;
import org.onosproject.drivers.server.impl.devices.DefaultNicDevice;
import org.onosproject.drivers.server.impl.devices.DefaultRestServerSBDevice;
import org.onosproject.drivers.server.impl.devices.DefaultServerDeviceDescription;
import org.onosproject.drivers.server.impl.stats.DefaultCpuStatistics;
import org.onosproject.drivers.server.impl.stats.DefaultMonitoringStatistics;
import org.onosproject.drivers.server.impl.stats.DefaultTimingStatistics;

import org.onlab.packet.ChassisId;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.behaviour.DevicesDiscovery;
import org.onosproject.net.device.DeviceDescription;
import org.onosproject.net.device.DeviceDescriptionDiscovery;
import org.onosproject.net.device.DefaultPortStatistics;
import org.onosproject.net.device.DefaultPortDescription;
import org.onosproject.net.device.PortDescription;
import org.onosproject.net.device.PortStatistics;
import org.onosproject.net.device.PortStatisticsDiscovery;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.protocol.rest.RestSBDevice;
import org.onosproject.protocol.rest.RestSBDevice.AuthenticationScheme;

import org.slf4j.Logger;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.ImmutableList;

import javax.ws.rs.ProcessingException;
import java.io.InputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Discovers the device details of
 * REST-based commodity server devices.
 */
public class ServerDevicesDiscovery extends BasicServerDriver
        implements  DevicesDiscovery, DeviceDescriptionDiscovery,
                    PortStatisticsDiscovery, CpuStatisticsDiscovery,
                    MonitoringStatisticsDiscovery {

    private final Logger log = getLogger(getClass());

    /**
     * Resource endpoints of the server agent (REST server-side).
     */
    private static final String RESOURCE_DISCOVERY_URL   = BASE_URL + SLASH + "resources";
    private static final String GLOBAL_STATS_URL         = BASE_URL + SLASH + "stats";
    private static final String SERVICE_CHAINS_STATS_URL = BASE_URL + SLASH + "chains_stats";  // + /ID

    /**
     * Parameters to be exchanged with the server's agent.
     */
    private static final String PARAM_MANUFACTURER     = "manufacturer";
    private static final String PARAM_HW_VENDOR        = "hwVersion";
    private static final String PARAM_SW_VENDOR        = "swVersion";
    private static final String PARAM_SERIAL           = "serial";
    private static final String PARAM_TIMING_STATS     = "timingStats";
    private static final String PARAM_TIMING_AUTOSCALE = "autoScaleTimingStats";

    private static final String NIC_PARAM_NAME             = "name";
    private static final String NIC_PARAM_PORT_INDEX       = "index";
    private static final String NIC_PARAM_PORT_TYPE        = "portType";
    private static final String NIC_PARAM_PORT_TYPE_FIBER  = "fiber";
    private static final String NIC_PARAM_PORT_TYPE_COPPER = "copper";
    private static final String NIC_PARAM_SPEED            = "speed";
    private static final String NIC_PARAM_STATUS           = "status";
    private static final String NIC_PARAM_HW_ADDR          = "hwAddr";

    /**
     * NIC statistics.
     */
    private static final String NIC_STATS_TX_COUNT  = "txCount";
    private static final String NIC_STATS_TX_BYTES  = "txBytes";
    private static final String NIC_STATS_TX_DROPS  = "txDropped";
    private static final String NIC_STATS_TX_ERRORS = "txErrors";
    private static final String NIC_STATS_RX_COUNT  = "rxCount";
    private static final String NIC_STATS_RX_BYTES  = "rxBytes";
    private static final String NIC_STATS_RX_DROPS  = "rxDropped";
    private static final String NIC_STATS_RX_ERRORS = "rxErrors";

    /**
     * CPU statistics.
     */
    private static final String CPU_PARAM_ID         = "id";
    private static final String CPU_PARAM_VENDOR     = "vendor";
    private static final String CPU_PARAM_FREQUENCY  = "frequency";
    private static final String CPU_PARAM_LOAD       = "load";
    private static final String CPU_PARAM_QUEUE      = "queue";
    private static final String CPU_PARAM_STATUS     = "busy";
    private static final String CPU_PARAM_THROUGHPUT = "throughput";
    private static final String CPU_PARAM_LATENCY    = "latency";
    private static final String MON_PARAM_UNIT       = "unit";
    private static final String MON_PARAM_BUSY_CPUS  = "busyCpus";
    private static final String MON_PARAM_FREE_CPUS  = "freeCpus";
    private static final String MON_PARAM_MIN        = "min";
    private static final String MON_PARAM_AVERAGE    = "average";
    private static final String MON_PARAM_MEDIAN     = "median";
    private static final String MON_PARAM_MAX        = "max";

    /**
     * Timing statistics.
     */
    private static final String TIMING_PARAM_PARSE     = "parseTime";
    private static final String TIMING_PARAM_LAUNCH    = "launchTime";
    private static final String TIMING_PARAM_DEPLOY    = "deployTime";
    private static final String TIMING_PARAM_AUTOSCALE = "autoScaleTime";

    /**
     * Auxiliary constants.
     */
    private static final short  DISCOVERY_RETRIES  = 3;
    private static final String CPU_VENDOR_NULL    = "Unsupported CPU vendor" +
        " Choose one in: " + BasicServerDriver.enumTypesToString(CpuVendor.class);
    private static final String NIC_RX_FILTER_NULL = "Unsupported NIC Rx filter" +
        " Choose one in: " + BasicServerDriver.enumTypesToString(RxFilter.class);

    /**
     * Port types that usually appear in commodity servers.
     */
    public static final Map<String, Port.Type> PORT_TYPE_MAP =
        Collections.unmodifiableMap(
            new HashMap<String, Port.Type>() {
                {
                    put(NIC_PARAM_PORT_TYPE_FIBER,  Port.Type.FIBER);
                    put(NIC_PARAM_PORT_TYPE_COPPER, Port.Type.COPPER);
                }
            }
        );

    /**
     * Constructs server device discovery.
     */
    public ServerDevicesDiscovery() {
        super();
        log.debug("Started");
    }

    @Override
    public Set<DeviceId> deviceIds() {
        // Set of devices to return
        Set<DeviceId> devices = new HashSet<DeviceId>();

        DeviceId deviceId = getHandler().data().deviceId();
        checkNotNull(deviceId, DEVICE_ID_NULL);
        devices.add(deviceId);

        return devices;
    }

    @Override
    public DeviceDescription deviceDetails(DeviceId deviceId) {
        return getDeviceDetails(deviceId);
    }

    @Override
    public DeviceDescription discoverDeviceDetails() {
        return getDeviceDetails(null);
    }

    /**
     * Query a server to retrieve its features.
     *
     * @param deviceId the device ID to be queried
     * @return a DeviceDescription with the device's features
     */
    private DeviceDescription getDeviceDetails(DeviceId deviceId) {
        // Retrieve the device ID, if null given
        if (deviceId == null) {
            deviceId = getHandler().data().deviceId();
            checkNotNull(deviceId, DEVICE_ID_NULL);
        }

        // Get the device
        RestSBDevice device = getController().getDevice(deviceId);
        checkNotNull(device, DEVICE_NULL);

        // Hit the path that provides the server's resources
        InputStream response = null;
        try {
            response = getController().get(deviceId, RESOURCE_DISCOVERY_URL, JSON);
        } catch (ProcessingException pEx) {
            log.error("Failed to discover the device details of: {}", deviceId);
            return null;
        }

        // Load the JSON into objects
        ObjectMapper mapper = new ObjectMapper();
        Map<String, Object> jsonMap = null;
        JsonNode jsonNode = null;
        ObjectNode objNode = null;
        try {
            jsonMap  = mapper.readValue(response, Map.class);
            jsonNode = mapper.convertValue(jsonMap, JsonNode.class);
            objNode = (ObjectNode) jsonNode;
        } catch (IOException ioEx) {
            log.error("Failed to discover the device details of: {}", deviceId);
            return null;
        }

        if (jsonMap == null) {
            log.error("Failed to discover the device details of: {}", deviceId);
            return null;
        }

        // Get all the attributes
        String id     = get(jsonNode, BasicServerDriver.PARAM_ID);
        String vendor = get(jsonNode, PARAM_MANUFACTURER);
        String hw     = get(jsonNode, PARAM_HW_VENDOR);
        String sw     = get(jsonNode, PARAM_SW_VENDOR);
        String serial = get(jsonNode, PARAM_SERIAL);

        // CPUs are composite attributes
        Set<CpuDevice> cpuSet = new HashSet<CpuDevice>();
        JsonNode cpuNode = objNode.path(BasicServerDriver.PARAM_CPUS);

        // Construct CPU objects
        for (JsonNode cn : cpuNode) {
            ObjectNode cpuObjNode = (ObjectNode) cn;

            // All the CPU attributes
            int           cpuId = cpuObjNode.path(CPU_PARAM_ID).asInt();
            String cpuVendorStr = get(cn, CPU_PARAM_VENDOR);
            long   cpuFrequency = cpuObjNode.path(CPU_PARAM_FREQUENCY).asLong();

            // Verify that this is a valid vendor
            CpuVendor cpuVendor = CpuVendor.getByName(cpuVendorStr);
            checkNotNull(cpuVendor, CPU_VENDOR_NULL);

            // Construct a CPU device
            CpuDevice cpu = new DefaultCpuDevice(cpuId, cpuVendor, cpuFrequency);

            // Add it to the set
            cpuSet.add(cpu);
        }

        // NICs are composite attributes too
        Set<NicDevice> nicSet = new HashSet<NicDevice>();
        JsonNode nicNode = objNode.path(PARAM_NICS);

        DefaultAnnotations.Builder annotations = DefaultAnnotations.builder();

        // Construct NIC objects
        for (JsonNode nn : nicNode) {
            ObjectNode nicObjNode = (ObjectNode) nn;

            // All the NIC attributes
            String nicName     = get(nn, NIC_PARAM_NAME);
            long nicIndex      = nicObjNode.path(NIC_PARAM_PORT_INDEX).asLong();
            long speed         = nicObjNode.path(NIC_PARAM_SPEED).asLong();
            String portTypeStr = get(nn, NIC_PARAM_PORT_TYPE);
            Port.Type portType = PORT_TYPE_MAP.get(portTypeStr);
            if (portType == null) {
                throw new IllegalArgumentException(
                    portTypeStr + " is not a valid port type for NIC " + nicName);
            }
            boolean status     = nicObjNode.path(NIC_PARAM_STATUS).asInt() > 0;
            String hwAddr      = get(nn, NIC_PARAM_HW_ADDR);
            JsonNode tagNode   = nicObjNode.path(BasicServerDriver.NIC_PARAM_RX_FILTER);
            if (tagNode == null) {
                throw new IllegalArgumentException(
                    "The Rx filters of NIC " + nicName + " are not reported");
            }

            // Convert the JSON list into an array of strings
            List<String> rxFilters = null;
            try {
                rxFilters = mapper.readValue(tagNode.traverse(),
                    new TypeReference<ArrayList<String>>() { });
            } catch (IOException ioEx) {
                continue;
            }

            // Parse the array of strings and create an RxFilter object
            NicRxFilter rxFilterMechanism = new NicRxFilter();
            for (String s : rxFilters) {
                // Verify that this is a valid Rx filter
                RxFilter rf = RxFilter.getByName(s);
                checkNotNull(rf, NIC_RX_FILTER_NULL);

                rxFilterMechanism.addRxFilter(rf);
            }

            // Store NIC name to number mapping as an annotation
            annotations.set(nicName, Long.toString(nicIndex));

            // Construct a NIC device for this server
            NicDevice nic = new DefaultNicDevice(
                nicName, nicIndex, portType, speed, status, hwAddr, rxFilterMechanism);

            // Add it to the set
            nicSet.add(nic);
        }

        // Construct a complete server device object.
        // Lists of NICs and CPUs extend the information
        // already in RestSBDevice (parent class).
        RestServerSBDevice dev = new DefaultRestServerSBDevice(
            device.ip(), device.port(), device.username(),
            device.password(), device.protocol(), device.url(),
            device.isActive(), device.testUrl().toString(),
            vendor, hw, sw, AuthenticationScheme.BASIC, "",
            cpuSet, nicSet
        );
        checkNotNull(dev, DEVICE_NULL);

        // Set alive
        raiseDeviceReconnect(dev);

        // Updates the controller with the complete device information
        getController().removeDevice(deviceId);
        getController().addDevice((RestSBDevice) dev);

        // Create a description for this server device
        ServerDeviceDescription desc = null;

        try {
            desc = new DefaultServerDeviceDescription(
                new URI(id), Device.Type.SERVER, vendor,
                hw, sw, serial, new ChassisId(),
                cpuSet, nicSet, annotations.build()
            );
        } catch (URISyntaxException uEx) {
            log.error("Failed to create a server device description for: {}",
                deviceId);
            return null;
        }

        log.info("Device's {} details sent to the controller", deviceId);

        return desc;
    }

    @Override
    public List<PortDescription> discoverPortDetails() {
        // Retrieve the device ID
        DeviceId deviceId = getHandler().data().deviceId();
        checkNotNull(deviceId, DEVICE_ID_NULL);

        // .. and object
        RestServerSBDevice device = null;
        try {
            device = (RestServerSBDevice) getController().getDevice(deviceId);
        } catch (ClassCastException ccEx) {
            log.error("Failed to discover ports for device {}", deviceId);
            return Collections.EMPTY_LIST;
        }

        if (device == null) {
            log.error("No device with ID {} is available for port discovery", deviceId);
            return Collections.EMPTY_LIST;
        }
        if ((device.nics() == null) || (device.nics().size() == 0)) {
            log.error("No ports available on {}", deviceId);
            return Collections.EMPTY_LIST;
        }

        // List of port descriptions to return
        List<PortDescription> portDescriptions = Lists.newArrayList();

        // Sorted list of NIC ports
        Set<NicDevice> nics = new TreeSet(device.nics());

        // Iterate through the NICs of this device to populate the list
        for (NicDevice nic : nics) {
            // Include the name of this device as an annotation
            DefaultAnnotations.Builder annotations = DefaultAnnotations.builder()
                                .set(AnnotationKeys.PORT_NAME, nic.name());

            // Create a port description and add it to the list
            portDescriptions.add(
                    DefaultPortDescription.builder()
                            .withPortNumber(PortNumber.portNumber(nic.portNumber(), nic.name()))
                            .isEnabled(nic.status())
                            .type(nic.portType())
                            .portSpeed(nic.speed())
                            .annotations(annotations.build())
                            .build());

            log.info("Port discovery on device {}: NIC {} is {} at {} Mbps",
                deviceId, nic.portNumber(), nic.status() ? "up" : "down",
                nic.speed());
        }

        return ImmutableList.copyOf(portDescriptions);
    }

    @Override
    public Collection<PortStatistics> discoverPortStatistics() {
        // Retrieve the device ID
        DeviceId deviceId = getHandler().data().deviceId();
        checkNotNull(deviceId, DEVICE_ID_NULL);

        // Get port statistics for this device
        return getPortStatistics(deviceId);
    }

    /**
     * Query a server to retrieve its port statistics.
     *
     * @param deviceId the device ID to be queried
     * @return list of (per port) PortStatistics
     */
    private Collection<PortStatistics> getPortStatistics(DeviceId deviceId) {
        // Get global monitoring statistics
        MonitoringStatistics monStats = getGlobalMonitoringStatistics(deviceId);
        if (monStats == null) {
            return Collections.EMPTY_LIST;
        }

        // Filter out the NIC statistics
        Collection<PortStatistics> portStats = monStats.nicStatisticsAll();
        if (portStats == null) {
            return Collections.EMPTY_LIST;
        }

        log.debug("Port statistics: {}", portStats.toString());

        return portStats;
    }

    @Override
    public Collection<CpuStatistics> discoverCpuStatistics() {
        // Retrieve the device ID
        DeviceId deviceId = getHandler().data().deviceId();
        checkNotNull(deviceId, DEVICE_ID_NULL);

        // Get CPU statistics for this device
        return getCpuStatistics(deviceId);
    }

    /**
     * Query a server to retrieve its CPU statistics.
     *
     * @param deviceId the device ID to be queried
     * @return list of (per core) CpuStatistics
     */
     public Collection<CpuStatistics> getCpuStatistics(DeviceId deviceId) {
        // Get global monitoring statistics
        MonitoringStatistics monStats = getGlobalMonitoringStatistics(deviceId);
        if (monStats == null) {
            return Collections.EMPTY_LIST;
        }

        // Filter out the CPU statistics
        Collection<CpuStatistics> cpuStats = monStats.cpuStatisticsAll();
        if (cpuStats == null) {
            return Collections.EMPTY_LIST;
        }

        log.debug("CPU statistics: {}", cpuStats.toString());

        return cpuStats;
    }

    @Override
    public MonitoringStatistics discoverGlobalMonitoringStatistics() {
        // Retrieve the device ID
        DeviceId deviceId = getHandler().data().deviceId();
        checkNotNull(deviceId, DEVICE_ID_NULL);

        // Get global monitoring statistics for this device
        return getGlobalMonitoringStatistics(deviceId);
    }

    /**
     * Query a server to retrieve its global monitoring statistics.
     *
     * @param deviceId the device ID to be queried
     * @return global monitoring statistics
     */
     public MonitoringStatistics getGlobalMonitoringStatistics(DeviceId deviceId) {
        // Monitoring statistics to return
        MonitoringStatistics monStats = null;

        RestServerSBDevice device = null;
        try {
            device = (RestServerSBDevice) getController().getDevice(deviceId);
        } catch (ClassCastException ccEx) {
            log.error("Failed to retrieve global monitoring statistics from device {}",
                deviceId);
            return monStats;
        }
        if ((device == null) || (!device.isActive())) {
            return monStats;
        }

        // Hit the path that provides the server's global resources
        InputStream response = null;
        try {
            response = getController().get(deviceId, GLOBAL_STATS_URL, JSON);
        } catch (ProcessingException pEx) {
            log.error("Failed to retrieve global monitoring statistics from device {}",
                deviceId);
            raiseDeviceDisconnect(device);
            return monStats;
        }

        // Load the JSON into objects
        ObjectMapper mapper = new ObjectMapper();
        Map<String, Object> jsonMap = null;
        ObjectNode objNode = null;
        try {
            jsonMap  = mapper.readValue(response, Map.class);
            JsonNode jsonNode = mapper.convertValue(jsonMap, JsonNode.class);
            objNode = (ObjectNode) jsonNode;
        } catch (IOException ioEx) {
            log.error("Failed to retrieve global monitoring statistics from device {}",
                deviceId);
            raiseDeviceDisconnect(device);
            return monStats;
        }

        if (jsonMap == null) {
            log.error("Failed to retrieve global monitoring statistics from device {}",
                deviceId);
            raiseDeviceDisconnect(device);
            return monStats;
        }

        // Get high-level CPU statistics
        int busyCpus = objNode.path(MON_PARAM_BUSY_CPUS).asInt();
        int freeCpus = objNode.path(MON_PARAM_FREE_CPUS).asInt();

        // Get a list of CPU statistics per core
        Collection<CpuStatistics> cpuStats = parseCpuStatistics(deviceId, objNode);

        // Get a list of port statistics
        Collection<PortStatistics> nicStats = parseNicStatistics(deviceId, objNode);

        // Get zero timing statistics
        TimingStatistics timinsgStats = getZeroTimingStatistics();

        // Ready to construct the grand object
        DefaultMonitoringStatistics.Builder statsBuilder =
            DefaultMonitoringStatistics.builder();

        statsBuilder.setDeviceId(deviceId)
                .setTimingStatistics(timinsgStats)
                .setCpuStatistics(cpuStats)
                .setNicStatistics(nicStats);

        monStats = statsBuilder.build();

        // When a device reports monitoring data, it means it is alive
        raiseDeviceReconnect(device);

        log.debug("Global monitoring statistics: {}", monStats.toString());

        return monStats;
    }

    @Override
    public MonitoringStatistics discoverMonitoringStatistics(URI tcId) {
        // Retrieve the device ID
        DeviceId deviceId = getHandler().data().deviceId();
        checkNotNull(deviceId, DEVICE_ID_NULL);

        // Get resource-specific monitoring statistics for this device
        return getMonitoringStatistics(deviceId, tcId);
    }

    /**
     * Query a server to retrieve monitoring statistics for a
     * specific resource (i.e., traffic class).
     *
     * @param deviceId the device ID to be queried
     * @param tcId the ID of the traffic class to be monitored
     * @return resource-specific monitoring statistics
     */
     private MonitoringStatistics getMonitoringStatistics(DeviceId deviceId, URI tcId) {
        // Monitoring statistics to return
        MonitoringStatistics monStats = null;

        RestServerSBDevice device = null;
        try {
            device = (RestServerSBDevice) getController().getDevice(deviceId);
        } catch (ClassCastException ccEx) {
            log.error("Failed to retrieve monitoring statistics from device {}",
                deviceId);
            return monStats;
        }
        if (device == null) {
            return monStats;
        }

        // Create a resource-specific URL
        String scUrl = SERVICE_CHAINS_STATS_URL + SLASH + tcId.toString();

        // Hit the path that provides the server's specific resources
        InputStream response = null;
        try {
            response = getController().get(deviceId, scUrl, JSON);
        } catch (ProcessingException pEx) {
            log.error("Failed to retrieve monitoring statistics from device {}",
                deviceId);
            raiseDeviceDisconnect(device);
            return monStats;
        }

        // Load the JSON into objects
        ObjectMapper mapper = new ObjectMapper();
        Map<String, Object> jsonMap = null;
        JsonNode jsonNode  = null;
        ObjectNode objNode = null;
        try {
            jsonMap  = mapper.readValue(response, Map.class);
            jsonNode = mapper.convertValue(jsonMap, JsonNode.class);
            objNode = (ObjectNode) jsonNode;
        } catch (IOException ioEx) {
            log.error("Failed to retrieve monitoring statistics from device {}",
                deviceId);
            raiseDeviceDisconnect(device);
            return monStats;
        }

        if (jsonMap == null) {
            log.error("Failed to retrieve monitoring statistics from device {}",
                deviceId);
            raiseDeviceDisconnect(device);
            return monStats;
        }

        // Get the ID of the traffic class
        String id = get(jsonNode, PARAM_ID);

        // And verify that this is the traffic class we want to monitor
        if (!id.equals(tcId.toString())) {
            throw new IllegalStateException(
                "Failed to retrieve monitoring data for traffic class " + tcId +
                ". Traffic class ID does not agree."
            );
        }

        // Get a list of CPU statistics per core
        Collection<CpuStatistics> cpuStats = parseCpuStatistics(deviceId, objNode);

        // Get a list of port statistics
        Collection<PortStatistics> nicStats = parseNicStatistics(deviceId, objNode);

        // Get timing statistics
        TimingStatistics timinsgStats = parseTimingStatistics(objNode);

        // Ready to construct the grand object
        DefaultMonitoringStatistics.Builder statsBuilder =
            DefaultMonitoringStatistics.builder();

        statsBuilder.setDeviceId(deviceId)
                .setTimingStatistics(timinsgStats)
                .setCpuStatistics(cpuStats)
                .setNicStatistics(nicStats);

        monStats = statsBuilder.build();

        // When a device reports monitoring data, it means it is alive
        raiseDeviceReconnect(device);

        log.debug("Monitoring statistics: {}", monStats.toString());

        return monStats;
    }

    /**
     * Parse the input JSON object, looking for CPU-related
     * statistics. Upon success, construct and return a list
     * of CPU statistics objects.
     *
     * @param deviceId the device ID that sent the JSON object
     * @param objNode input JSON node with CPU statistics information
     * @return list of (per core) CpuStatistics
     */
    private Collection<CpuStatistics> parseCpuStatistics(DeviceId deviceId, JsonNode objNode) {
        if ((deviceId == null) || (objNode == null)) {
            return Collections.EMPTY_LIST;
        }

        Collection<CpuStatistics> cpuStats = Lists.newArrayList();

        JsonNode cpuNode = objNode.path(BasicServerDriver.PARAM_CPUS);

        for (JsonNode cn : cpuNode) {
            ObjectNode cpuObjNode = (ObjectNode) cn;

            // CPU statistics builder
            DefaultCpuStatistics.Builder cpuBuilder = DefaultCpuStatistics.builder();

            // Throughput statistics are optional
            JsonNode throughputNode = cpuObjNode.get(CPU_PARAM_THROUGHPUT);
            if (throughputNode != null) {
                String throughputUnit = get(throughputNode, MON_PARAM_UNIT);
                if (!Strings.isNullOrEmpty(throughputUnit)) {
                    cpuBuilder.setThroughputUnit(throughputUnit);
                }
                float averageThroughput = (float) 0;
                if (throughputNode.get(MON_PARAM_AVERAGE) != null) {
                    averageThroughput = throughputNode.path(MON_PARAM_AVERAGE).floatValue();
                }
                cpuBuilder.setAverageThroughput(averageThroughput);
            }

            // Latency statistics are optional
            JsonNode latencyNode = cpuObjNode.get(CPU_PARAM_LATENCY);
            if (latencyNode != null) {
                String latencyUnit = get(latencyNode, MON_PARAM_UNIT);
                if (!Strings.isNullOrEmpty(latencyUnit)) {
                    cpuBuilder.setLatencyUnit(latencyUnit);
                }
                float minLatency = (float) 0;
                if (latencyNode.get(MON_PARAM_MIN) != null) {
                    minLatency = latencyNode.path(MON_PARAM_MIN).floatValue();
                }
                float medianLatency = (float) 0;
                if (latencyNode.get(MON_PARAM_MEDIAN) != null) {
                    medianLatency = latencyNode.path(MON_PARAM_MEDIAN).floatValue();
                }
                float maxLatency = (float) 0;
                if (latencyNode.get(MON_PARAM_MAX) != null) {
                    maxLatency = latencyNode.path(MON_PARAM_MAX).floatValue();
                }

                cpuBuilder.setMinLatency(minLatency)
                    .setMedianLatency(medianLatency)
                    .setMaxLatency(maxLatency);
            }

            // CPU ID with its load and status
            int cpuId = cpuObjNode.path(CPU_PARAM_ID).asInt();
            float cpuLoad = cpuObjNode.path(CPU_PARAM_LOAD).floatValue();
            int queueId = cpuObjNode.path(CPU_PARAM_QUEUE).asInt();
            boolean isBusy = cpuObjNode.path(CPU_PARAM_STATUS).booleanValue();

            // This is mandatory information
            cpuBuilder.setDeviceId(deviceId)
                    .setId(cpuId)
                    .setLoad(cpuLoad)
                    .setQueue(queueId)
                    .setIsBusy(isBusy);

            // We have all the statistics for this CPU core
            cpuStats.add(cpuBuilder.build());
        }

        return cpuStats;
    }

    /**
     * Parse the input JSON object, looking for NIC-related
     * statistics. Upon success, construct and return a list
     * of NIC statistics objects.
     *
     * @param deviceId the device ID that sent the JSON object
     * @param objNode input JSON node with NIC statistics information
     * @return list of (per port) PortStatistics
     */
    private Collection<PortStatistics> parseNicStatistics(DeviceId deviceId, JsonNode objNode) {
        if ((deviceId == null) || (objNode == null)) {
            return Collections.EMPTY_LIST;
        }

        RestServerSBDevice device = null;
        try {
            device = (RestServerSBDevice) getController().getDevice(deviceId);
        } catch (ClassCastException ccEx) {
            return Collections.EMPTY_LIST;
        }
        if (device == null) {
            return Collections.EMPTY_LIST;
        }

        Collection<PortStatistics> nicStats = Lists.newArrayList();

        JsonNode nicNode = objNode.path(PARAM_NICS);

        for (JsonNode nn : nicNode) {
            ObjectNode nicObjNode = (ObjectNode) nn;

            // All the NIC attributes
            String nicName  = get(nn, NIC_PARAM_NAME);
            checkArgument(!Strings.isNullOrEmpty(nicName), "NIC name is empty or NULL");

            long portNumber = device.portNumberFromName(nicName);
            checkArgument(portNumber >= 0, "Unknown port ID " + portNumber + " for NIC " + nicName);

            long rxCount   = nicObjNode.path(NIC_STATS_RX_COUNT).asLong();
            long rxBytes   = nicObjNode.path(NIC_STATS_RX_BYTES).asLong();
            long rxDropped = nicObjNode.path(NIC_STATS_RX_DROPS).asLong();
            long rxErrors  = nicObjNode.path(NIC_STATS_RX_ERRORS).asLong();
            long txCount   = nicObjNode.path(NIC_STATS_TX_COUNT).asLong();
            long txBytes   = nicObjNode.path(NIC_STATS_TX_BYTES).asLong();
            long txDropped = nicObjNode.path(NIC_STATS_TX_DROPS).asLong();
            long txErrors  = nicObjNode.path(NIC_STATS_TX_ERRORS).asLong();

            // Incorporate these statistics into an object
            DefaultPortStatistics.Builder nicBuilder = DefaultPortStatistics.builder();

            nicBuilder.setDeviceId(deviceId)
                    .setPort((int) portNumber)
                    .setPacketsReceived(rxCount)
                    .setPacketsSent(txCount)
                    .setBytesReceived(rxBytes)
                    .setBytesSent(txBytes)
                    .setPacketsRxDropped(rxDropped)
                    .setPacketsRxErrors(rxErrors)
                    .setPacketsTxDropped(txDropped)
                    .setPacketsTxErrors(txErrors);

            // We have statistics for this NIC
            nicStats.add(nicBuilder.build());
        }

        return nicStats;
    }

    /**
     * Parse the input JSON object, looking for timing-related statistics.
     * Upon success, return a timing statistics object with the advertized values.
     * Upon failure, return a timing statistics object with zero-initialized values.
     *
     * @param objNode input JSON node with timing statistics information
     * @return TimingStatistics object or null
     */
    private TimingStatistics parseTimingStatistics(JsonNode objNode) {
        TimingStatistics timinsgStats = null;

        if (objNode == null) {
            return timinsgStats;
        }

        // If no timing statistics are present, then send zeros
        if (objNode.get(PARAM_TIMING_STATS) == null) {
            return getZeroTimingStatistics();
        }

        DefaultTimingStatistics.Builder timingBuilder = DefaultTimingStatistics.builder();

        // Get timing statistics
        JsonNode timingNode = objNode.path(PARAM_TIMING_STATS);
        ObjectNode timingObjNode = (ObjectNode) timingNode;

        // The unit of timing statistics
        String timingStatsUnit = get(timingNode, MON_PARAM_UNIT);
        if (!Strings.isNullOrEmpty(timingStatsUnit)) {
            timingBuilder.setUnit(timingStatsUnit);
        }

        // Time (ns) to parse the controller's deployment instruction
        long parsingTime = 0;
        if (timingObjNode.get(TIMING_PARAM_PARSE) != null) {
            parsingTime = timingObjNode.path(TIMING_PARAM_PARSE).asLong();
        }
        // Time (ns) to do the deployment
        long launchingTime = 0;
        if (timingObjNode.get(TIMING_PARAM_LAUNCH) != null) {
            launchingTime = timingObjNode.path(TIMING_PARAM_LAUNCH).asLong();
        }
        // Deployment time (ns) equals to time to parse + time to launch
        long deployTime = 0;
        if (timingObjNode.get(TIMING_PARAM_DEPLOY) != null) {
            deployTime = timingObjNode.path(TIMING_PARAM_DEPLOY).asLong();
        }
        checkArgument(deployTime == parsingTime + launchingTime, "Inconsistent timing statistics");

        timingBuilder.setParsingTime(parsingTime)
                    .setLaunchingTime(launchingTime);

        // Get autoscale timing statistics
        JsonNode autoscaleTimingNode = objNode.path(PARAM_TIMING_AUTOSCALE);
        if (autoscaleTimingNode == null) {
            return timingBuilder.build();
        }

        ObjectNode autoscaleTimingObjNode = (ObjectNode) autoscaleTimingNode;
        // Time (ns) to autoscale a server's load
        long autoscaleTime = 0;
        if (autoscaleTimingObjNode.get(TIMING_PARAM_AUTOSCALE) != null) {
            autoscaleTimingObjNode.path(TIMING_PARAM_AUTOSCALE).asLong();
        }
        timingBuilder.setAutoscaleTime(autoscaleTime);

        return timingBuilder.build();
    }

    /**
     * Return a timing statistics object with zero counters.
     * This is useful when constructing MonitoringStatistics
     * objects that do not require timers.
     *
     * @return TimingStatistics object
     */
    private TimingStatistics getZeroTimingStatistics() {
        DefaultTimingStatistics.Builder zeroTimingBuilder = DefaultTimingStatistics.builder();

        zeroTimingBuilder.setParsingTime(0)
                         .setLaunchingTime(0)
                         .setAutoscaleTime(0);

        return zeroTimingBuilder.build();
    }

}
