/*
 * Copyright 2014 Open Networking Laboratory
 *
 * 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.
 */

/*
 ONOS network topology viewer - version 1.1

 @author Simon Hunt
 */

(function (onos) {
    'use strict';

    // shorter names for library APIs
    var d3u = onos.lib.d3util,
        gly = onos.lib.glyphs,
        trace;

    // configuration data
    var config = {
        useLiveData: true,
        fnTrace: true,
        debugOn: false,
        debug: {
            showNodeXY: true,
            showKeyHandler: false
        },
        birdDim: 400,
        options: {
            layering: true,
            collisionPrevention: true,
            showBackground: true
        },
        backgroundUrl: 'img/us-map.png',
        webSockUrl: 'ws/topology',
        data: {
            live: {
                jsonUrl: 'rs/topology/graph',
                detailPrefix: 'rs/topology/graph/',
                detailSuffix: ''
            },
            fake: {
                jsonUrl: 'json/network2.json',
                detailPrefix: 'json/',
                detailSuffix: '.json'
            }
        },
        labels: {
            imgPad: 16,
            padLR: 4,
            padTB: 3,
            marginLR: 3,
            marginTB: 2,
            port: {
                gap: 3,
                width: 18,
                height: 14
            }
        },
        topo: {
            linkBaseColor: '#666',
            linkInColor: '#66f',
            linkInWidth: 14,
            linkOutColor: '#f00',
            linkOutWidth: 30
        },
        icons: {
            w: 28,
            h: 28,
            xoff: -12,
            yoff: -8
        },
        iconUrl: {
            device: 'img/device.png',
            host: 'img/host.png',
            pkt: 'img/pkt.png',
            opt: 'img/opt.png'
        },
        force: {
            note_for_links: 'link.type is used to differentiate',
            linkDistance: {
                direct: 100,
                optical: 120,
                hostLink: 3
            },
            linkStrength: {
                direct: 1.0,
                optical: 1.0,
                hostLink: 1.0
            },
            note_for_nodes: 'node.class is used to differentiate',
            charge: {
                device: -8000,
                host: -5000
            },
            pad: 20,
            translate: function() {
                return 'translate(' +
                    config.force.pad + ',' +
                    config.force.pad + ')';
            }
        },
        // see below in creation of viewBox on main svg
        logicalSize: 1000
    };

    // radio buttons
    var layerButtons = [
            { text: 'All Layers', id: 'all', cb: showAllLayers },
            { text: 'Packet Only', id: 'pkt', cb: showPacketLayer },
            { text: 'Optical Only', id: 'opt', cb: showOpticalLayer }
        ],
        layerBtnSet,
        layerBtnDispatch = {
            all: showAllLayers,
            pkt: showPacketLayer,
            opt: showOpticalLayer
        };

    // key bindings
    var keyDispatch = {
        M: testMe,                  // TODO: remove (testing only)
        S: injectStartupEvents,     // TODO: remove (testing only)
        space: injectTestEvent,     // TODO: remove (testing only)

        B: toggleBg,
        L: cycleLabels,
        P: togglePorts,
        U: unpin,
        R: resetZoomPan,
        esc: handleEscape
    };

    // state variables
    var network = {
            view: null,     // view token reference
            nodes: [],
            links: [],
            lookup: {},
            revLinkToKey: {}
        },
        scenario = {
            evDir: 'json/ev/',
            evScenario: '/scenario.json',
            evPrefix: '/ev_',
            evOnos: '_onos.json',
            evUi: '_ui.json',
            ctx: null,
            params: {},
            evNumber: 0,
            view: null,
            debug: false
        },
        webSock,
        sid = 0,
        deviceLabelIndex = 0,
        hostLabelIndex = 0,
        selections = {},
        selectOrder = [],
        hovered = null,
        detailPane,
        antTimer = null,
        onosInstances = {},
        onosOrder = [],
        oiBox,
        oiShowMaster = false,

        portLabelsOn = false;

    // D3 selections
    var svg,
        zoomPanContainer,
        bgImg,
        topoG,
        nodeG,
        linkG,
        node,
        link,
        mask;

    // the projection for the map background
    var geoMapProjection;

    // the zoom function
    var zoom;

    // ==============================
    // For Debugging / Development

    function note(label, msg) {
        console.log('NOTE: ' + label + ': ' + msg);
    }

    function debug(what) {
        return config.debugOn && config.debug[what];
    }

    function fnTrace(msg, id) {
        if (config.fnTrace) {
            console.log('FN: ' + msg + ' [' + id + ']');
        }
    }

    function evTrace(data) {
        fnTrace(data.event, data.payload.id);
    }

    // ==============================
    // Key Callbacks

    function testMe(view) {
        //view.alert('test');
        noWebSock(true);
    }

    function abortIfLive() {
        if (config.useLiveData) {
            network.view.alert("Sorry, currently using live data..");
            return true;
        }
        return false;
    }

    function testDebug(msg) {
        if (scenario.debug) {
            scenario.view.alert(msg);
        }
    }

    function injectTestEvent(view) {
        if (abortIfLive()) { return; }
        var sc = scenario,
            evn = ++sc.evNumber,
            pfx = sc.evDir + sc.ctx + sc.evPrefix + evn,
            onosUrl = pfx + sc.evOnos,
            uiUrl = pfx + sc.evUi,
            stack = [
                { url: onosUrl, cb: handleServerEvent },
                { url: uiUrl, cb: handleUiEvent }
            ];
        recurseFetchEvent(stack, evn);
    }

    function recurseFetchEvent(stack, evn) {
        var v = scenario.view,
            frame;
        if (stack.length === 0) {
            v.alert('Oops!\n\nNo event #' + evn + ' found.');
            return;
        }
        frame = stack.shift();

        d3.json(frame.url, function (err, data) {
            if (err) {
                if (err.status === 404) {
                    // if we didn't find the data, try the next stack frame
                    recurseFetchEvent(stack, evn);
                } else {
                    v.alert('non-404 error:\n\n' + frame.url + '\n\n' + err);
                }
            } else {
                testDebug('loaded: ' + frame.url);
                wsTrace('test', JSON.stringify(data));
                frame.cb(data);
            }
        });

    }

    function handleUiEvent(data) {
        scenario.view.alert('UI Tx: ' + data.event + '\n\n' +
            JSON.stringify(data));
    }

    function injectStartupEvents(view) {
        var last = scenario.params.lastAuto || 0;
        if (abortIfLive()) { return; }

        while (scenario.evNumber < last) {
            injectTestEvent(view);
        }
    }

    function toggleBg() {
        var vis = bgImg.style('visibility');
        bgImg.style('visibility', (vis === 'hidden') ? 'visible' : 'hidden');
    }

    function cycleLabels() {
        deviceLabelIndex = (deviceLabelIndex === network.deviceLabelCount - 1)
            ? 0 : deviceLabelIndex + 1;

        network.nodes.forEach(function (d) {
            if (d.class === 'device') {
                updateDeviceLabel(d);
            }
        });
    }

    function togglePorts(view) {
        view.alert('togglePorts() callback')
    }

    function unpin() {
        if (hovered) {
            hovered.fixed = false;
            hovered.el.classed('fixed', false);
            network.force.resume();
        }
    }

    function handleEscape(view) {
        if (oiShowMaster) {
            cancelAffinity();
        } else {
            deselectAll();
        }
    }

    // ==============================
    // Radio Button Callbacks

    var layerLookup = {
        host: {
            endstation: 'pkt', // default, if host event does not define type
            bgpSpeaker: 'pkt'
        },
        device: {
            switch: 'pkt',
            roadm: 'opt'
        },
        link: {
            hostLink: 'pkt',
            direct: 'pkt',
            indirect: '',
            tunnel: '',
            optical: 'opt'
        }
    };

    function inLayer(d, layer) {
        var type = d.class === 'link' ? d.type() : d.type,
            look = layerLookup[d.class],
            lyr = look && look[type];
        return lyr === layer;
    }

    function unsuppressLayer(which) {
        node.each(function (d) {
            var node = d.el;
            if (inLayer(d, which)) {
                node.classed('suppressed', false);
            }
        });

        link.each(function (d) {
            var link = d.el;
            if (inLayer(d, which)) {
                link.classed('suppressed', false);
            }
        });
    }

    function suppressLayers(b) {
        node.classed('suppressed', b);
        link.classed('suppressed', b);
//        d3.selectAll('svg .port').classed('inactive', false);
//        d3.selectAll('svg .portText').classed('inactive', false);
    }

    function showAllLayers() {
        suppressLayers(false);
    }

    function showPacketLayer() {
        node.classed('suppressed', true);
        link.classed('suppressed', true);
        unsuppressLayer('pkt');
    }

    function showOpticalLayer() {
        node.classed('suppressed', true);
        link.classed('suppressed', true);
        unsuppressLayer('opt');
    }

    function restoreLayerState() {
        layerBtnDispatch[layerBtnSet.selected()]();
    }

    // ==============================
    // Private functions

    function safeId(s) {
        return s.replace(/[^a-z0-9]/gi, '-');
    }

    // set the size of the given element to that of the view (reduced if padded)
    function setSize(el, view, pad) {
        var padding = pad ? pad * 2 : 0;
        el.attr({
            width: view.width() - padding,
            height: view.height() - padding
        });
    }

    function makeNodeKey(d, what) {
        var port = what + 'Port';
        return d[what] + '/' + d[port];
    }

    function makeLinkKey(d, flipped) {
        var one = flipped ? makeNodeKey(d, 'dst') : makeNodeKey(d, 'src'),
            two = flipped ? makeNodeKey(d, 'src') : makeNodeKey(d, 'dst');
        return one + '-' + two;
    }

    function findLinkById(id) {
        // check to see if this is a reverse lookup, else default to given id
        var key = network.revLinkToKey[id] || id;
            return key && network.lookup[key];
    }

    function findLink(linkData, op) {
        var key = makeLinkKey(linkData),
            keyrev = makeLinkKey(linkData, 1),
            link = network.lookup[key],
            linkRev = network.lookup[keyrev],
            result = {},
            ldata = link || linkRev,
            rawLink;

        if (op === 'add') {
            if (link) {
                // trying to add a link that we already know about
                result.ldata = link;
                result.badLogic = 'addLink: link already added';

            } else if (linkRev) {
                // we found the reverse of the link to be added
                result.ldata = linkRev;
                if (linkRev.fromTarget) {
                    result.badLogic = 'addLink: link already added';
                }
            }
        } else if (op === 'update') {
            if (!ldata) {
                result.badLogic = 'updateLink: link not found';
            } else {
                rawLink = link ? ldata.fromSource : ldata.fromTarget;
                result.updateWith = function (data) {
                    $.extend(rawLink, data);
                    restyleLinkElement(ldata);
                }
            }
        } else if (op === 'remove') {
            if (!ldata) {
                result.badLogic = 'removeLink: link not found';
            } else {
                rawLink = link ? ldata.fromSource : ldata.fromTarget;

                if (!rawLink) {
                    result.badLogic = 'removeLink: link not found';

                } else {
                    result.removeRawLink = function () {
                        if (link) {
                            // remove fromSource
                            ldata.fromSource = null;
                            if (ldata.fromTarget) {
                                // promote target into source position
                                ldata.fromSource = ldata.fromTarget;
                                ldata.fromTarget = null;
                                ldata.key = keyrev;
                                delete network.lookup[key];
                                network.lookup[keyrev] = ldata;
                                delete network.revLinkToKey[keyrev];
                            }
                        } else {
                            // remove fromTarget
                            ldata.fromTarget = null;
                            delete network.revLinkToKey[keyrev];
                        }
                        if (ldata.fromSource) {
                            restyleLinkElement(ldata);
                        } else {
                            removeLinkElement(ldata);
                        }
                    }
                }
            }
        }
        return result;
    }

    function addLinkUpdate(ldata, link) {
        // add link event, but we already have the reverse link installed
        ldata.fromTarget = link;
        network.revLinkToKey[link.id] = ldata.key;
        restyleLinkElement(ldata);
    }

    var allLinkTypes = 'direct indirect optical tunnel',
        defaultLinkType = 'direct';

    function restyleLinkElement(ldata) {
        // this fn's job is to look at raw links and decide what svg classes
        // need to be applied to the line element in the DOM
        var el = ldata.el,
            type = ldata.type(),
            lw = ldata.linkWidth(),
            online = ldata.online();

        el.classed('link', true);
        el.classed('inactive', !online);
        el.classed(allLinkTypes, false);
        if (type) {
            el.classed(type, true);
        }
        el.transition()
            .duration(1000)
            .attr('stroke-width', linkScale(lw))
            .attr('stroke', config.topo.linkBaseColor);
    }

    // ==============================
    // Event handlers for server-pushed events

    function logicError(msg) {
        // TODO, report logic error to server, via websock, so it can be logged
        //network.view.alert('Logic Error:\n\n' + msg);
        console.warn(msg);
    }

    var eventDispatch = {
        addInstance: addInstance,
        addDevice: addDevice,
        addLink: addLink,
        addHost: addHost,

        updateInstance: stillToImplement,
        updateDevice: updateDevice,
        updateLink: updateLink,
        updateHost: updateHost,

        removeInstance: stillToImplement,
        removeDevice: stillToImplement,
        removeLink: removeLink,
        removeHost: removeHost,

        showDetails: showDetails,
        showTraffic: showTraffic
    };

    function addInstance(data) {
        evTrace(data);
        var inst = data.payload,
            id = inst.id;
        if (onosInstances[id]) {
            logicError('ONOS instance already added: ' + id);
            return;
        }
        onosInstances[id] = inst;
        onosOrder.push(inst);
        updateInstances();
    }

    function addDevice(data) {
        evTrace(data);
        var device = data.payload,
            nodeData = createDeviceNode(device);
        network.nodes.push(nodeData);
        network.lookup[nodeData.id] = nodeData;
        updateNodes();
        network.force.start();
    }

    function addLink(data) {
        evTrace(data);
        var link = data.payload,
            result = findLink(link, 'add'),
            bad = result.badLogic,
            ldata = result.ldata;

        if (bad) {
            logicError(bad + ': ' + link.id);
            return;
        }

        if (ldata) {
            // we already have a backing store link for src/dst nodes
            addLinkUpdate(ldata, link);
            return;
        }

        // no backing store link yet
        ldata = createLink(link);
        if (ldata) {
            network.links.push(ldata);
            network.lookup[ldata.key] = ldata;
            updateLinks();
            network.force.start();
        }
    }

    function addHost(data) {
        evTrace(data);
        var host = data.payload,
            node = createHostNode(host),
            lnk;
        network.nodes.push(node);
        network.lookup[host.id] = node;
        updateNodes();

        lnk = createHostLink(host);
        if (lnk) {
            node.linkData = lnk;    // cache ref on its host
            network.links.push(lnk);
            network.lookup[host.ingress] = lnk;
            network.lookup[host.egress] = lnk;
            updateLinks();
        }
        network.force.start();
    }

    // TODO: fold updateX(...) methods into one base method; remove duplication
    function updateDevice(data) {
        evTrace(data);
        var device = data.payload,
            id = device.id,
            nodeData = network.lookup[id];
        if (nodeData) {
            $.extend(nodeData, device);
            updateDeviceState(nodeData);
        } else {
            logicError('updateDevice lookup fail. ID = "' + id + '"');
        }
    }

    function updateLink(data) {
        evTrace(data);
        var link = data.payload,
            result = findLink(link, 'update'),
            bad = result.badLogic;
        if (bad) {
            logicError(bad + ': ' + link.id);
            return;
        }
        result.updateWith(link);
    }

    function updateHost(data) {
        evTrace(data);
        var host = data.payload,
            id = host.id,
            hostData = network.lookup[id];
        if (hostData) {
            $.extend(hostData, host);
            updateHostState(hostData);
        } else {
            logicError('updateHost lookup fail. ID = "' + id + '"');
        }
    }

    // TODO: fold removeX(...) methods into base method - remove dup code
    function removeLink(data) {
        evTrace(data);
        var link = data.payload,
            result = findLink(link, 'remove'),
            bad = result.badLogic;
        if (bad) {
            logicError(bad + ': ' + link.id);
            return;
        }
        result.removeRawLink();
    }

    function removeHost(data) {
        evTrace(data);
        var host = data.payload,
            id = host.id,
            hostData = network.lookup[id];
        if (hostData) {
            removeHostElement(hostData);
        } else {
            logicError('removeHost lookup fail. ID = "' + id + '"');
        }
    }

    function showDetails(data) {
        evTrace(data);
        populateDetails(data.payload);
        detailPane.show();
    }

    function showTraffic(data) {
        evTrace(data);
        var paths = data.payload.paths;

        // Revert any links hilighted previously.
        link.classed('primary secondary animated optical', false);

        // Now hilight all links in the paths payload.
        paths.forEach(function (p) {
            var cls = p.class;
            p.links.forEach(function (id) {
                var lnk = findLinkById(id);
                if (lnk) {
                    lnk.el.classed(cls, true);
                }
            });
        });
    }

    // ...............................

    function stillToImplement(data) {
        var p = data.payload;
        note(data.event, p.id);
        network.view.alert('Not yet implemented: "' + data.event + '"');
    }

    function unknownEvent(data) {
        network.view.alert('Unknown event type: "' + data.event + '"');
    }

    function handleServerEvent(data) {
        var fn = eventDispatch[data.event] || unknownEvent;
        fn(data);
    }

    // ==============================
    // Out-going messages...

    function userFeedback(msg) {
        // for now, use the alert pane as is. Maybe different alert style in
        // the future (centered on view; dismiss button?)
        network.view.alert(msg);
    }

    function nSel() {
        return selectOrder.length;
    }
    function getSel(idx) {
        return selections[selectOrder[idx]];
    }
    function getSelId(idx) {
        return getSel(idx).obj.id;
    }
    function allSelectionsClass(cls) {
        for (var i=0, n=nSel(); i<n; i++) {
            if (getSel(i).obj.class !== cls) {
                return false;
            }
        }
        return true;
    }

    // request details for the selected element
    // invoked from selection of a single node.
    function requestDetails() {
        var data = getSel(0).obj,
            payload = {
                id: data.id,
                class: data.class
            };
        sendMessage('requestDetails', payload);
    }

    function addIntentAction() {
        sendMessage('addHostIntent', {
            one: getSelId(0),
            two: getSelId(1),
            ids: [ getSelId(0), getSelId(1) ]
        });
    }

    function showTrafficAction() {
        // if nothing is hovered over, and nothing selected, send cancel request
        if (!hovered && nSel() === 0) {
            sendMessage('cancelTraffic', {});
            return;
        }

        // NOTE: hover is only populated if "show traffic on hover" is
        //        toggled on, and the item hovered is a host...
        var hoverId = (trafficHover() && hovered && hovered.class === 'host')
                        ? hovered.id : '';
        sendMessage('requestTraffic', {
            ids: selectOrder,
            hover: hoverId
        });
    }


    // ==============================
    // onos instance panel functions

    function updateInstances() {
        var onoses = oiBox.el.selectAll('.onosInst')
            .data(onosOrder, function (d) { return d.id; });

        // operate on existing onoses if necessary

        var entering = onoses.enter()
            .append('div')
            .attr('class', 'onosInst')
            .classed('online', function (d) { return d.online; })
            .on('click', clickInst);

        entering.each(function (d, i) {
            var el = d3.select(this),
                img;

            $('<img src="img/host.png">').appendTo(el);
            img = el.select('img')
                .attr({
                    width: 40,
                    top: -10,
                    left: -10
                })
                .style({
                });

            $('<div>').attr('class', 'onosTitle').text(d.id).appendTo(el);

            // is the UI attached to this instance?
            // TODO: need uiAttached boolean in instance data
            //if (d.uiAttached) {
            if (i === 0) {
                $('<img src="img/ui.png">').attr('class','ui').appendTo(el);
            }
        });

        // operate on existing + new onoses here

        // the departed...
        var exiting = onoses.exit()
            .transition()
            .style('opacity', 0)
            .remove();
    }

    function clickInst(d) {
        var el = d3.select(this),
            aff = el.classed('affinity');
        if (!aff) {
            setAffinity(el, d);
        } else {
            cancelAffinity();
        }
    }

    function setAffinity(el, d) {
        d3.selectAll('.onosInst')
            .classed('mastership', true)
            .classed('affinity', false);
        el.classed('affinity', true);

        suppressLayers(true);
        node.each(function (n) {
             if (n.master === d.id) {
                 n.el.classed('suppressed', false);
             }
        });
        oiShowMaster = true;
    }

    function cancelAffinity() {
        d3.selectAll('.onosInst')
            .classed('mastership affinity', false);
        restoreLayerState();
        oiShowMaster = false;
    }

    // ==============================
    // force layout modification functions

    function translate(x, y) {
        return 'translate(' + x + ',' + y + ')';
    }

    function missMsg(what, id) {
        return '\n[' + what + '] "' + id + '" missing ';
    }

    function linkEndPoints(srcId, dstId) {
        var srcNode = network.lookup[srcId],
            dstNode = network.lookup[dstId],
            sMiss = !srcNode ? missMsg('src', srcId) : '',
            dMiss = !dstNode ? missMsg('dst', dstId) : '';

        if (sMiss || dMiss) {
            logicError('Node(s) not on map for link:\n' + sMiss + dMiss);
            return null;
        }
        return {
            source: srcNode,
            target: dstNode,
            x1: srcNode.x,
            y1: srcNode.y,
            x2: dstNode.x,
            y2: dstNode.y
        };
    }

    function createHostLink(host) {
        var src = host.id,
            dst = host.cp.device,
            id = host.ingress,
            lnk = linkEndPoints(src, dst);

        if (!lnk) {
            return null;
        }

        // Synthesize link ...
        $.extend(lnk, {
            key: id,
            class: 'link',

            type: function () { return 'hostLink'; },
            // TODO: ideally, we should see if our edge switch is online...
            online: function () { return true; },
            linkWidth: function () { return 1; }
        });
        return lnk;
    }

    function createLink(link) {
        var lnk = linkEndPoints(link.src, link.dst),
            type = link.type;

        if (!lnk) {
            return null;
        }

        $.extend(lnk, {
            key: link.id,
            class: 'link',
            fromSource: link,

            // functions to aggregate dual link state
            type: function () {
                var s = lnk.fromSource,
                    t = lnk.fromTarget;
                return (s && s.type) || (t && t.type) || defaultLinkType;
            },
            online: function () {
                var s = lnk.fromSource,
                    t = lnk.fromTarget;
                return (s && s.online) || (t && t.online);
            },
            linkWidth: function () {
                var s = lnk.fromSource,
                    t = lnk.fromTarget,
                    ws = (s && s.linkWidth) || 0,
                    wt = (t && t.linkWidth) || 0;
                return Math.max(ws, wt);
            }
        });
        return lnk;
    }

    var widthRatio = 1.4,
        linkScale = d3.scale.linear()
            .domain([1, 12])
            .range([widthRatio, 12 * widthRatio])
            .clamp(true);

    function updateLinks() {
        link = linkG.selectAll('.link')
            .data(network.links, function (d) { return d.key; });

        // operate on existing links, if necessary
        // link .foo() .bar() ...

        // operate on entering links:
        var entering = link.enter()
            .append('line')
            .attr({
                x1: function (d) { return d.x1; },
                y1: function (d) { return d.y1; },
                x2: function (d) { return d.x2; },
                y2: function (d) { return d.y2; },
                stroke: config.topo.linkInColor,
                'stroke-width': config.topo.linkInWidth
            });

        // augment links
        entering.each(function (d) {
            var link = d3.select(this);
            // provide ref to element selection from backing data....
            d.el = link;
            restyleLinkElement(d);

            // TODO: add src/dst port labels etc.
        });

        // operate on both existing and new links, if necessary
        //link .foo() .bar() ...

        // operate on exiting links:
        link.exit()
            .attr('stroke-dasharray', '3, 3')
            .style('opacity', 0.5)
            .transition()
            .duration(1500)
            .attr({
                'stroke-dasharray': '3, 12',
                stroke: config.topo.linkOutColor,
                'stroke-width': config.topo.linkOutWidth
            })
            .style('opacity', 0.0)
            .remove();
    }

    function createDeviceNode(device) {
        // start with the object as is
        var node = device,
            type = device.type,
            svgCls = type ? 'node device ' + type : 'node device';

        // Augment as needed...
        node.class = 'device';
        node.svgClass = device.online ? svgCls + ' online' : svgCls;
        positionNode(node);

        // cache label array length
        network.deviceLabelCount = device.labels.length;
        return node;
    }

    function createHostNode(host) {
        // start with the object as is
        var node = host;

        // Augment as needed...
        node.class = 'host';
        if (!node.type) {
            node.type = 'endstation';
        }
        node.svgClass = 'node host ' + node.type;
        positionNode(node);

        // cache label array length
        network.hostLabelCount = host.labels.length;
        return node;
    }

    function positionNode(node) {
        var meta = node.metaUi,
            x = meta && meta.x,
            y = meta && meta.y,
            xy;

        // If we have [x,y] already, use that...
        if (x && y) {
            node.fixed = true;
            node.x = x;
            node.y = y;
            return;
        }

        var location = node.location;
        if (location && location.type === 'latlng') {
            var coord = geoMapProjection([location.lng, location.lat]);
            node.fixed = true;
            node.x = coord[0];
            node.y = coord[1];
            return;
        }

        // Note: Placing incoming unpinned nodes at exactly the same point
        //        (center of the view) causes them to explode outwards when
        //        the force layout kicks in. So, we spread them out a bit
        //        initially, to provide a more serene layout convergence.
        //       Additionally, if the node is a host, we place it near
        //        the device it is connected to.

        function spread(s) {
            return Math.floor((Math.random() * s) - s/2);
        }

        function randDim(dim) {
            return dim / 2 + spread(dim * 0.7071);
        }

        function rand() {
            return {
                x: randDim(network.view.width()),
                y: randDim(network.view.height())
            };
        }

        function near(node) {
            var min = 12,
                dx = spread(12),
                dy = spread(12);
            return {
                x: node.x + min + dx,
                y: node.y + min + dy
            };
        }

        function getDevice(cp) {
            var d = network.lookup[cp.device];
            return d || rand();
        }

        xy = (node.class === 'host') ? near(getDevice(node.cp)) : rand();
        $.extend(node, xy);
    }

    function iconUrl(d) {
        return 'img/' + d.type + '.png';
    }

    // returns the newly computed bounding box of the rectangle
    function adjustRectToFitText(n) {
        var text = n.select('text'),
            box = text.node().getBBox(),
            lab = config.labels;

        text.attr('text-anchor', 'middle')
            .attr('y', '-0.8em')
            .attr('x', lab.imgPad/2);

        // translate the bbox so that it is centered on [x,y]
        box.x = -box.width / 2;
        box.y = -box.height / 2;

        // add padding
        box.x -= (lab.padLR + lab.imgPad/2);
        box.width += lab.padLR * 2 + lab.imgPad;
        box.y -= lab.padTB;
        box.height += lab.padTB * 2;

        return box;
    }

    function mkSvgClass(d) {
        return d.fixed ? d.svgClass + ' fixed' : d.svgClass;
    }

    function hostLabel(d) {
        var idx = (hostLabelIndex < d.labels.length) ? hostLabelIndex : 0;
        return d.labels[idx];
    }
    function deviceLabel(d) {
        var idx = (deviceLabelIndex < d.labels.length) ? deviceLabelIndex : 0;
        return d.labels[idx];
    }
    function niceLabel(label) {
        return (label && label.trim()) ? label : '.';
    }

    function updateDeviceLabel(d) {
        var label = niceLabel(deviceLabel(d)),
            node = d.el,
            box;

        node.select('text')
            .text(label)
            .style('opacity', 0)
            .transition()
            .style('opacity', 1);

        box = adjustRectToFitText(node);

        node.select('rect')
            .transition()
            .attr(box);

        node.select('image')
            .transition()
            .attr('x', box.x + config.icons.xoff)
            .attr('y', box.y + config.icons.yoff);
    }

    function updateHostLabel(d) {
        var label = hostLabel(d),
            host = d.el;

        host.select('text').text(label);
    }

    function updateDeviceState(nodeData) {
        nodeData.el.classed('online', nodeData.online);
        updateDeviceLabel(nodeData);
        // TODO: review what else might need to be updated
    }

    function updateLinkState(linkData) {
        updateLinkWidth(linkData);
        linkData.el.classed('inactive', !linkData.online);
        // TODO: review what else might need to be updated
        //  update label, if showing
    }

    function updateHostState(hostData) {
        updateHostLabel(hostData);
        // TODO: review what else might need to be updated
    }

    function nodeMouseOver(d) {
        hovered = d;
        if (trafficHover() && d.class === 'host') {
            showTrafficAction();
        }
    }

    function nodeMouseOut(d) {
        hovered = null;
        if (trafficHover() && d.class === 'host') {
            showTrafficAction();
        }
    }

    function addHostIcon(node, radius, iconId) {
        var dim = radius * 1.5,
            xlate = -dim / 2;

        node.append('use')
            .classed('glyph', true)
            .attr('transform', translate(xlate,xlate))
            .attr('xlink:href', '#' + iconId)
            .attr('width', dim)
            .attr('height', dim);
    }

    function updateNodes() {
        node = nodeG.selectAll('.node')
            .data(network.nodes, function (d) { return d.id; });

        // operate on existing nodes, if necessary
        //  update host labels
        //node .foo() .bar() ...

        // operate on entering nodes:
        var entering = node.enter()
            .append('g')
            .attr({
                id: function (d) { return safeId(d.id); },
                class: mkSvgClass,
                transform: function (d) { return translate(d.x, d.y); },
                opacity: 0
            })
            .call(network.drag)
            .on('mouseover', nodeMouseOver)
            .on('mouseout', nodeMouseOut)
            .transition()
            .attr('opacity', 1);

        // augment device nodes...
        entering.filter('.device').each(function (d) {
            var node = d3.select(this),
                icon = iconUrl(d),
                label = niceLabel(deviceLabel(d)),
                box;

            // provide ref to element from backing data....
            d.el = node;

            node.append('rect')
                .attr({
                    'rx': 5,
                    'ry': 5
                });

            node.append('text')
                .text(label)
                .attr('dy', '1.1em');

            box = adjustRectToFitText(node);

            node.select('rect')
                .attr(box);

            if (icon) {
                var cfg = config.icons;
                node.append('svg:image')
                    .attr({
                        x: box.x + config.icons.xoff,
                        y: box.y + config.icons.yoff,
                        width: cfg.w,
                        height: cfg.h,
                        'xlink:href': icon
                    });
            }

            // debug function to show the modelled x,y coordinates of nodes...
            if (debug('showNodeXY')) {
                node.select('rect').attr('fill-opacity', 0.5);
                node.append('circle')
                    .attr({
                        class: 'debug',
                        cx: 0,
                        cy: 0,
                        r: '3px'
                    });
            }
        });

        // TODO: better place for this configuration state
        var defaultHostRadius = 9,
            hostRadius = {
                bgpSpeaker: 20
            },
            hostIcon = {
                bgpSpeaker: 'bullhorn'
            };


        // augment host nodes...
        entering.filter('.host').each(function (d) {
            var node = d3.select(this),
                r = hostRadius[d.type] || defaultHostRadius,
                textDy = r + 10,
                icon = hostIcon[d.type];

            // provide ref to element from backing data....
            d.el = node;

            node.append('circle')
                .attr('r', r);

            if (icon) {
                addHostIcon(node, r, icon);
            }

            node.append('text')
                .text(hostLabel)
                .attr('dy', textDy)
                .attr('text-anchor', 'middle');

            // debug function to show the modelled x,y coordinates of nodes...
            if (debug('showNodeXY')) {
                node.select('circle').attr('fill-opacity', 0.5);
                node.append('circle')
                    .attr({
                        class: 'debug',
                        cx: 0,
                        cy: 0,
                        r: '3px'
                    });
            }
        });

        // operate on both existing and new nodes, if necessary
        //node .foo() .bar() ...

        // operate on exiting nodes:
        // Note that the node is removed after 2 seconds.
        // Sub element animations should be shorter than 2 seconds.
        var exiting = node.exit()
            .transition()
            .duration(2000)
            .style('opacity', 0)
            .remove();

        // host node exits....
        exiting.filter('.host').each(function (d) {
            var node = d3.select(this);

            node.select('text')
                .style('opacity', 0.5)
                .transition()
                .duration(1000)
                .style('opacity', 0);
            // note, leave <g>.remove to remove this element

            node.select('circle')
                .style('stroke-fill', '#555')
                .style('fill', '#888')
                .style('opacity', 0.5)
                .transition()
                .duration(1500)
                .attr('r', 0);
            // note, leave <g>.remove to remove this element

        });

        // TODO: device node exits
    }

    function find(key, array) {
        for (var idx = 0, n = array.length; idx < n; idx++) {
            if (array[idx].key === key) {
                return idx;
            }
        }
        return -1;
    }

    function removeLinkElement(linkData) {
        var idx = find(linkData.key, network.links),
            removed;
        if (idx >=0) {
            // remove from links array
            removed = network.links.splice(idx, 1);
            // remove from lookup cache
            delete network.lookup[removed[0].key];
            updateLinks();
            network.force.resume();
        }
    }

    function removeHostElement(hostData) {
        // first, remove associated hostLink...
        removeLinkElement(hostData.linkData);

        // remove from lookup cache
        delete network.lookup[hostData.id];
        // remove from nodes array
        var idx = find(hostData.id, network.nodes);
        network.nodes.splice(idx, 1);
        // remove from SVG
        updateNodes();
        network.force.resume();
    }


    function tick() {
        node.attr({
            transform: function (d) { return translate(d.x, d.y); }
        });

        link.attr({
            x1: function (d) { return d.source.x; },
            y1: function (d) { return d.source.y; },
            x2: function (d) { return d.target.x; },
            y2: function (d) { return d.target.y; }
        });
    }

    // ==============================
    // Web-Socket for live data

    function webSockUrl() {
        return document.location.toString()
            .replace(/\#.*/, '')
            .replace('http://', 'ws://')
            .replace('https://', 'wss://')
            .replace('index2.html', config.webSockUrl);
    }

    webSock = {
        ws : null,

        connect : function() {
            webSock.ws = new WebSocket(webSockUrl());

            webSock.ws.onopen = function() {
                noWebSock(false);
            };

            webSock.ws.onmessage = function(m) {
                if (m.data) {
                    wsTraceRx(m.data);
                    handleServerEvent(JSON.parse(m.data));
                }
            };

            webSock.ws.onclose = function(m) {
                webSock.ws = null;
                noWebSock(true);
            };
        },

        send : function(text) {
            if (text != null) {
                webSock._send(text);
            }
        },

        _send : function(message) {
            if (webSock.ws) {
                webSock.ws.send(message);
            } else if (config.useLiveData) {
                network.view.alert('no web socket open\n\n' + message);
            } else {
                console.log('WS Send: ' + JSON.stringify(message));
            }
        }

    };

    function noWebSock(b) {
        mask.style('display',b ? 'block' : 'none');
    }

    // TODO: use cache of pending messages (key = sid) to reconcile responses

    function sendMessage(evType, payload) {
        var toSend = {
                event: evType,
                sid: ++sid,
                payload: payload
            },
            asText = JSON.stringify(toSend);
        wsTraceTx(asText);
        webSock.send(asText);
    }

    function wsTraceTx(msg) {
        wsTrace('tx', msg);
    }
    function wsTraceRx(msg) {
        wsTrace('rx', msg);
    }
    function wsTrace(rxtx, msg) {
        console.log('[' + rxtx + '] ' + msg);
        // TODO: integrate with trace view
        //if (trace) {
        //    trace.output(rxtx, msg);
        //}
    }


    // ==============================
    // Selection stuff

    function selectObject(obj, el) {
        var n,
            srcEv = d3.event.sourceEvent,
            meta = srcEv.metaKey,
            shift = srcEv.shiftKey;

        if ((panZoom() && !meta) || (!panZoom() && meta)) {
            return;
        }

        if (el) {
            n = d3.select(el);
        } else {
            node.each(function(d) {
                if (d == obj) {
                    n = d3.select(el = this);
                }
            });
        }
        if (!n) return;

        if (shift && n.classed('selected')) {
            deselectObject(obj.id);
            updateDetailPane();
            return;
        }

        if (!shift) {
            deselectAll();
        }

        selections[obj.id] = { obj: obj, el: el };
        selectOrder.push(obj.id);

        n.classed('selected', true);
        updateDetailPane();
    }

    function deselectObject(id) {
        var obj = selections[id],
            idx;
        if (obj) {
            d3.select(obj.el).classed('selected', false);
            delete selections[id];
            idx = $.inArray(id, selectOrder);
            if (idx >= 0) {
                selectOrder.splice(idx, 1);
            }
        }
    }

    function deselectAll() {
        // deselect all nodes in the network...
        node.classed('selected', false);
        selections = {};
        selectOrder = [];
        updateDetailPane();
    }

    // update the state of the detail pane, based on current selections
    function updateDetailPane() {
        var nSel = selectOrder.length;
        if (!nSel) {
            detailPane.hide();
            showTrafficAction();        // sends cancelTraffic event
        } else if (nSel === 1) {
            singleSelect();
        } else {
            multiSelect();
        }
    }

    function singleSelect() {
        requestDetails();
        // NOTE: detail pane will be shown from showDetails event callback
    }

    function multiSelect() {
        populateMultiSelect();
    }

    function addSep(tbody) {
        var tr = tbody.append('tr');
        $('<hr>').appendTo(tr.append('td').attr('colspan', 2));
    }

    function addProp(tbody, label, value) {
        var tr = tbody.append('tr');

        tr.append('td')
            .attr('class', 'label')
            .text(label + ' :');

        tr.append('td')
            .attr('class', 'value')
            .text(value);
    }

    function populateMultiSelect() {
        detailPane.empty();

        var title = detailPane.append("h2"),
            table = detailPane.append("table"),
            tbody = table.append("tbody");

        title.text('Multi-Select...');

        selectOrder.forEach(function (d, i) {
            addProp(tbody, i+1, d);
        });

        addMultiSelectActions();
    }

    function populateDetails(data) {
        detailPane.empty();

        var title = detailPane.append("h2"),
            table = detailPane.append("table"),
            tbody = table.append("tbody");

        $('<img src="img/' + data.type + '.png">').appendTo(title);
        $('<span>').attr('class', 'icon').text(data.id).appendTo(title);

        data.propOrder.forEach(function(p) {
            if (p === '-') {
                addSep(tbody);
            } else {
                addProp(tbody, p, data.props[p]);
            }
        });

        addSingleSelectActions();
    }

    function addSingleSelectActions() {
        detailPane.append('hr');
        // always want to allow 'show traffic'
        addAction(detailPane, 'Show Traffic', showTrafficAction);
    }

    function addMultiSelectActions() {
        detailPane.append('hr');
        // always want to allow 'show traffic'
        addAction(detailPane, 'Show Traffic', showTrafficAction);
        // if exactly two hosts are selected, also want 'add host intent'
        if (nSel() === 2 && allSelectionsClass('host')) {
            addAction(detailPane, 'Add Host Intent', addIntentAction);
        }
    }

    function addAction(panel, text, cb) {
        panel.append('div')
            .classed('actionBtn', true)
            .text(text)
            .on('click', cb);
    }


    function zoomPan(scale, translate) {
        zoomPanContainer.attr("transform", "translate(" + translate + ")scale(" + scale + ")");
        // keep the map lines constant width while zooming
        bgImg.style("stroke-width", 2.0 / scale + "px");
    }

    function resetZoomPan() {
        zoomPan(1, [0,0]);
        zoom.scale(1).translate([0,0]);
    }

    function setupZoomPan() {
        function zoomed() {
            if (!panZoom() ^ !d3.event.sourceEvent.metaKey) {
                zoomPan(d3.event.scale, d3.event.translate);
            }
        }

        zoom = d3.behavior.zoom()
            .translate([0, 0])
            .scale(1)
            .scaleExtent([1, 8])
            .on("zoom", zoomed);

        svg.call(zoom);
    }

    // ==============================
    // Test harness code

    function prepareScenario(view, ctx, dbg) {
        var sc = scenario,
            urlSc = sc.evDir + ctx + sc.evScenario;

        if (!ctx) {
            view.alert("No scenario specified (null ctx)");
            return;
        }

        sc.view = view;
        sc.ctx = ctx;
        sc.debug = dbg;
        sc.evNumber = 0;

        d3.json(urlSc, function(err, data) {
            var p = data && data.params || {},
                desc = data && data.description || null,
                intro = data && data.title;

            if (err) {
                view.alert('No scenario found:\n\n' + urlSc + '\n\n' + err);
            } else {
                sc.params = p;
                if (desc) {
                    intro += '\n\n  ' + desc.join('\n  ');
                }
                view.alert(intro);
            }
        });

    }

    // ==============================
    // Toggle Buttons in masthead

    // TODO: toggle button (and other widgets in the masthead) should be provided
    //  by the framework; not generated by the view.

    var showInstances,
        doPanZoom,
        showTrafficOnHover;

    function addButtonBar(view) {
        var bb = d3.select('#mast')
            .append('span').classed('right', true).attr('id', 'bb');

        function mkTogBtn(text, cb) {
            return bb.append('span')
                .classed('btn', true)
                .text(text)
                .on('click', cb);
        }

        showInstances = mkTogBtn('Show Instances', toggleInst);
        doPanZoom = mkTogBtn('Pan/Zoom', togglePanZoom);
        showTrafficOnHover = mkTogBtn('Show traffic on hover', toggleTrafficHover);
    }

    function instShown() {
        return showInstances.classed('active');
    }
    function toggleInst() {
        showInstances.classed('active', !instShown());
        if (instShown()) {
            oiBox.show();
        } else {
            oiBox.hide();
        }
    }

    function panZoom() {
        return doPanZoom.classed('active');
    }
    function togglePanZoom() {
        doPanZoom.classed('active', !panZoom());
    }

    function trafficHover() {
        return showTrafficOnHover.classed('active');
    }
    function toggleTrafficHover() {
        showTrafficOnHover.classed('active', !trafficHover());
    }

    function loadGlyphs(svg) {
        var defs = svg.append('defs');
        gly.defBird(defs);
        gly.defBullhorn(defs);
    }

    // ==============================
    // View life-cycle callbacks

    function preload(view, ctx, flags) {
        var w = view.width(),
            h = view.height(),
            fcfg = config.force,
            fpad = fcfg.pad,
            forceDim = [w - 2*fpad, h - 2*fpad];

        // NOTE: view.$div is a D3 selection of the view's div
        var viewBox = '0 0 ' + config.logicalSize + ' ' + config.logicalSize;
        svg = view.$div.append('svg').attr('viewBox', viewBox);
        setSize(svg, view);

        loadGlyphs(svg);

        zoomPanContainer = svg.append('g').attr('id', 'zoomPanContainer');
        setupZoomPan();

        // add blue glow filter to svg layer
        d3u.appendGlow(zoomPanContainer);

        // group for the topology
        topoG = zoomPanContainer.append('g')
            .attr('id', 'topo-G')
            .attr('transform', fcfg.translate());

        // subgroups for links and nodes
        linkG = topoG.append('g').attr('id', 'links');
        nodeG = topoG.append('g').attr('id', 'nodes');

        // selection of nodes and links
        link = linkG.selectAll('.link');
        node = nodeG.selectAll('.node');

        function chrg(d) {
            return fcfg.charge[d.class] || -12000;
        }
        function ldist(d) {
            return fcfg.linkDistance[d.type] || 50;
        }
        function lstrg(d) {
            // 0.0 - 1.0
            return fcfg.linkStrength[d.type] || 1.0;
        }

        function selectCb(d, self) {
            selectObject(d, self);
        }

        function atDragEnd(d, self) {
            // once we've finished moving, pin the node in position
            d.fixed = true;
            d3.select(self).classed('fixed', true);
            if (config.useLiveData) {
                sendUpdateMeta(d);
            } else {
                console.log('Moving node ' + d.id + ' to [' + d.x + ',' + d.y + ']');
            }
        }

        function sendUpdateMeta(d) {
            sendMessage('updateMeta', {
                id: d.id,
                'class': d.class,
                'memento': {
                    x: d.x,
                    y: d.y
                }
            });
        }

        // set up the force layout
        network.force = d3.layout.force()
            .size(forceDim)
            .nodes(network.nodes)
            .links(network.links)
            .gravity(0.4)
            .friction(0.7)
            .charge(chrg)
            .linkDistance(ldist)
            .linkStrength(lstrg)
            .on('tick', tick);

        network.drag = d3u.createDragBehavior(network.force,
            selectCb, atDragEnd, panZoom);

        // create mask layer for when we lose connection to server.
        // TODO: this should be part of the framework
        mask = view.$div.append('div').attr('id','topo-mask');
        para(mask, 'Oops!');
        para(mask, 'Web-socket connection to server closed...');
        para(mask, 'Try refreshing the page.');

        mask.append('svg')
            .attr({
                id: 'mask-bird',
                width: w,
                height: h
            })
            .append('g')
            .attr('transform', birdTranslate(w, h))
            .style('opacity', 0.3)
            .append('use')
                .attr({
                    'xlink:href': '#bird',
                    width: config.birdDim,
                    height: config.birdDim,
                    fill: '#111'
                })
    }

    function para(sel, text) {
        sel.append('p').text(text);
    }


    function load(view, ctx, flags) {
        // resize, in case the window was resized while we were not loaded
        resize(view, ctx, flags);

        // cache the view token, so network topo functions can access it
        network.view = view;
        config.useLiveData = !flags.local;

        if (!config.useLiveData) {
            prepareScenario(view, ctx, flags.debug);
        }

        // set our radio buttons and key bindings
        layerBtnSet = view.setRadio(layerButtons);
        view.setKeys(keyDispatch);

        // patch in our "button bar" for now
        // TODO: implement a more official frameworky way of doing this..
        addButtonBar(view);

        // Load map data asynchronously; complete startup after that..
        loadGeoJsonData();

        // start the and timer
        var dashIdx = 0;
        antTimer = setInterval(function () {
            // TODO: figure out how to choose Src-->Dst and Dst-->Src, per link
            dashIdx = dashIdx === 0 ? 14 : dashIdx - 2;
            d3.selectAll('.animated').style('stroke-dashoffset', dashIdx);
        }, 35);
    }

    function unload(view, ctx, flags) {
        if (antTimer) {
            clearInterval(antTimer);
            antTimer = null;
        }
    }

    // TODO: move these to config/state portion of script
    var geoJsonUrl = 'json/map/continental_us.json',     // TODO: Paul
        geoJson;

    function loadGeoJsonData() {
        d3.json(geoJsonUrl, function (err, data) {
            if (err) {
                // fall back to USA map background
                loadStaticMap();
            } else {
                geoJson = data;
                loadGeoMap();
            }

            // finally, connect to the server...
            if (config.useLiveData) {
                webSock.connect();
            }
        });
    }

    function showBg() {
        return config.options.showBackground ? 'visible' : 'hidden';
    }

    function loadStaticMap() {
        fnTrace('loadStaticMap', config.backgroundUrl);
        var w = network.view.width(),
            h = network.view.height();

        // load the background image
        bgImg = svg.insert('svg:image', '#topo-G')
            .attr({
                id: 'topo-bg',
                width: w,
                height: h,
                'xlink:href': config.backgroundUrl
            })
            .style({
                visibility: showBg()
            });
    }

    function loadGeoMap() {
        fnTrace('loadGeoMap', geoJsonUrl);

        // extracts the topojson data into geocoordinate-based geometry
        var topoData = topojson.feature(geoJson, geoJson.objects.states);

        // see: http://bl.ocks.org/mbostock/4707858
        geoMapProjection = d3.geo.mercator();
        var path = d3.geo.path().projection(geoMapProjection);

        geoMapProjection
            .scale(1)
            .translate([0, 0]);

        // [[x1,y1],[x2,y2]]
        var b = path.bounds(topoData);
        // size map to 95% of minimum dimension to fill space
        var s = .95 / Math.min((b[1][0] - b[0][0]) / config.logicalSize, (b[1][1] - b[0][1]) / config.logicalSize);
        var t = [(config.logicalSize - s * (b[1][0] + b[0][0])) / 2, (config.logicalSize - s * (b[1][1] + b[0][1])) / 2];

        geoMapProjection
            .scale(s)
            .translate(t);

        bgImg = zoomPanContainer.insert("g", '#topo-G');
        bgImg.attr('id', 'map').selectAll('path')
            .data(topoData.features)
            .enter()
            .append('path')
            .attr('d', path);
    }

    function resize(view, ctx, flags) {
        var w = view.width(),
            h = view.height();

        setSize(svg, view);

        d3.select('#mask-bird').attr({ width: w, height: h})
            .select('g').attr('transform', birdTranslate(w, h));
    }

    function birdTranslate(w, h) {
        var bdim = config.birdDim;
        return 'translate('+((w-bdim)*.4)+','+((h-bdim)*.1)+')';
    }

    // ==============================
    // View registration

    onos.ui.addView('topo', {
        preload: preload,
        load: load,
        unload: unload,
        resize: resize
    });

    detailPane = onos.ui.addFloatingPanel('topo-detail');
    oiBox = onos.ui.addFloatingPanel('topo-oibox', 'TL');

}(ONOS));
