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


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

        // 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()));
        addGeoLocation(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 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) {
        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);
    }
}
