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

import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.util.Bandwidth;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Element;
import org.onosproject.net.HostId;
import org.onosproject.net.Link;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.host.HostService;
import org.onosproject.net.link.LinkService;
import org.onosproject.net.resource.ContinuousResource;
import org.onosproject.ui.RequestHandler;
import org.onosproject.ui.UiConnection;
import org.onosproject.ui.UiMessageHandler;
import org.onosproject.ui.topo.Highlights;
import org.onosproject.ui.topo.TopoJson;
import org.onosproject.net.resource.DiscreteResourceId;
import org.onosproject.net.resource.Resources;
import org.onosproject.net.resource.ResourceQueryService;
import org.onosproject.incubator.net.PortStatisticsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.Set;

/**
 * ONOS UI Topology overlay for LinkProps. Creates the highlights for each link
 * depending on the selected mode (rate,byte,band) and adds labels to egress
 * links of the device being hovered over.
 */
public class LinkPropsTopovMessageHandler extends UiMessageHandler {

    private static final String LP_TOPOV_DISPLAY_START = "linkPropsTopovDisplayStart";
    private static final String LP_TOPOV_DISPLAY_UPDATE = "linkPropsTopovDisplayUpdate";
    private static final String LP_TOPOV_DISPLAY_STOP = "linkPropsTopovDisplayStop";

    private static final String ID = "id";
    private static final String MODE = "mode";

    private enum Mode { IDLE, RATE, BYTE, BAND }

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

    private DeviceService deviceService;
    private HostService hostService;
    private LinkService linkService;
    private PortStatisticsService portStatisticsService;
    private ResourceQueryService resourceQueryService;

    private Mode currentMode = Mode.IDLE;
    private Element elementOfNote;


    // ===============-=-=-=-=-=-======================-=-=-=-=-=-=-================================


    @Override
    public void init(UiConnection connection, ServiceDirectory directory) {
        super.init(connection, directory);
        deviceService = directory.get(DeviceService.class);
        hostService = directory.get(HostService.class);
        linkService = directory.get(LinkService.class);
        portStatisticsService = directory.get(PortStatisticsService.class);
        resourceQueryService = directory.get(ResourceQueryService.class);
    }

    @Override
    protected Collection<RequestHandler> createRequestHandlers() {
        return ImmutableSet.of(
                new DisplayStartHandler(),
                new DisplayUpdateHandler(),
                new DisplayStopHandler()
        );
    }

    // === -------------------------
    // === Handler classes

    private final class DisplayStartHandler extends RequestHandler {
        public DisplayStartHandler() {
            super(LP_TOPOV_DISPLAY_START);
        }

        @Override
        public void process(ObjectNode payload) {
            String mode = string(payload, MODE);

            log.debug("Start Display: mode [{}]", mode);
            clearState();
            clearForMode();

            switch (mode) {
                case "rate":
                    currentMode = Mode.RATE;
                    sendRateData();
                    break;

                case "byte":
                    currentMode = Mode.BYTE;
                    sendByteData();
                    break;

                case "band":
                    currentMode = Mode.BAND;
                    sendBandwidth();
                    break;

                default:
                    currentMode = Mode.IDLE;
                    break;
            }
        }
    }

    private final class DisplayUpdateHandler extends RequestHandler {
        public DisplayUpdateHandler() {
            super(LP_TOPOV_DISPLAY_UPDATE);
        }

        @Override
        public void process(ObjectNode payload) {
            String id = string(payload, ID);
            log.debug("Update Display: id [{}]", id);
            if (!Strings.isNullOrEmpty(id)) {
                updateForMode(id);
            } else {
                clearForMode();
            }
        }
    }

    private final class DisplayStopHandler extends RequestHandler {
        public DisplayStopHandler() {
            super(LP_TOPOV_DISPLAY_STOP);
        }

        @Override
        public void process(ObjectNode payload) {
            log.debug("Stop Display");
            clearState();
            clearForMode();
        }
    }

    // === ------------

    private void clearState() {
        currentMode = Mode.IDLE;
        elementOfNote = null;
    }

    private void updateForMode(String id) {
        log.debug("host service: {}", hostService);
        log.debug("device service: {}", deviceService);

        try {
            HostId hid = HostId.hostId(id);
            log.debug("host id {}", hid);
            elementOfNote = hostService.getHost(hid);
            log.debug("host element {}", elementOfNote);

        } catch (Exception e) {
            try {
                DeviceId did = DeviceId.deviceId(id);
                log.debug("device id {}", did);
                elementOfNote = deviceService.getDevice(did);
                log.debug("device element {}", elementOfNote);

            } catch (Exception e2) {
                log.debug("Unable to process ID [{}]", id);
                elementOfNote = null;
            }
        }

        switch (currentMode) {
            case RATE:
                sendRateData();
                break;

            case BYTE:
                sendByteData();
                break;

            case BAND:
                sendBandwidth();
                break;

            default:
                break;
        }

    }

    private void clearForMode() {
        sendHighlights(new Highlights());
    }

    private void sendHighlights(Highlights highlights) {
        sendMessage(TopoJson.highlightsMessage(highlights));
    }


