/*
 * 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.flow.FlowEntry;
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.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.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";


    protected 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);
    }

    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 :
                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()));
        addGeoLocation(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)
                .put("ingress", compactLinkString(edgeLink(host, true)))
                .put("egress", compactLinkString(edgeLink(host, false)));

        payload.set("cp", hostConnect(host.location()));
        if (prevHost != null && prevHost.location() != null) {
            payload.set("prevCp", hostConnect(prevHost.location()));
        }
        payload.set("labels", labels(nameForHost(host), ip, host.mac().toString()));
        payload.set("props", props(host.annotations()));
        addGeoLocation(host, payload);
        addMetaUi(host.id().toString(), payload);

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

    // 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 void addGeoLocation(Annotated annotated, ObjectNode payload) {
        Annotations annotations = annotated.annotations();
        if (annotations == null) {
            return;
        }

        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 (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);
            } catch (NumberFormatException e) {
                log.warn("Invalid geo data: latitude={}, longitude={}", slat, slng);
            }
        }
    }

    // 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) {
        int count = 0;
        for (FlowEntry flowEntry : services.flow().getFlowEntries(deviceId)) {
            count++;
        }
        return count;
    }

    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);
    }
}
