/*
 * Copyright 2015-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.ui.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.ImmutableSet;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.packet.IpAddress;
import org.onlab.packet.VlanId;
import org.onlab.util.DefaultHashMap;
import org.onosproject.cluster.ClusterEvent;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.NodeId;
import org.onosproject.core.CoreService;
import org.onosproject.incubator.net.tunnel.OpticalTunnelEndPoint;
import org.onosproject.incubator.net.tunnel.Tunnel;
import org.onosproject.net.Annotated;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.Annotations;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultEdgeLink;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.EdgeLink;
import org.onosproject.net.ElementId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
import org.onosproject.net.Link;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.host.HostEvent;
import org.onosproject.net.link.LinkEvent;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.net.topology.Topology;
import org.onosproject.ui.JsonUtils;
import org.onosproject.ui.UiConnection;
import org.onosproject.ui.UiMessageHandler;
import org.onosproject.ui.impl.topo.util.ServicesBundle;
import org.onosproject.ui.lion.LionBundle;
import org.onosproject.ui.topo.PropertyPanel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import static com.google.common.base.Strings.isNullOrEmpty;
import static org.onosproject.net.PortNumber.portNumber;
import static org.onosproject.net.config.basics.BasicElementConfig.LOC_TYPE_GEO;
import static org.onosproject.net.config.basics.BasicElementConfig.LOC_TYPE_GRID;
import static org.onosproject.ui.topo.TopoConstants.CoreButtons;
import static org.onosproject.ui.topo.TopoConstants.Properties.DEVICES;
import static org.onosproject.ui.topo.TopoConstants.Properties.FLOWS;
import static org.onosproject.ui.topo.TopoConstants.Properties.GRID_X;
import static org.onosproject.ui.topo.TopoConstants.Properties.GRID_Y;
import static org.onosproject.ui.topo.TopoConstants.Properties.HOSTS;
import static org.onosproject.ui.topo.TopoConstants.Properties.HW_VERSION;
import static org.onosproject.ui.topo.TopoConstants.Properties.INTENTS;
import static org.onosproject.ui.topo.TopoConstants.Properties.IP;
import static org.onosproject.ui.topo.TopoConstants.Properties.LATITUDE;
import static org.onosproject.ui.topo.TopoConstants.Properties.LINKS;
import static org.onosproject.ui.topo.TopoConstants.Properties.LONGITUDE;
import static org.onosproject.ui.topo.TopoConstants.Properties.MAC;
import static org.onosproject.ui.topo.TopoConstants.Properties.PORTS;
import static org.onosproject.ui.topo.TopoConstants.Properties.PROTOCOL;
import static org.onosproject.ui.topo.TopoConstants.Properties.SERIAL_NUMBER;
import static org.onosproject.ui.topo.TopoConstants.Properties.SW_VERSION;
import static org.onosproject.ui.topo.TopoConstants.Properties.TOPOLOGY_SSCS;
import static org.onosproject.ui.topo.TopoConstants.Properties.TUNNELS;
import static org.onosproject.ui.topo.TopoConstants.Properties.URI;
import static org.onosproject.ui.topo.TopoConstants.Properties.VENDOR;
import static org.onosproject.ui.topo.TopoConstants.Properties.VERSION;
import static org.onosproject.ui.topo.TopoConstants.Properties.VLAN;
import static org.onosproject.ui.topo.TopoConstants.Properties.VLAN_NONE;
import static org.onosproject.ui.topo.TopoUtils.compactLinkString;

/**
 * Facility for creating messages bound for the topology viewer.
 */