    private void sendRateData() {
        if (elementOfNote != null && elementOfNote instanceof Device) {
            DeviceId devId = (DeviceId) elementOfNote.id();
            Set<Link> links = linkService.getDeviceEgressLinks(devId);
            Highlights highlights = getLinkSpeed(links, devId);
            sendHighlights(highlights);
        }
    }

    private void sendBandwidth() {
        if (elementOfNote != null && elementOfNote instanceof Device) {
            DeviceId devId = (DeviceId) elementOfNote.id();
            Set<Link> links = linkService.getDeviceEgressLinks(devId);
            Highlights highlights = getBandwidth(links, devId);
            sendHighlights(highlights);
        }
    }

    /**
     * Gets the links connected to the highlighted device.
     * Creates a ContinuousResource object for each link
     * and gets the bandwidth of the link from the query
     * and sets the label of the link as the bandwidth value.
     */
    private Highlights getBandwidth(Set<Link> links, DeviceId devId) {
        LpLinkMap linkMap = new LpLinkMap();
        if (links != null) {
            log.debug("Processing {} links", links.size());
            links.forEach(linkMap::add);
        } else {
            log.debug("No egress links found for device {}", devId);
        }

        Highlights highlights = new Highlights();

        PortNumber portnum = PortNumber.portNumber((int) links.iterator().next().src().port().toLong());

        for (LpLink dlink : linkMap.biLinks()) {
            DiscreteResourceId parent = Resources.discrete(devId, portnum).id();
            ContinuousResource continuousResource =
                    (ContinuousResource) resourceQueryService.getAvailableResources(parent,
                                                                                    Bandwidth.class).iterator().next();
            double availBandwidth = continuousResource.value();

            dlink.makeImportant().setLabel(Double.toString(availBandwidth) + " bytes/s");
            highlights.add(dlink.highlight(null));
        }
        return highlights;
    }

    /**
     * Gets the links connected to the highlighted device.
     * Uses PortStatisticsService to get a load object of
     * the links and find the rate of data flow out of the
     * device via that link (src) and into the device via
     * that link (dst), because dlink.two() gives a
     * NullPointerException. Creates a label which displays
     * the src and dst rates for the link.
     */
    private Highlights getLinkSpeed(Set<Link> links, DeviceId devId) {
        LpLinkMap linkMap = new LpLinkMap();
        if (links != null) {
            log.debug("Processing {} links", links.size());
            links.forEach(linkMap::add);
        } else {
            log.debug("No egress links found for device {}", devId);
        }

        Highlights highlights = new Highlights();

        for (LpLink dlink : linkMap.biLinks()) {
            String rate = "Out: " + getSpeedString((portStatisticsService.load(dlink.one().src()).rate())) + " | In: "
                    + getSpeedString((portStatisticsService.load(dlink.one().dst()).rate()));
            dlink.makeImportant().setLabel(rate);
            highlights.add(dlink.highlight(null));
        }
        return highlights;
    }

    private String getSpeedString(Long speed) {
        if (speed > 1_000_000_000) {
            return Long.toString(speed / 1_000_000_000) + "Gb/s";
        } else if (speed > 1_000_000) {
            return Long.toString(speed / 1_000_000) + "Mb/s";
        } else if (speed > 1_000) {
            return Long.toString(speed / 1_000) + "kb/s";
        } else {
            return Long.toString(speed) + "bytes/s";
        }
    }

    private void sendByteData() {
        if (elementOfNote != null && elementOfNote instanceof Device) {
            DeviceId devId = (DeviceId) elementOfNote.id();
            Set<Link> links = linkService.getDeviceEgressLinks(devId);
            Highlights highlights = getTotalBytes(links, devId);
            sendHighlights(highlights);
        }
    }

    /**
     * Gets the links connected to the highlighted device.
     * Uses PortStatisticsService to get a load object of
     * the links and find the total number of bytes sent out
     * of the device via that link (src) and into the device
     * via that link (dst), because dlink.two() gives a
     * NullPointerException. Creates a label which displays
     * the src and dst total bytes for the link.
     */
    private Highlights getTotalBytes(Set<Link> links, DeviceId devId) {
        LpLinkMap linkMap = new LpLinkMap();
        if (links != null) {
            log.debug("Processing {} links", links.size());
            links.forEach(linkMap::add);
        } else {
            log.debug("No egress links found for device {}", devId);
        }

        Highlights highlights = new Highlights();

        for (LpLink dlink : linkMap.biLinks()) {
            String bytes = "Out: " + getBytesString(portStatisticsService.load(dlink.one().src()).latest()) + " | In: "
                    + getBytesString(portStatisticsService.load(dlink.one().dst()).latest());
            dlink.makeImportant().setLabel(bytes);
            highlights.add(dlink.highlight(null));
        }
        return highlights;
    }

    private String getBytesString(Long bytes) {
        final long tb = (long) 1_000_000_000_000.0;
        if (bytes > tb) {
            return Long.toString(bytes / tb) + "Tb";
        } else if (bytes > 1_000_000_000) {
            return Long.toString(bytes / 1_000_000_000) + "Gb";
        } else if (bytes > 1_000_000) {
            return Long.toString(bytes / 1_000_000) + "Mb";
        } else if (bytes > 1_000) {
            return Long.toString(bytes / 1_000) + "kb";
        } else {
            return Long.toString(bytes) + "bytes";
        }
    }

}
