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

/*
 ONOS GUI -- Topology View Module
 */

(function () {
    'use strict';

    var moduleDependencies = [
        'ngCookies',
        'onosUtil',
        'onosSvg',
        'onosRemote',
    ];

    // references to injected services
    var $scope, $log, $loc, $timeout,
        fs, ks, zs, gs, ms, sus, flash, wss, ps, th, tds, t3s, tes, tfs, tps,
        tis, tms, tss, tls, tos, fltr, ttbs, tspr, tov;

    // DOM elements
    var ovtopo, svg, defs, zoomLayer, mapG, spriteG, forceG, noDevsLayer;

    // Internal state
    var zoomer,
        actionMap,
        topoLion = function (x) { return '#' + x + '#'; }; // func replaced later

    // --- Short Cut Keys ------------------------------------------------

    function setUpKeys(overlayKeys) {
        // key bindings need to be made after the services have been injected
        // thus, deferred to here...

        // we need functions that can be invoked after LION bundle loaded
        function togInst() { return topoLion('tbtt_tog_instances'); }
        function togSumm() { return topoLion('tbtt_tog_summary'); }
        function togUseDet() { return topoLion('tbtt_tog_use_detail'); }

        function togHost() { return topoLion('tbtt_tog_host'); }
        function togOff() { return topoLion('tbtt_tog_offline'); }
        function togPortHi() { return topoLion('tbtt_tog_porthi'); }

        function showBad() { return topoLion('tbtt_bad_links'); }
        function togMap() { return topoLion('tbtt_tog_map'); }
        function selMap() { return topoLion('tbtt_sel_map'); }
        function togSpr() { return topoLion('tbtt_tog_sprite'); }

        function rstLoc() { return topoLion('tbtt_reset_loc'); }
        function togOb() { return topoLion('tbtt_tog_oblique'); }
        function cycLayer() { return topoLion('tbtt_cyc_layers'); }
        function cycDev() { return topoLion('tbtt_cyc_dev_labs'); }
        function cycHost() { return topoLion('tbtt_cyc_host_labs'); }

        function unpin() { return topoLion('tbtt_unpin_node'); }
        function rzoom() { return topoLion('tbtt_reset_zoom'); }
        function togtb() { return topoLion('tbtt_tog_toolbar'); }
        function eqmaster() { return topoLion('tbtt_eq_master'); }

        function uiClick() { return topoLion('click'); }
        function uiShClick() { return topoLion('shift_click'); }
        function uiDrag() { return topoLion('drag'); }
        function uiCmdScr() { return topoLion('cmd_scroll'); }
        function uiCmdDrag() { return topoLion('cmd_drag'); }

        function uiClickTxt() { return topoLion('qh_gest_click'); }
        function uiShClickTxt() { return topoLion('qh_gest_shift_click'); }
        function uiDragTxt() { return topoLion('qh_gest_drag'); }
        function uiCmdScrTxt() { return topoLion('qh_gest_cmd_scroll'); }
        function uiCmdDragTxt() { return topoLion('qh_gest_cmd_drag'); }

        actionMap = {
            I: [toggleInstances, togInst],
            O: [toggleSummary, togSumm],
            D: [toggleUseDetailsFlag, togUseDet],

            H: [toggleHosts, togHost],
            M: [toggleOffline, togOff],
            P: [togglePorts, togPortHi],

            dash: [tfs.showBadLinks, showBad],
            B: [toggleMap, togMap],
            G: [openMapSelection, selMap],
            S: [toggleSprites, togSpr],

            X: [tfs.resetAllLocations, rstLoc],
            Z: [tos.toggleOblique, togOb],
            N: [fltr.clickAction, cycLayer],
            L: [tfs.cycleDeviceLabels, cycDev],
            'shift-L': [tfs.cycleHostLabels, cycHost],

            U: [tfs.unpin, unpin],
            R: [resetZoom, rzoom],
            dot: [ttbs.toggleToolbar, togtb],
            E: [equalizeMasters, eqmaster],

            // -- instance color palette debug
            // 9: function () { sus.cat7().testCard(svg); },

            // topology overlay selections
            F1: function () { ttbs.fnkey(0); },
            F2: function () { ttbs.fnkey(1); },
            F3: function () { ttbs.fnkey(2); },
            F4: function () { ttbs.fnkey(3); },
            F5: function () { ttbs.fnkey(4); },

            esc: handleEscape,

            _keyListener: ttbs.keyListener,

            _helpFormat: [
                ['I', 'O', 'D', 'H', 'M', 'P', 'dash', 'B', 'G', 'S'],
                ['X', 'Z', 'N', 'L', 'shift-L', 'U', 'R', '-', 'E', '-', 'dot'],
                [], // this column reserved for overlay actions
            ],
        };

        if (fs.isO(overlayKeys)) {
            mergeKeys(overlayKeys);
        }

        ks.keyBindings(actionMap);

        ks.gestureNotes([
            [uiClick, uiClickTxt],
            [uiShClick, uiShClickTxt],
            [uiDrag, uiDragTxt],
            [uiCmdScr, uiCmdScrTxt],
            [uiCmdDrag, uiCmdDragTxt],
        ]);
    }

    // when a topology overlay is activated, we need to bind their keystrokes
    // and include them in the quick-help panel
    function mergeKeys(extra) {
        var _hf = actionMap._helpFormat[2];

        ks.checkNotGlobal(extra);

        extra._keyOrder.forEach(function (k) {
            var d = extra[k],
                cb = d && d.cb,
                tt = d && d.tt;
            // NOTE: ignore keys that are already defined
            if (d && !actionMap[k]) {
                actionMap[k] = [cb, tt];
                _hf.push(k);
            }
        });
    }

    // --- Keystroke functions -------------------------------------------

    function toggleInstances(x) {
        updatePrefsState('insts', tis.toggle(x));
        tfs.updateDeviceColors();
    }

    function toggleSummary(x) {
        updatePrefsState('summary', tps.toggleSummary(x));
    }

    function toggleUseDetailsFlag(x) {
        updatePrefsState('detail', tps.toggleUseDetailsFlag(x));
    }

    function toggleHosts(x) {
        updatePrefsState('hosts', tfs.toggleHosts(x));
    }

    function toggleOffline(x) {
        updatePrefsState('offdev', tfs.toggleOffline(x));
    }

    function togglePorts(x) {
        updatePrefsState('porthl', tfs.togglePorts(x));
    }

    function _togSvgLayer(x, G, tag, what) {
        var on = (x === 'keyev') ? !sus.visible(G) : !!x,
            verb = on ? topoLion('show') : topoLion('hide');
        sus.visible(G, on);
        updatePrefsState(tag, on);
        flash.flash(verb + ' ' + what);
    }

    function toggleMap(x) {
        _togSvgLayer(x, mapG, 'bg', topoLion('fl_background_map'));
    }

    function openMapSelection() {
        tms.openMapSelection();
    }

    function toggleSprites(x) {
        _togSvgLayer(x, spriteG, 'spr', topoLion('fl_sprite_layer'));
    }

    function resetZoom() {
        zoomer.reset();
        flash.flash(topoLion('fl_pan_zoom_reset'));
    }

    function equalizeMasters() {
        wss.sendEvent('equalizeMasters');
        flash.flash(topoLion('fl_eq_masters'));
    }

    function handleEscape() {
        if (tis.showMaster()) {
            // if an instance is selected, cancel the affinity mapping
            tis.cancelAffinity();

        } else if (tov.hooks.escape()) {
            // else if the overlay consumed the ESC event...
            // (work already done)

        } else if (tss.deselectAll()) {
            // else if we have node selections, deselect them all
            // (work already done)

        } else if (tls.deselectAllLinks()) {
            // else if we have a link selected, deselect it
            // (work already done)

        } else if (tis.isVisible()) {
            // else if the Instance Panel is visible, hide it
            tis.hide();
            tfs.updateDeviceColors();

        } else if (tps.summaryVisible()) {
            // else if the Summary Panel is visible, hide it
            tps.hideSummary();
        }
    }

    // --- Toolbar Functions ---------------------------------------------

    function notValid(what) {
        $log.warn('topo.js getActionEntry(): Not a valid ' + what);
    }

    function getActionEntry(key) {
        var entry;

        if (!key) {
            notValid('key');
            return null;
        }

        entry = actionMap[key];

        if (!entry) {
            notValid('actionMap entry');
            return null;
        }
        return fs.isA(entry) || [entry, ''];
    }

    function setUpToolbar() {
        ttbs.init({
            getActionEntry: getActionEntry,
            setUpKeys: setUpKeys,
        });
        ttbs.createToolbar();
    }

    // --- Glyphs, Icons, and the like -----------------------------------

    function setUpDefs() {
        defs = svg.append('defs');
        gs.loadDefs(defs);
        sus.loadGlowDefs(defs);
    }


    // --- Pan and Zoom --------------------------------------------------

    // zoom enabled predicate. ev is a D3 source event.
    function zoomEnabled(ev) {
        return fs.isMobile() || (ev.metaKey || ev.altKey);
    }

    function zoomCallback() {
        var sc = zoomer.scale(),
            tr = zoomer.translate();

        ps.setPrefs('topo_zoom', { tx: tr[0], ty: tr[1], sc: sc });

        // keep the map lines constant width while zooming
        mapG.style('stroke-width', (2.0 / sc) + 'px');

        tfs.setNodeScale(sc);
    }

    function setUpZoom() {
        zoomLayer = svg.append('g').attr('id', 'topo-zoomlayer');
        zoomer = zs.createZoomer({
            svg: svg,
            zoomLayer: zoomLayer,
            zoomEnabled: zoomEnabled,
            zoomCallback: zoomCallback,
        });
    }


    // callback invoked when the SVG view has been resized..
    function svgResized(s) {
        tfs.newDim([s.width, s.height]);
    }

    // --- Background Map ------------------------------------------------

    function recenterLabel(g) {
        var box = g.node().getBBox();

        box.x -= box.width/2;
        box.y -= box.height/2;
        g.attr('transform', sus.translate(box.x, box.y));
    }

    function setUpNoDevs() {
        var g;

        noDevsLayer = svg.append('g').attr({
            id: 'topo-noDevsLayer',
            transform: sus.translate(500, 500),
        });
        // Note, SVG viewbox is '0 0 1000 1000', defined in topo.html.
        // We are translating this layer to have its origin at the center

        g = noDevsLayer.append('g');
        gs.addGlyph(g, 'bird', 100).attr('class', 'noDevsBird');
        g.append('text').text('').attr({ x: 120, y: 80 });
        recenterLabel(g);
        showNoDevs(true);
    }

    function lionNoDevs() {
        var g = d3.select('#topo-noDevsLayer g');

        g.select('text').text(topoLion('no_devices_are_connected'));
        recenterLabel(g);
    }

    function showNoDevs(b) {
        sus.visible(noDevsLayer, b);
    }


    var countryFilters = {
        s_america: function (c) {
            return c.properties.continent === 'South America';
        },

        ns_america: function (c) {
            return c.properties.custom === 'US-cont' ||
                c.properties.subregion === 'Central America' ||
                c.properties.continent === 'South America';
        },

        japan: function (c) {
            return c.properties.geounit === 'Japan';
        },

        europe: function (c) {
            return c.properties.continent === 'Europe';
        },

        italy: function (c) {
            return c.properties.geounit === 'Italy';
        },

        uk: function (c) {
            // technically, Ireland is not part of the United Kingdom,
            // but the map looks weird without it showing.
            return c.properties.adm0_a3 === 'GBR' ||
                c.properties.adm0_a3 === 'IRL';
        },

        s_korea: function (c) {
            return c.properties.adm0_a3 === 'KOR';
        },

        australia: function (c) {
            return c.properties.adm0_a3 === 'AUS';
        },
    };

    var tintOn = 0,
        shadeFlip = 0,
        shadePalette = {
        light: {
            sea: 'aliceblue',
            land: 'white',
            outline: '#ddd',
        },
        dark: {
            sea: '#001830',
            land: '#232331',
            outline: '#3a3a3a',
        },
    };

    function shading() {
        return tintOn ? {
            palette: shadePalette[th.theme()],
            flip: shadeFlip,
        } : '';
    }

    function setMap(map) {
        ps.setPrefs('topo_mapid', map);
        setUpMap();
        opacifyMap(true);
    }

    function currentMap() {
        return ps.getPrefs(
            'topo_mapid',
            {
                mapid: 'usa',
                mapscale: 1,
                mapfilepath: '*continental_us',
                tint: 'off',
            },
            $loc.search()
        );
    }

    function setUpMap() {
        var prefs = currentMap(),
            mapId = prefs.mapid,
            mapFilePath = prefs.mapfilepath,
            mapScale = prefs.mapscale,
            tint = prefs.tint,
            promise,
            cfilter;

        tintOn = tint === 'on' ? 1 : 0;

        $log.debug('setUpMap() mapId:', mapId, ', mapScale:', mapScale,
                   ', tint:', tint);

        mapG = d3.select('#topo-map');
        if (mapG.empty()) {
            mapG = zoomLayer.append('g').attr('id', 'topo-map');
        } else {
            mapG.each(function (d, i) {
                d3.selectAll(this.childNodes).remove();
            });
        }

        if (mapFilePath === '*countries') {

            cfilter = countryFilters[mapId] || countryFilters.uk;

            promise = ms.loadMapRegionInto(mapG, {
                countryFilter: cfilter,
                adjustScale: mapScale,
                shading: shading(),
            });
        } else {

            promise = ms.loadMapInto(mapG, mapFilePath, mapId, {
                adjustScale: mapScale,
                shading: shading(),
            });
        }

        ps.setPrefs('topo_mapid', prefs);
        return promise;
    }

    function mapReshader() {
        $log.debug('... Re-shading map ...');
        ms.reshade(shading());
    }

    // set up theme listener to re-shade the map when required.
    function mapShader(on) {
        if (on) {
            th.addListener(mapReshader);
        } else {
            th.removeListener(mapReshader);
        }
    }

    function opacifyMap(b) {
        mapG.transition()
            .duration(1000)
            .attr('opacity', b ? 1 : 0);
    }

    function setUpSprites() {
        var prefs = ps.getPrefs('topo_sprites', { sprites: '' }, $loc.search()),
            sprId = prefs.sprites;

        spriteG = zoomLayer.append('g').attr('id', 'topo-sprites');
        if (sprId) {
            ps.setPrefs('topo_sprites', prefs);
            tspr.loadSprites(spriteG, defs, sprId);
        }
    }

    // --- User Preferemces ----------------------------------------------

    var prefsState = {};

    function updatePrefsState(what, b) {
        prefsState[what] = b ? 1 : 0;
        ps.setPrefs('topo_prefs', prefsState);
    }

    function applyPreferences(evt) {
//        var zoomPrefs = ps.getPrefs('topo_zoom', null);
//        if (ps.getPrefs('topo_prefs', null)) {
//            restoreConfigFromPrefs();
//        }
//        if (zoomPrefs) {
//            $log.debug('TOPO- Zoom State:', zoomPrefs);
//            zoomer.panZoom([zoomPrefs.tx, zoomPrefs.ty], zoomPrefs.sc, 100);
//        }
    }

    function restoreConfigFromPrefs() {
        // NOTE: toolbar will have set this for us..
        prefsState = ps.asNumbers(
            ps.getPrefs('topo_prefs', ttbs.defaultPrefs), ['ovid'], true
        );

        $log.debug('TOPO- Prefs State:', prefsState);

        flash.enable(false);
        toggleInstances(prefsState.insts);
        toggleSummary(prefsState.summary);
        toggleUseDetailsFlag(prefsState.detail);
        toggleHosts(prefsState.hosts);
        toggleOffline(prefsState.offdev);
        togglePorts(prefsState.porthl);
        toggleMap(prefsState.bg);
        toggleSprites(prefsState.spr);
        ttbs.setToolbar(prefsState.toolbar);
        t3s.setDevLabIndex(prefsState.dlbls);
        t3s.setHostLabIndex(prefsState.hlbls);
        flash.enable(true);
    }


    // somewhat hackish, because summary update cannot happen until we
    //  have opened the websocket to the server; hence this extra function
    // invoked after tes.start()
    function restoreSummaryFromPrefs() {
        prefsState = ps.asNumbers(
            ps.getPrefs('topo_prefs', ttbs.defaultPrefs), ['ovid'], true
        );
        $log.debug('TOPO- Prefs SUMMARY State:', prefsState.summary);

        flash.enable(false);
        toggleSummary(prefsState.summary);
        flash.enable(true);
    }

    // initial set of topo events received, now do post-processing
    function topoStartDone() {
        // give a small delay before attempting to reselect node(s) and
        // highlight elements, since they have to be re-added to the DOM first...
        $timeout(function () {
            $log.debug('^^ topo.topoStartDone() ^^');

            // reselect the previous selection...
            tss.reselect();

            // if an intent should be shown, invoke the appropriate callback
            if ($scope.intentData) {
                tov.hooks.showIntent($scope.intentData);
            }

        }, 200);
    }

    // --- Controller Definition -----------------------------------------

    angular.module('ovTopo', moduleDependencies)
        .controller('OvTopoCtrl',
            ['$scope', '$log', '$location', '$timeout', '$cookies',
            'FnService', 'MastService', 'KeyService', 'ZoomService',
            'GlyphService', 'MapService', 'SvgUtilService', 'FlashService',
            'WebSocketService', 'PrefsService', 'ThemeService',
            'TopoDialogService', 'TopoD3Service', 'TopoEventService',
            'TopoForceService', 'TopoPanelService', 'TopoInstService',
            'TopoSelectService', 'TopoLinkService', 'TopoTrafficService',
            'TopoObliqueService', 'TopoFilterService', 'TopoToolbarService',
            'TopoMapService', 'TopoSpriteService', 'TooltipService',
            'TopoOverlayService', 'LionService',

                function (_$scope_, _$log_, _$loc_, _$timeout_, _$cookies_,
                  _fs_, mast, _ks_, _zs_,
                  _gs_, _ms_, _sus_, _flash_,
                  _wss_, _ps_, _th_,
                  _tds_, _t3s_, _tes_,
                  _tfs_, _tps_, _tis_,
                  _tss_, _tls_, _tts_,
                  _tos_, _fltr_, _ttbs_,
                  _tms_, _tspr_, _ttip_,
                  _tov_, lion) {

            var params = _$loc_.search(),
                selOverlay = params.overlayId,
                projection,
                dim,
                uplink = {
                    // provides function calls back into this space
                    showNoDevs: showNoDevs,
                    projection: function () { return projection; },
                    zoomLayer: function () { return zoomLayer; },
                    zoomer: function () { return zoomer; },
                    opacifyMap: opacifyMap,
                    topoStartDone: topoStartDone,
                };

            $scope = _$scope_;
            $log = _$log_;
            $loc = _$loc_;
            $timeout = _$timeout_;
            fs = _fs_;
            ks = _ks_;
            zs = _zs_;
            gs = _gs_;
            ms = _ms_;
            sus = _sus_;
            flash = _flash_;
            wss = _wss_;
            ps = _ps_;
            th = _th_;
            tds = _tds_;
            t3s = _t3s_;
            tes = _tes_;
            tfs = _tfs_;
            // TODO: consider funnelling actions through TopoForceService...
            //  rather than injecting references to these 'sub-modules',
            //  just so we can invoke functions on them.
            tps = _tps_;
            tis = _tis_;
            tms = _tms_;
            tls = _tls_;
            tos = _tos_;
            fltr = _fltr_;
            ttbs = _ttbs_;
            tspr = _tspr_;
            tov = _tov_;
            tss = _tss_;

            tms.start({
                toggleMap: toggleMap,
                currentMap: currentMap,
                setMap: setMap,
            });

            // pull intent data from the query string...
            if (params.key && params.appId && params.appName) {
                $scope.intentData = {
                    key: params.key,
                    appId: params.appId,
                    appName: params.appName,
                    intentType: params.intentType,
                };
            }

            $scope.notifyResize = function () {
                svgResized(fs.windowSize(mast.mastHeight()));
            };

            // Cleanup on destroyed scope..
            $scope.$on('$destroy', function () {
                $log.log('OvTopoCtrl is saying Buh-Bye!');
                tes.stop();
                tms.stop();
                ks.unbindKeys();
                tps.destroyPanels();
                tds.closeDialog();
                tis.destroyInst();
                tfs.destroyForce();
                ttbs.destroyToolbar();
                mapShader(false);
            });

            // svg layer and initialization of components
            ovtopo = d3.select('#ov-topo');
            svg = ovtopo.select('svg');
            // set the svg size to match that of the window, less the masthead
            svg.attr(fs.windowSize(mast.mastHeight()));
            dim = [svg.attr('width'), svg.attr('height')];

            ps.addListener(applyPreferences);

            setUpKeys();
            setUpToolbar();
            setUpDefs();
            setUpZoom();
            setUpNoDevs();
            setUpMap().then(
                function (proj) {
                    var z = ps.getPrefs('topo_zoom', { tx: 0, ty: 0, sc: 1 });
                    zoomer.panZoom([z.tx, z.ty], z.sc);
                    $log.debug('** Zoom restored:', z);

                    projection = proj;
                    $log.debug('** We installed the projection:', proj);
                    flash.enable(false);
                    toggleMap(prefsState.bg);
                    flash.enable(true);
                    mapShader(true);

                    // piggyback off the deferred map loading to load the
                    // localization bundle after the uber bundle has arrived...
                    $scope.lion = lion.bundle('core.view.Topo');
                    topoLion = $scope.lion;
                    $log.debug('Loaded Topo LION Bundle:', topoLion);

                    // insert localized text into already established
                    // DOM elements...
                    lionNoDevs();

                    // pass lion bundle function ref to other topo modules
                    tfs.setLionBundle(topoLion);
                    tis.setLionBundle(topoLion);
                    tms.setLionBundle(topoLion);
                    tps.setLionBundle(topoLion);
                    ttbs.setLionBundle(topoLion);

                    // now we have the map projection, we are ready for
                    //  the server to send us device/host data...
                    tes.start();
                    // need to do the following so we immediately get
                    //  the summary panel data back from the server
                    restoreSummaryFromPrefs();
                }
            );
            tes.bindHandlers();
            setUpSprites();

            forceG = zoomLayer.append('g').attr('id', 'topo-force');
            tfs.initForce(svg, forceG, uplink, dim);
            tis.initInst({ showMastership: tfs.showMastership });
            tps.initPanels();

            restoreConfigFromPrefs();

            ttbs.selectOverlay(selOverlay || prefsState.ovid);

            $log.debug('registered overlays...', tov.list());
            $log.log('OvTopoCtrl has been created');
        }]);
}());