public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler {

    private static final String NO_GEO_VALUE = "0.0";
    private static final String DASH = "-";
    private static final String SLASH = " / ";

    // nav paths are the view names for hot-link navigation from topo view...
    private static final String DEVICE_NAV_PATH = "device";
    private static final String HOST_NAV_PATH = "host";

    // link panel label keys
    private static final String LPL_FRIENDLY = "lp_label_friendly";
    private static final String LPL_A_TYPE = "lp_label_a_type";
    private static final String LPL_A_ID = "lp_label_a_id";
    private static final String LPL_A_FRIENDLY = "lp_label_a_friendly";
    private static final String LPL_A_PORT = "lp_label_a_port";
    private static final String LPL_B_TYPE = "lp_label_b_type";
    private static final String LPL_B_ID = "lp_label_b_id";
    private static final String LPL_B_FRIENDLY = "lp_label_b_friendly";
    private static final String LPL_B_PORT = "lp_label_b_port";
    private static final String LPL_A2B = "lp_label_a2b";
    private static final String LPL_B2A = "lp_label_b2a";
    private static final String LPV_NO_LINK = "lp_value_no_link";

    // other Lion keys
    private static final String HOST = "host";
    private static final String DEVICE = "device";
    private static final String EXPECTED = "expected";
    private static final String NOT_EXPECTED = "not_expected";

    // default to an "add" event...
    private static final DefaultHashMap<ClusterEvent.Type, String> CLUSTER_EVENT =
            new DefaultHashMap<>("addInstance");

    // default to an "update" event...
    private static final DefaultHashMap<DeviceEvent.Type, String> DEVICE_EVENT =
            new DefaultHashMap<>("updateDevice");
    private static final DefaultHashMap<LinkEvent.Type, String> LINK_EVENT =
            new DefaultHashMap<>("updateLink");
    private static final DefaultHashMap<HostEvent.Type, String> HOST_EVENT =
            new DefaultHashMap<>("updateHost");

    // but call out specific events that we care to differentiate...
    static {
        CLUSTER_EVENT.put(ClusterEvent.Type.INSTANCE_REMOVED, "removeInstance");

        DEVICE_EVENT.put(DeviceEvent.Type.DEVICE_ADDED, "addDevice");
        DEVICE_EVENT.put(DeviceEvent.Type.DEVICE_REMOVED, "removeDevice");

        LINK_EVENT.put(LinkEvent.Type.LINK_ADDED, "addLink");
        LINK_EVENT.put(LinkEvent.Type.LINK_REMOVED, "removeLink");

        HOST_EVENT.put(HostEvent.Type.HOST_ADDED, "addHost");
        HOST_EVENT.put(HostEvent.Type.HOST_REMOVED, "removeHost");
        HOST_EVENT.put(HostEvent.Type.HOST_MOVED, "moveHost");
    }

    private static final DefaultHashMap<Device.Type, String> DEVICE_GLYPHS =
            new DefaultHashMap<>("m_unknown");

    static {
        DEVICE_GLYPHS.put(Device.Type.SWITCH, "m_switch");
        DEVICE_GLYPHS.put(Device.Type.ROUTER, "m_router");
        DEVICE_GLYPHS.put(Device.Type.ROADM, "m_roadm");
        DEVICE_GLYPHS.put(Device.Type.OTN, "m_otn");
        DEVICE_GLYPHS.put(Device.Type.ROADM_OTN, "m_roadm_otn");
        DEVICE_GLYPHS.put(Device.Type.BALANCER, "m_balancer");
        DEVICE_GLYPHS.put(Device.Type.IPS, "m_ips");
        DEVICE_GLYPHS.put(Device.Type.IDS, "m_ids");
        DEVICE_GLYPHS.put(Device.Type.CONTROLLER, "m_controller");
        DEVICE_GLYPHS.put(Device.Type.VIRTUAL, "m_virtual");
        DEVICE_GLYPHS.put(Device.Type.FIBER_SWITCH, "m_fiberSwitch");
        DEVICE_GLYPHS.put(Device.Type.MICROWAVE, "m_microwave");
        DEVICE_GLYPHS.put(Device.Type.OLT, "m_olt");
        DEVICE_GLYPHS.put(Device.Type.ONU, "m_onu");
        DEVICE_GLYPHS.put(Device.Type.OPTICAL_AMPLIFIER, "unknown"); // TODO glyph needed
        DEVICE_GLYPHS.put(Device.Type.OTHER, "m_other");
    }

    private static final String DEFAULT_HOST_GLYPH = "m_endstation";
    private static final String LINK_GLYPH = "m_ports";


    static final Logger log =
            LoggerFactory.getLogger(TopologyViewMessageHandlerBase.class);

    private static final ProviderId PID =
            new ProviderId("core", "org.onosproject.core", true);

    // TODO: extract into an external & durable state; good enough for now and demo
    private static Map<String, ObjectNode> metaUi = new ConcurrentHashMap<>();

    /**
     * Returns read-only view of the meta-ui information.
     *
     * @return map of id to meta-ui mementos
     */
    static Map<String, ObjectNode> getMetaUi() {
        return Collections.unmodifiableMap(metaUi);
    }

    /**
     * Clears any meta-ui information.
     */
    public static void clearMetaUi() {
        metaUi.clear();
    }

    private static final String LION_TOPO = "core.view.Topo";

    private static final Set<String> REQ_LION_BUNDLES = ImmutableSet.of(
            LION_TOPO
    );

    protected ServicesBundle services;

    private String version;


    @Override
    public void init(UiConnection connection, ServiceDirectory directory) {
        super.init(connection, directory);
        services = new ServicesBundle(directory);
        setVersionString(directory);
    }

    // Creates a palatable version string to display on the summary panel
    private void setVersionString(ServiceDirectory directory) {
        String ver = directory.get(CoreService.class).version().toString();
        version = ver.replace(".SNAPSHOT", "*").replaceFirst("~.*$", "");
    }

    @Override
    public Set<String> requiredLionBundles() {
        return REQ_LION_BUNDLES;
    }

    // Returns the first of the given set of IP addresses as a string.
    private String ip(Set<IpAddress> ipAddresses) {
        Iterator<IpAddress> it = ipAddresses.iterator();
        return it.hasNext() ? it.next().toString() : "unknown";
    }

    // Produces JSON structure from annotations.
    private JsonNode props(Annotations annotations) {
        ObjectNode props = objectNode();
        if (annotations != null) {
            for (String key : annotations.keys()) {
                props.put(key, annotations.value(key));
            }
        }
        return props;
    }

    // Produces an informational log message event bound to the client.
    protected ObjectNode info(String message) {
        return message("info", message);
    }

    // Produces a warning log message event bound to the client.
    protected ObjectNode warning(String message) {
        return message("warning", message);
    }

    // Produces an error log message event bound to the client.
    protected ObjectNode error(String message) {
        return message("error", message);
    }

    // Produces a log message event bound to the client.
    private ObjectNode message(String severity, String message) {
        ObjectNode payload = objectNode()
                .put("severity", severity)
                .put("message", message);

        return JsonUtils.envelope("message", payload);
    }

    // Produces a cluster instance message to the client.
    protected ObjectNode instanceMessage(ClusterEvent event, String msgType) {
        ControllerNode node = event.subject();
        int switchCount = services.mastership().getDevicesOf(node.id()).size();
        ObjectNode payload = objectNode()
                .put("id", node.id().toString())
                .put("ip", node.ip().toString())
                .put("online", services.cluster().getState(node.id()).isActive())
                .put("ready", services.cluster().getState(node.id()).isReady())
                .put("uiAttached", node.equals(services.cluster().getLocalNode()))
                .put("switches", switchCount);

        ArrayNode labels = arrayNode();
        labels.add(node.id().toString());
        labels.add(node.ip().toString());

        // Add labels, props and stuff the payload into envelope.
        payload.set("labels", labels);
        addMetaUi(node.id().toString(), payload);

        String type = msgType != null ? msgType : CLUSTER_EVENT.get(event.type());
        return JsonUtils.envelope(type, payload);
    }

    // Produces a device event message to the client.
    protected ObjectNode deviceMessage(DeviceEvent event) {
        Device device = event.subject();
        String uiType = device.annotations().value(AnnotationKeys.UI_TYPE);
        String devType = uiType != null ? uiType :
            services.driver().getDriver(device.id()).getProperty(AnnotationKeys.UI_TYPE);
        if (devType == null) {
            devType = device.type().toString().toLowerCase();
        }
        String name = device.annotations().value(AnnotationKeys.NAME);
        name = isNullOrEmpty(name) ? device.id().toString() : name;

        ObjectNode payload = objectNode()
                .put("id", device.id().toString())
                .put("type", devType)
                .put("online", services.device().isAvailable(device.id()))
                .put("master", master(device.id()));

        payload.set("labels", labels("", name, device.id().toString()));
        payload.set("props", props(device.annotations()));

        if (!addGeoLocation(device, payload) && !addGridLocation(device, payload)) {
            addMetaUi(device.id().toString(), payload);
        }

        String type = DEVICE_EVENT.get(event.type());
        return JsonUtils.envelope(type, payload);
    }

    // Produces a link event message to the client.
    protected ObjectNode linkMessage(LinkEvent event) {
        Link link = event.subject();
        ObjectNode payload = objectNode()
                .put("id", compactLinkString(link))
                .put("type", link.type().toString().toLowerCase())
                .put("expected", link.isExpected())
                .put("online", link.state() == Link.State.ACTIVE)
                .put("linkWidth", 1.2)
                .put("src", link.src().deviceId().toString())
                .put("srcPort", link.src().port().toString())
                .put("dst", link.dst().deviceId().toString())
                .put("dstPort", link.dst().port().toString());
        String type = LINK_EVENT.get(event.type());
        return JsonUtils.envelope(type, payload);
    }

    // Produces a host event message to the client.
    protected ObjectNode hostMessage(HostEvent event) {
        Host host = event.subject();
        Host prevHost = event.prevSubject();
        String hostType = host.annotations().value(AnnotationKeys.UI_TYPE);
        String ip = ip(host.ipAddresses());

        ObjectNode payload = objectNode()
                .put("id", host.id().toString())
                .put("type", isNullOrEmpty(hostType) ? "endstation" : hostType);

        // set most recent connect point (and previous if we know it)
        payload.set("cp", hostConnect(host.location()));
        if (prevHost != null && prevHost.location() != null) {
            payload.set("prevCp", hostConnect(prevHost.location()));
        }

        // set ALL connect points
        addAllCps(host.locations(), payload);

        payload.set("labels", labels(nameForHost(host), ip, host.mac().toString(), ""));
        payload.set("props", props(host.annotations()));

        if (!addGeoLocation(host, payload) && !addGridLocation(host, payload)) {
            addMetaUi(host.id().toString(), payload);
        }

        String type = HOST_EVENT.get(event.type());
        return JsonUtils.envelope(type, payload);
    }

    private void addAllCps(Set<HostLocation> locations, ObjectNode payload) {
        ArrayNode cps = arrayNode();
        locations.forEach(loc -> cps.add(hostConnect(loc)));
        payload.set("allCps", cps);
    }

    // Encodes the specified host location into a JSON object.
    private ObjectNode hostConnect(HostLocation location) {
        return objectNode()
                .put("device", location.deviceId().toString())
                .put("port", location.port().toLong());
    }

    // Encodes the specified list of labels a JSON array.
    private ArrayNode labels(String... labels) {
        ArrayNode json = arrayNode();
        for (String label : labels) {
            json.add(label);
        }
        return json;
    }

    // Returns the name of the master node for the specified device id.
    private String master(DeviceId deviceId) {
        NodeId master = services.mastership().getMasterFor(deviceId);
        return master != null ? master.toString() : "";
    }

    // Generates an edge link from the specified host location.
    private EdgeLink edgeLink(Host host, boolean ingress) {
        return new DefaultEdgeLink(PID, new ConnectPoint(host.id(), portNumber(0)),
                                   host.location(), ingress);
    }

    // Adds meta UI information for the specified object.
    private void addMetaUi(String id, ObjectNode payload) {
        ObjectNode meta = metaUi.get(id);
        if (meta != null) {
            payload.set("metaUi", meta);
        }
    }

    // Adds a geo location JSON to the specified payload object.
    private boolean addGeoLocation(Annotated annotated, ObjectNode payload) {
        Annotations annotations = annotated.annotations();
        if (annotations != null) {
            String locType = annotations.value(AnnotationKeys.LOC_TYPE);
            String slat = annotations.value(AnnotationKeys.LATITUDE);
            String slng = annotations.value(AnnotationKeys.LONGITUDE);
            boolean validLat = slat != null && !slat.equals(NO_GEO_VALUE);
            boolean validLng = slng != null && !slng.equals(NO_GEO_VALUE);

            if (Objects.equals(locType, LOC_TYPE_GEO) && validLat && validLng) {
                try {
                    double lat = Double.parseDouble(slat);
                    double lng = Double.parseDouble(slng);
                    ObjectNode loc = objectNode()
                            .put("locType", "geo")
                            .put("latOrY", lat)
                            .put("longOrX", lng);
                    payload.set("location", loc);
                    return true;
                } catch (NumberFormatException e) {
                    log.warn("Invalid geo data: latitude={}, longitude={}", slat, slng);
                }
            }
        }
        return false;
    }

    // Adds a grid location JSON to the specified payload object.
    private boolean addGridLocation(Annotated annotated, ObjectNode payload) {
        Annotations annotations = annotated.annotations();
        if (annotations != null) {
            String locType = annotations.value(AnnotationKeys.LOC_TYPE);
            String xs = annotations.value(AnnotationKeys.GRID_X);
            String ys = annotations.value(AnnotationKeys.GRID_Y);

            if (Objects.equals(locType, LOC_TYPE_GRID) && xs != null && ys != null) {
                try {
                    double x = Double.parseDouble(xs);
                    double y = Double.parseDouble(ys);
                    ObjectNode loc = objectNode()
                            .put("locType", "grid")
                            .put("latOrY", y)
                            .put("longOrX", x);
                    payload.set("location", loc);
                    return true;
                } catch (NumberFormatException e) {
                    log.warn("Invalid grid data: x={}, y={}", xs, ys);
                }
            }
        }
        return false;
    }

    // Updates meta UI information for the specified object.
    protected void updateMetaUi(ObjectNode payload) {
        metaUi.put(JsonUtils.string(payload, "id"),
                   JsonUtils.node(payload, "memento"));
    }


    // -----------------------------------------------------------------------
    // Create models of the data to return, that overlays can adjust / augment

    private String lookupGlyph(Device device) {
        return DEVICE_GLYPHS.get(device.type());
    }


    // Returns property panel model for summary response.
    protected PropertyPanel summmaryMessage() {
        // chose NOT to add debug messages, since this is called every few seconds
        Topology topology = services.topology().currentTopology();
        LionBundle lion = getLionBundle(LION_TOPO);
        String panelTitle = lion.getSafe("title_panel_summary");

        return new PropertyPanel(panelTitle, "bird")
                .addProp(VERSION, lion.getSafe(VERSION), version)
                .addSeparator()
                .addProp(DEVICES, lion.getSafe(DEVICES), services.device().getDeviceCount())
                .addProp(LINKS, lion.getSafe(LINKS), topology.linkCount())
                .addProp(HOSTS, lion.getSafe(HOSTS), services.host().getHostCount())
                .addProp(TOPOLOGY_SSCS, lion.getSafe(TOPOLOGY_SSCS), topology.clusterCount())
                .addSeparator()
                .addProp(INTENTS, lion.getSafe(INTENTS), services.intent().getIntentCount())
                .addProp(TUNNELS, lion.getSafe(TUNNELS), services.tunnel().tunnelCount())
                .addProp(FLOWS, lion.getSafe(FLOWS), services.flow().getFlowRuleCount());
    }


    private String friendlyDevice(DeviceId deviceId) {
        Device device = services.device().getDevice(deviceId);
        Annotations annot = device.annotations();
        String name = annot.value(AnnotationKeys.NAME);
        return isNullOrEmpty(name) ? deviceId.toString() : name;
    }

    // Generates a property panel model for device details response
    protected PropertyPanel deviceDetails(DeviceId deviceId) {
        log.debug("generate prop panel data for device {}", deviceId);
        Device device = services.device().getDevice(deviceId);
        Annotations annot = device.annotations();
        String proto = annot.value(AnnotationKeys.PROTOCOL);
        String title = friendlyDevice(deviceId);
        LionBundle lion = getLionBundle(LION_TOPO);

        PropertyPanel pp = new PropertyPanel(title, lookupGlyph(device))
                .navPath(DEVICE_NAV_PATH)
                .id(deviceId.toString());
        addDeviceBasicProps(pp, deviceId, device, proto, lion);
        addLocationProps(pp, annot, lion);
        addDeviceCountStats(pp, deviceId, lion);
        addDeviceCoreButtons(pp);
        return pp;
    }

    private void addDeviceBasicProps(PropertyPanel pp, DeviceId deviceId,
                                     Device device, String proto, LionBundle lion) {
        pp.addProp(URI, lion.getSafe(URI), deviceId.toString())
                .addProp(VENDOR, lion.getSafe(VENDOR), device.manufacturer())
                .addProp(HW_VERSION, lion.getSafe(HW_VERSION), device.hwVersion())
                .addProp(SW_VERSION, lion.getSafe(SW_VERSION), device.swVersion())
                .addProp(SERIAL_NUMBER, lion.getSafe(SERIAL_NUMBER), device.serialNumber())
                .addProp(PROTOCOL, lion.getSafe(PROTOCOL), proto)
                .addSeparator();
    }

    // only add location properties if we have them
    private void addLocationProps(PropertyPanel pp, Annotations annot,
                                  LionBundle lion) {
        String slat = annot.value(AnnotationKeys.LATITUDE);
        String slng = annot.value(AnnotationKeys.LONGITUDE);
        String sgrY = annot.value(AnnotationKeys.GRID_Y);
        String sgrX = annot.value(AnnotationKeys.GRID_X);

        boolean validLat = slat != null && !slat.equals(NO_GEO_VALUE);
        boolean validLng = slng != null && !slng.equals(NO_GEO_VALUE);
        if (validLat && validLng) {
            pp.addProp(LATITUDE, lion.getSafe(LATITUDE), slat)
                    .addProp(LONGITUDE, lion.getSafe(LONGITUDE), slng)
                    .addSeparator();

        } else if (sgrY != null && sgrX != null) {
            pp.addProp(GRID_Y, lion.getSafe(GRID_Y), sgrY)
                    .addProp(GRID_X, lion.getSafe(GRID_X), sgrX)
                    .addSeparator();
        }
        // else, no location
    }

    private void addDeviceCountStats(PropertyPanel pp, DeviceId deviceId, LionBundle lion) {
        int portCount = services.device().getPorts(deviceId).size();
        int flowCount = getFlowCount(deviceId);
        int tunnelCount = getTunnelCount(deviceId);

        pp.addProp(PORTS, lion.getSafe(PORTS), portCount)
                .addProp(FLOWS, lion.getSafe(FLOWS), flowCount)
                .addProp(TUNNELS, lion.getSafe(TUNNELS), tunnelCount);
    }

    private void addDeviceCoreButtons(PropertyPanel pp) {
        pp.addButton(CoreButtons.SHOW_DEVICE_VIEW)
                .addButton(CoreButtons.SHOW_FLOW_VIEW)
                .addButton(CoreButtons.SHOW_PORT_VIEW)
                .addButton(CoreButtons.SHOW_GROUP_VIEW)
                .addButton(CoreButtons.SHOW_METER_VIEW);
    }

    protected int getFlowCount(DeviceId deviceId) {
        return services.flow().getFlowRuleCount(deviceId);
    }

    protected int getTunnelCount(DeviceId deviceId) {
        int count = 0;
        Collection<Tunnel> tunnels = services.tunnel().queryAllTunnels();
        for (Tunnel tunnel : tunnels) {
            //Only OpticalTunnelEndPoint has a device
            if (!(tunnel.src() instanceof OpticalTunnelEndPoint) ||
                    !(tunnel.dst() instanceof OpticalTunnelEndPoint)) {
                continue;
            }

            Optional<ElementId> srcElementId = ((OpticalTunnelEndPoint) tunnel.src()).elementId();
            Optional<ElementId> dstElementId = ((OpticalTunnelEndPoint) tunnel.dst()).elementId();
            if (!srcElementId.isPresent() || !dstElementId.isPresent()) {
                continue;
            }
            DeviceId srcDeviceId = (DeviceId) srcElementId.get();
            DeviceId dstDeviceId = (DeviceId) dstElementId.get();
            if (srcDeviceId.equals(deviceId) || dstDeviceId.equals(deviceId)) {
                count++;
            }
        }
        return count;
    }

    private boolean useDefaultName(String annotName) {
        return isNullOrEmpty(annotName) || DASH.equals(annotName);
    }

    private String nameForHost(Host host) {
        String name = host.annotations().value(AnnotationKeys.NAME);
        return useDefaultName(name) ? ip(host.ipAddresses()) : name;
    }

    private String glyphForHost(Annotations annot) {
        String uiType = annot.value(AnnotationKeys.UI_TYPE);
        return isNullOrEmpty(uiType) ? DEFAULT_HOST_GLYPH : uiType;
    }

    // Generates a property panel model for a host details response
    protected PropertyPanel hostDetails(HostId hostId) {
        log.debug("generate prop panel data for host {}", hostId);
        Host host = services.host().getHost(hostId);
        Annotations annot = host.annotations();
        String glyphId = glyphForHost(annot);
        LionBundle lion = getLionBundle(LION_TOPO);

        PropertyPanel pp = new PropertyPanel(nameForHost(host), glyphId)
                .navPath(HOST_NAV_PATH)
                .id(hostId.toString());
        addHostBasicProps(pp, host, lion);
        addLocationProps(pp, annot, lion);
        return pp;
    }

    private void addHostBasicProps(PropertyPanel pp, Host host, LionBundle lion) {
        pp.addProp(LPL_FRIENDLY, lion.getSafe(LPL_FRIENDLY), nameForHost(host))
                .addProp(MAC, lion.getSafe(MAC), host.mac())
                .addProp(IP, lion.getSafe(IP), host.ipAddresses(), "[\\[\\]]")
                .addProp(VLAN, lion.getSafe(VLAN), displayVlan(host.vlan(), lion))
                .addSeparator();
    }

    private String displayVlan(VlanId vlan, LionBundle lion) {
        return VlanId.NONE.equals(vlan) ? lion.getSafe(VLAN_NONE) : vlan.toString();
    }

    // Generates a property panel model for a link details response (edge-link)
    protected PropertyPanel edgeLinkDetails(HostId hid, ConnectPoint cp) {
        log.debug("generate prop panel data for edgelink {} {}", hid, cp);
        LionBundle lion = getLionBundle(LION_TOPO);
        String title = lion.getSafe("title_edge_link");

        PropertyPanel pp = new PropertyPanel(title, LINK_GLYPH);
        addLinkHostProps(pp, hid, lion);
        addLinkCpBProps(pp, cp, lion);
        return pp;
    }

    // Generates a property panel model for a link details response (infra-link)
    protected PropertyPanel infraLinkDetails(ConnectPoint cpA, ConnectPoint cpB) {
        log.debug("generate prop panel data for infralink {} {}", cpA, cpB);
        LionBundle lion = getLionBundle(LION_TOPO);
        String title = lion.getSafe("title_infra_link");

        PropertyPanel pp = new PropertyPanel(title, LINK_GLYPH);
        addLinkCpAProps(pp, cpA, lion);
        addLinkCpBProps(pp, cpB, lion);
        addLinkBackingProps(pp, cpA, cpB, lion);
        return pp;
    }

    private void addLinkHostProps(PropertyPanel pp, HostId hostId, LionBundle lion) {
        Host host = services.host().getHost(hostId);

        pp.addProp(LPL_A_TYPE, lion.getSafe(LPL_A_TYPE), lion.getSafe(HOST))
                .addProp(LPL_A_ID, lion.getSafe(LPL_A_ID), hostId.toString())
                .addProp(LPL_A_FRIENDLY, lion.getSafe(LPL_A_FRIENDLY), nameForHost(host))
                .addSeparator();
    }

    private void addLinkCpAProps(PropertyPanel pp, ConnectPoint cp, LionBundle lion) {
        DeviceId did = cp.deviceId();

        pp.addProp(LPL_A_TYPE, lion.getSafe(LPL_A_TYPE), lion.getSafe(DEVICE))
                .addProp(LPL_A_ID, lion.getSafe(LPL_A_ID), did.toString())
                .addProp(LPL_A_FRIENDLY, lion.getSafe(LPL_A_FRIENDLY), friendlyDevice(did))
                .addProp(LPL_A_PORT, lion.getSafe(LPL_A_PORT), cp.port().toLong())
                .addSeparator();
    }

    private void addLinkCpBProps(PropertyPanel pp, ConnectPoint cp, LionBundle lion) {
        DeviceId did = cp.deviceId();

        pp.addProp(LPL_B_TYPE, lion.getSafe(LPL_B_TYPE), lion.getSafe(DEVICE))
                .addProp(LPL_B_ID, lion.getSafe(LPL_B_ID), did.toString())
                .addProp(LPL_B_FRIENDLY, lion.getSafe(LPL_B_FRIENDLY), friendlyDevice(did))
                .addProp(LPL_B_PORT, lion.getSafe(LPL_B_PORT), cp.port().toLong())
                .addSeparator();
    }

    private void addLinkBackingProps(PropertyPanel pp, ConnectPoint cpA,
                                     ConnectPoint cpB, LionBundle lion) {
        Link a2b = services.link().getLink(cpA, cpB);
        Link b2a = services.link().getLink(cpB, cpA);

        pp.addProp(LPL_A2B, lion.getSafe(LPL_A2B), linkPropString(a2b, lion))
                .addProp(LPL_B2A, lion.getSafe(LPL_B2A), linkPropString(b2a, lion));
    }

    private String linkPropString(Link link, LionBundle lion) {
        if (link == null) {
            return lion.getSafe(LPV_NO_LINK);
        }
        return lion.getSafe(link.type()) + SLASH +
                lion.getSafe(link.state()) + SLASH +
                lion.getSafe(link.isExpected() ? EXPECTED : NOT_EXPECTED);
    }
}
