/*
 * Copyright 2019-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.
 */
import {
    AfterViewInit,
    Component, HostListener, Inject, Input,
    OnDestroy,
    OnInit, SimpleChange,
    ViewChild
} from '@angular/core';
import * as d3 from 'd3';
import {
    FnService,
    IconService,
    KeysService,
    KeysToken,
    LionService,
    LogService,
    PrefsService,
    SvgUtilService,
    TopoZoomPrefs,
    WebSocketService,
    ZoomUtils
} from 'gui2-fw-lib';
import {InstanceComponent} from '../panel/instance/instance.component';
import {DetailsComponent} from '../panel/details/details.component';
import {BackgroundSvgComponent} from '../layer/backgroundsvg/backgroundsvg.component';
import {ForceSvgComponent} from '../layer/forcesvg/forcesvg.component';
import {Intent, TopologyService} from '../topology.service';
import {
    GridDisplayToggle,
    HostLabelToggle,
    LabelToggle,
    UiElement
} from '../layer/forcesvg/models';
import {
    ALL_TRAFFIC,
    BKGRND_SELECT,
    BKGRND_TOGGLE,
    CANCEL_TRAFFIC,
    CYCLEGRIDDISPLAY_BTN,
    CYCLEHOSTLABEL_BTN,
    CYCLELABELS_BTN,
    DETAILS_TOGGLE,
    EQMASTER_BTN,
    HOSTS_TOGGLE,
    INSTANCE_TOGGLE,
    LAYOUT_ACCESS_BTN,
    LAYOUT_DEFAULT_BTN,
    OFFLINE_TOGGLE,
    PORTS_TOGGLE,
    QUICKHELP_BTN,
    RESETZOOM_BTN,
    SUMMARY_TOGGLE,
    ALARMS_TOGGLE
} from '../panel/toolbar/toolbar.component';
import {TrafficService, TrafficType} from '../traffic.service';
import {ZoomableDirective} from '../layer/zoomable.directive';
import {MapObject} from '../layer/maputils';
import {LayoutService, LayoutType} from '../layout.service';
import {SelectedEvent} from '../layer/forcesvg/visuals/nodevisual';
import {ActivatedRoute} from '@angular/router';

const TOPO2_PREFS = 'topo2_prefs';
const TOPO_MAPID_PREFS = 'topo_mapid';

const PREF_BG = 'bg';
const PREF_DETAIL = 'detail';
const PREF_DLBLS = 'dlbls';
const PREF_HLBLS = 'hlbls';
const PREF_GRID = 'grid';
const PREF_HOSTS = 'hosts';
const PREF_INSTS = 'insts';
const PREF_OFFDEV = 'offdev';
const PREF_PORTHL = 'porthl';
const PREF_SUMMARY = 'summary';
const PREF_TOOLBAR = 'toolbar';
const PREF_PINNED = 'pinned';
const PREF_TRAFFIC = 'traffic';
const PREF_ALARMS = 'alarms';

const BACKGROUND_ELEMENTS = [
    'svg topo2',
    'path bgmap'
];

/**
 * Model of the topo2_prefs object - this is a subset of the overall Prefs returned
 * by the server
 */
export interface Topo2Prefs {
    bg: number;
    detail: number;
    dlbls: number;
    hlbls: number;
    hosts: number;
    insts: number;
    offdev: number;
    porthl: number;
    spr: number;
    ovid: string;
    summary: number;
    toolbar: number;
    grid: number;
    pinned: number;
    traffic: number;
    alarms: number;
}

/**
 * ONOS GUI Topology View
 *
 * This Topology View component is the top level component in a hierarchy that
 * comprises the whole Topology View
 *
 * There are three main parts (panels, graphical and breadcrumbs)
 * The panel hierarchy
 * |-- Instances Panel (shows ONOS instances)
 * |-- Summary Panel (summary of ONOS)
 * |-- Toolbar Panel (the toolbar)
 * |-- Details Panel (when a node is selected in the Force graphical view (see below))
 *
 * The graphical hierarchy contains
 * Topology (this)
 *  |-- No Devices Connected (only of there are no nodes to show)
 *  |-- Zoom Layer (everything beneath this can be zoomed and panned)
 *      |-- Background (container for any backgrounds - can be toggled on and off)
 *          |-- Map
 *      |-- Forces (all of the nodes and links laid out by a d3.force simulation)
 *
 * The breadcrumbs
 * |-- Breadcrumb (in region view a way of navigating back up through regions)
 */
@Component({
  selector: 'onos-topology',
  templateUrl: './topology.component.html',
  styleUrls: ['./topology.component.css']
})
export class TopologyComponent implements OnInit, OnDestroy, AfterViewInit {
    @Input() bannerHeight: number = 48;
    // These are references to the components inserted in the template
    @ViewChild(InstanceComponent, {static: true}) instance: InstanceComponent;
    @ViewChild(DetailsComponent, {static: true}) details: DetailsComponent;
    @ViewChild(BackgroundSvgComponent, {static: true}) background: BackgroundSvgComponent;
    @ViewChild(ForceSvgComponent, {static: true}) force: ForceSvgComponent;
    @ViewChild(ZoomableDirective, {static: true}) zoomDirective: ZoomableDirective;

    flashMsg: string = '';
    // These are used as defaults if nothing is set on the server
    prefsState: Topo2Prefs = <Topo2Prefs>{
        bg: 0,
        detail: 1,
        dlbls: 0,
        hlbls: 2,
        hosts: 0,
        insts: 1,
        offdev: 1,
        ovid: 'traffic', // default to traffic overlay
        porthl: 1,
        spr: 0,
        summary: 1,
        toolbar: 0,
        grid: 0,
        pinned: 0,
        traffic: 2, // default to PORTSTATSPKTSEC, as it will iterate over to 0 on init
        alarms: 1,
    };

    mapIdState: MapObject = <MapObject>{
        id: undefined,
        scale: 1.0
    };
    mapSelShown: boolean = false;
    lionFn; // Function

    gridShown: boolean = true;
    geoGridShown: boolean = true;

    constructor(
        protected log: LogService,
        protected fs: FnService,
        protected ks: KeysService,
        protected sus: SvgUtilService,
        protected ps: PrefsService,
        protected wss: WebSocketService,
        protected ts: TopologyService,
        protected trs: TrafficService,
        protected is: IconService,
        private lion: LionService,
        private layout: LayoutService,
        protected ar: ActivatedRoute,
        @Inject('Window') public window: any,
    ) {
        if (this.lion.ubercache.length === 0) {
            this.lionFn = this.dummyLion;
            this.lion.loadCbs.set('topo-toolbar', () => this.doLion());
        } else {
            this.doLion();
        }

        this.log.warn('Constructor', this.zoomDirective);

        this.is.loadIconDef('active');
        this.is.loadIconDef('bgpSpeaker');
        this.is.loadIconDef('bird');
        this.is.loadIconDef('deviceTable');
        this.is.loadIconDef('fiber_switch');
        this.is.loadIconDef('flowTable');
        this.is.loadIconDef('groupTable');
        this.is.loadIconDef('m_allTraffic');
        this.is.loadIconDef('m_cycleLabels');
        this.is.loadIconDef('m_cycleGridDisplay');
        this.is.loadIconDef('m_disjointPaths');
        this.is.loadIconDef('m_details');
        this.is.loadIconDef('m_endstation');
        this.is.loadIconDef('m_eqMaster');
        this.is.loadIconDef('m_fiberSwitch');
        this.is.loadIconDef('m_firewall');
        this.is.loadIconDef('m_map');
        this.is.loadIconDef('m_microwave');
        this.is.loadIconDef('m_ols');
        this.is.loadIconDef('m_otn');
        this.is.loadIconDef('m_ports');
        this.is.loadIconDef('m_resetZoom');
        this.is.loadIconDef('m_roadm');
        this.is.loadIconDef('m_roadm_otn');
        this.is.loadIconDef('m_router');
        this.is.loadIconDef('m_selectMap');
        this.is.loadIconDef('m_summary');
        this.is.loadIconDef('m_switch');
        this.is.loadIconDef('m_terminal_device');
        this.is.loadIconDef('m_uiAttached');
        this.is.loadIconDef('m_unknown');
        this.is.loadIconDef('meterTable');
        this.is.loadIconDef('microwave');
        this.is.loadIconDef('otn');
        this.is.loadIconDef('portTable');
        this.is.loadIconDef('roadm_otn');
        this.is.loadIconDef('triangleUp');
        this.is.loadIconDef('uiAttached');
    }

    /**
     * Static functions must come before member variables
     * @param index Corresponds to LabelToggle.Enum index
     */
    private static deviceLabelFlashMessage(index: number): string {
        switch (index) {
            case 0: return 'fl_device_labels_hide';
            case 1: return 'fl_device_labels_show_friendly';
            case 2: return 'fl_device_labels_show_id';
        }
    }

    private static hostLabelFlashMessage(index: number): string {
        switch (index) {
            case 0: return 'fl_host_labels_hide';
            case 1: return 'fl_host_labels_show_friendly';
            case 2: return 'fl_host_labels_show_ip';
            case 3: return 'fl_host_labels_show_mac';
        }
    }

    private static gridDisplayFlashMessage(index: number): string {
        switch (index) {
            case 0: return 'fl_grid_display_hide';
            case 1: return 'fl_grid_display_1000';
            case 2: return 'fl_grid_display_geo';
            case 3: return 'fl_grid_display_both';
        }
    }

    private static trafficTypeFlashMessage(index: number): string {
        switch (index) {
            case 0: return 'tr_fl_fstats_bytes';
            case 1: return 'tr_fl_pstats_bits';
            case 2: return 'tr_fl_pstats_pkts';
        }
    }

    /**
     * Pass the list of Key Commands to the KeyService, and initialize the Topology
     * Service - which communicates with through the WebSocket to the ONOS server
     * to get the nodes and links.
     */
    ngOnInit() {
        this.bindCommands();

        // The components from the template are handed over to TopologyService here
        // so that WebSocket responses can be passed back in to them
        // The handling of the WebSocket call is delegated out to the Topology
        // Service just to compartmentalize things a bit
        this.ts.init(this.instance, this.background, this.force);

        // For the 2.1 release to not listen to updates of prefs as they are
        // only the echo of what we have sent down and the event mechanism
        // does not discern between users. Can get confused if multiple windows open
        // this.ps.addListener((data) => this.prefsUpdateHandler(data));

        this.prefsState = this.ps.getPrefs(TOPO2_PREFS, this.prefsState);
        this.mapIdState = this.ps.getPrefs(TOPO_MAPID_PREFS, this.mapIdState);
        this.trs.init(this.force);

        // Scale the window initially - then after resize
        const zoomMapExtents = ZoomUtils.zoomToWindowSize(
            this.bannerHeight, this.window.innerWidth, this.window.innerHeight);
        this.zoomDirective.changeZoomLevel(zoomMapExtents, true);

        // TODO find out why the following is never printed
        this.log.debug('TopologyComponent initialized,',
            this.bannerHeight, this.window.innerWidth, this.window.innerHeight,
            zoomMapExtents);
    }

    ngAfterViewInit(): void {
        this.ar.queryParams.subscribe(params => {
            const intentId = params['intentId'];
            const intentType = params['intentType'];
            const appId = params['appId'];
            const appName = params['appName'];

            if (intentId && intentType && appId) {
                const selectedIntent = <Intent>{
                    key: intentId,
                    type: intentType,
                    appId: appId,
                    appName: appName,
                };
                this.ts.setSelectedIntent(selectedIntent);

                this.log.warn('TopologyComponent init with Intent: ', selectedIntent, params);
            }
        });
    }

    /**
     * Callback function that's called whenever new Prefs are received from WebSocket
     *
     * Note: At present the backend server does not filter updated by logged in user,
     * so you might get updates pertaining to a different user
     */
    prefsUpdateHandler(data: any): void {
        // Extract the TOPO2 prefs from it
        if (data[TOPO2_PREFS]) {
            this.prefsState = data[TOPO2_PREFS];
        }
        this.log.debug('Updated topo2 prefs', this.prefsState, this.mapIdState);
    }

    /**
     * When this component is being stopped, disconnect the TopologyService from
     * the WebSocket
     */
    ngOnDestroy() {
        this.ts.destroy();
        this.ps.removeListener((data) => this.prefsUpdateHandler(data));
        this.trs.destroy();
        this.log.debug('Topology component destroyed');
    }

    @HostListener('window:resize', ['$event'])
    onResize(event) {
        const zoomMapExtents = ZoomUtils.zoomToWindowSize(
                this.bannerHeight, event.target.innerWidth, event.target.innerHeight);
        this.zoomDirective.changeZoomLevel(zoomMapExtents, true);
        this.log.debug('Topology window resize',
            event.target.innerWidth, event.target.innerHeight, this.bannerHeight, zoomMapExtents);
    }

    /**
     * When ever a toolbar button is clicked, an event is sent up from toolbar
     * component which is caught and passed on to here.
     * @param name The name of the button that was clicked
     */
    toolbarButtonClicked(name: string) {
        switch (name) {
            case INSTANCE_TOGGLE:
                this.toggleInstancePanel();
                break;
            case SUMMARY_TOGGLE:
                this.toggleSummary();
                break;
            case DETAILS_TOGGLE:
                this.toggleDetails();
                break;
            case HOSTS_TOGGLE:
                this.toggleHosts();
                break;
            case OFFLINE_TOGGLE:
                this.toggleOfflineDevices();
                break;
            case PORTS_TOGGLE:
                this.togglePorts();
                break;
            case BKGRND_TOGGLE:
                this.toggleBackground();
                break;
            case BKGRND_SELECT:
                this.mapSelShown = !this.mapSelShown;
                break;
            case CYCLELABELS_BTN:
                this.cycleDeviceLabels();
                break;
            case CYCLEHOSTLABEL_BTN:
                this.cycleHostLabels();
                break;
            case CYCLEGRIDDISPLAY_BTN:
                this.cycleGridDisplay();
                break;
            case RESETZOOM_BTN:
                this.resetZoom();
                break;
            case EQMASTER_BTN:
                this.equalizeMasters();
                break;
            case CANCEL_TRAFFIC:
                this.cancelTraffic();
                break;
            case ALL_TRAFFIC:
                this.cycleTrafficTypeDisplay();
                break;
            case QUICKHELP_BTN:
                this.ks.quickHelpShown = true;
                break;
            case LAYOUT_DEFAULT_BTN:
                this.layout.changeLayout(LayoutType.LAYOUT_DEFAULT);
                break;
            case LAYOUT_ACCESS_BTN:
                this.layout.changeLayout(LayoutType.LAYOUT_ACCESS);
                break;
            case ALARMS_TOGGLE:
                this.toggleAlarms();
                break;
            default:
                this.log.warn('Unhandled Toolbar action', name);
        }
    }

    /**
     * The list of key strokes that will be active in the Topology View.
     *
     * This action map is passed to the KeyService through the bindCommands()
     * when this component is being initialized
     *
     * TODO - Replace this doggy doo doo (copied over from GUI-1)
     * with something more structured
     */
    actionMap() {
        return {
            A: [() => {this.cycleTrafficTypeDisplay(); }, this.lionFn('tr_btn_monitor_all')],
            B: [(token) => {this.toggleBackground(token); }, this.lionFn('tbtt_tog_map')],
            D: [(token) => {this.toggleDetails(token); }, this.lionFn('tbtt_tog_use_detail')],
            E: [() => {this.equalizeMasters(); }, this.lionFn('tbtt_eq_master')],
            H: [() => {this.toggleHosts(); }, this.lionFn('tbtt_tog_host')],
            I: [(token) => {this.toggleInstancePanel(token); }, this.lionFn('tbtt_tog_instances')],
            G: [() => {this.mapSelShown = !this.mapSelShown; }, this.lionFn('tbtt_sel_map')],
            L: [() => {this.cycleDeviceLabels(); }, this.lionFn('tbtt_cyc_dev_labs')],
            M: [() => {this.toggleOfflineDevices(); }, this.lionFn('tbtt_tog_offline')],
            O: [() => {this.toggleSummary(); }, this.lionFn('tbtt_tog_summary')],
            P: [(token) => {this.togglePorts(token); }, this.lionFn('tbtt_tog_porthi')],
            Q: [() => {this.cycleGridDisplay(); }, this.lionFn('tbtt_cyc_grid_display')],
            R: [() => {this.resetZoom(); }, this.lionFn('tbtt_reset_zoom')],
            U: [() => {this.unpinOrFreezeNodes(); }, this.lionFn('tbtt_unpin_node')],
            X: [() => {this.resetNodeLocation(); }, this.lionFn('tbtt_reset_loc')],
            dot: [() => {this.toggleToolbar(); }, this.lionFn('tbtt_tog_toolbar')],
            0: [() => {this.cancelTraffic(); }, this.lionFn('tr_btn_cancel_monitoring')],
            'shift-L': [() => {this.cycleHostLabels(); }, this.lionFn('tbtt_cyc_host_labs')],

            // -- instance color palette debug
            9: () => {
                this.sus.cat7().testCard(d3.select('svg#topo2'));
            },

            esc: [() => {this.handleEscape(); }, this.lionFn('qh_hint_esc')],

            // TODO update after adding in Background Service
            // topology overlay selections
            // F1: function () { t2tbs.fnKey(0); },
            // F2: function () { t2tbs.fnKey(1); },
            // F3: function () { t2tbs.fnKey(2); },
            // F4: function () { t2tbs.fnKey(3); },
            // F5: function () { t2tbs.fnKey(4); },
            //
            // _keyListener: t2tbs.keyListener.bind(t2tbs),

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


    bindCommands(additional?: any) {

        const am = this.actionMap();
        this.ks.keyBindings(am);

        this.ks.gestureNotes([
            ['click', 'Select the item and show details'],
            ['shift-click', 'Toggle selection state'],
            ['drag', 'Reposition (and pin) device / host'],
            ['cmd-scroll', 'Zoom in / out'],
            ['cmd-drag', 'Pan'],
        ]);
    }

    handleEscape() {

        if (false) {
            // TODO: Cancel show mastership
            // TODO: Cancel Active overlay
            // TODO: Reinstate with components
        } else {
            this.nodeSelected(undefined);
            this.log.debug('Handling escape');
            // } else if (t2rs.deselectAllNodes()) {
            //     // else if we have node selections, deselect them all
            //     // (work already done)
            // } else if (t2rs.deselectLink()) {
            //     // else if we have a link selection, deselect it
            //     // (work already done)
            // } else if (t2is.isVisible()) {
            //     // If the instance panel is visible, close it
            //     t2is.toggle();
            // } else if (t2sp.isVisible()) {
            //     // If the summary panel is visible, close it
            //     t2sp.toggle();
        }
    }

    /**
     * Updates the cache of preferences locally and onwards to the PrefsService
     * @param what The attribute of the local topo2-prefs cache to update
     * @param b the value to update it with
     */
    updatePrefsState(what: string, b: number) {
        this.prefsState[what] = b;
        this.ps.setPrefs(TOPO2_PREFS, this.prefsState);
    }

    /**
     * When the button is clicked on the toolbar or the L key is pressed
     * 1) cycle through options
     * 2) flash up a message
     * 3a) Update the local prefs cache
     * 3b) And passes on to the global prefs service which sends back to the server
     * 3c) It also has a knock on effect of passing it on to ForceSvgComponent
     *      because prefsState.dlbls is given as an input to it
     * 3d) This will in turn pass it down to the DeviceSvgComponent which
     *       displays the label
     */
    protected cycleDeviceLabels() {
        const old: LabelToggle.Enum = this.prefsState.dlbls;
        const next = LabelToggle.next(old);
        this.flashMsg = this.lionFn(TopologyComponent.deviceLabelFlashMessage(next));
        this.updatePrefsState(PREF_DLBLS, next);
        this.log.debug('Cycling device labels', old, next);
    }

    protected cycleHostLabels() {
        const old: HostLabelToggle.Enum = this.prefsState.hlbls;
        const next = HostLabelToggle.next(old);
        this.flashMsg = this.lionFn(TopologyComponent.hostLabelFlashMessage(next));
        this.updatePrefsState(PREF_HLBLS, next);
        this.log.debug('Cycling host labels', old, next);
    }

    protected cycleGridDisplay() {
        const old: GridDisplayToggle.Enum = this.prefsState.grid;
        const next = GridDisplayToggle.next(old);
        this.flashMsg = this.lionFn(TopologyComponent.gridDisplayFlashMessage(next));
        this.updatePrefsState(PREF_GRID, next);
        this.log.debug('Cycling grid display', old, next);
    }

    protected cycleTrafficTypeDisplay() {
        const old: TrafficType.Enum = this.prefsState.traffic; // by number
        const next = TrafficType.next(old);
        this.flashMsg = this.lionFn(TopologyComponent.trafficTypeFlashMessage(next));
        this.updatePrefsState(PREF_TRAFFIC, next);
        this.trs.requestTraffic(next);
        this.log.debug('Cycling traffic display', old, next);
    }

    /**
     * When the button is clicked on the toolbar or the B key is pressed
     * 1) Find the inverse of the current state (held as 1 or 0)
     * 2) Flash up a message on screen
     * 3b) And passes on to the global prefs service which sends back to the server
     * 3c) It also has a knock on effect of passing it on to ToolbarComponent
     *      because prefsState.bg is given as an input to it
     * @param token not currently used
     */
    protected toggleBackground(token?: KeysToken) {
        const bg: boolean = !Boolean(this.prefsState.bg);
        this.flashMsg = this.lionFn(bg ? 'show' : 'hide') +
            ' ' + this.lionFn('fl_background_map');
        this.updatePrefsState(PREF_BG, bg ? 1 : 0);
        this.log.debug('Toggling background', token, bg ? 'shown' : 'hidden');
    }

    protected toggleDetails(token?: KeysToken) {
        const on: boolean = !Boolean(this.prefsState.detail);
        this.flashMsg = this.lionFn(on ? 'show' : 'hide') +
            ' ' + this.lionFn('fl_panel_details');
        this.updatePrefsState(PREF_DETAIL, on ? 1 : 0);
        this.log.debug('Toggling details', token);
    }

    protected toggleInstancePanel(token?: KeysToken) {
        const on: boolean = !Boolean(this.prefsState.insts);
        this.flashMsg = this.lionFn(on ? 'show' : 'hide') +
            ' ' + this.lionFn('fl_panel_instances');
        this.updatePrefsState(PREF_INSTS, on ? 1 : 0);
        this.log.debug('Toggling instances', token, on);
    }

    protected toggleSummary() {
        const on: boolean = !Boolean(this.prefsState.summary);
        this.flashMsg = this.lionFn(on ? 'show' : 'hide') +
            ' ' + this.lionFn('fl_panel_summary');
        this.updatePrefsState(PREF_SUMMARY, on ? 1 : 0);
    }

    protected togglePorts(token?: KeysToken) {
        const current: boolean = !Boolean(this.prefsState.porthl);
        this.flashMsg = this.lionFn(current ? 'enable' : 'disable') +
            ' ' + this.lionFn('fl_port_highlighting');
        this.updatePrefsState(PREF_PORTHL, current ? 1 : 0);
        this.log.debug(current ? 'Enable' : 'Disable', 'port highlighting');
    }

    protected toggleToolbar() {
        const on: boolean = !Boolean(this.prefsState.toolbar);
        this.updatePrefsState(PREF_TOOLBAR, on ? 1 : 0);
        this.log.debug('toggling toolbar', on ? 'shown' : 'hidden');
    }

    protected toggleHosts() {
        const current: boolean = !Boolean(this.prefsState.hosts);
        this.flashMsg = this.lionFn('hosts') + ' ' +
                        this.lionFn(current ? 'visible' : 'hidden');
        this.updatePrefsState(PREF_HOSTS, current ? 1 : 0);
        this.log.debug('toggling hosts: ', this.prefsState.hosts ? 'Show' : 'Hide');
    }

    protected toggleOfflineDevices() {
        const on: boolean = !Boolean(this.prefsState.offdev);
        this.flashMsg = this.lionFn(on ? 'show' : 'hide') +
            ' ' + this.lionFn('fl_offline_devices');
        this.updatePrefsState(PREF_OFFDEV, on ? 1 : 0);
        this.log.debug('toggling offline devices', this.prefsState.offdev);
    }


    protected toggleAlarms() {
        const on: boolean = !Boolean(this.prefsState.alarms);
        this.flashMsg = this.lionFn(on ? 'show' : 'hide') + ' Alarms';
        this.updatePrefsState(PREF_ALARMS, on ? 1 : 0);
        this.log.debug('Alarms toggled', on);
    }

    protected resetZoom() {
        const zoomMapExtents = ZoomUtils.zoomToWindowSize(
            this.bannerHeight, this.window.innerWidth, this.window.innerHeight);
        this.zoomDirective.changeZoomLevel(zoomMapExtents, false);
        this.flashMsg = this.lionFn('fl_pan_zoom_reset');
    }

    protected equalizeMasters() {
        this.wss.sendEvent('equalizeMasters', {});
        this.flashMsg = this.lionFn('fl_eq_masters');
        this.log.debug('equalizing masters');
    }

    /**
     * If any nodes with fixed positions had been dragged out of place
     * then put back where they belong
     * If there are some devices selected reset only these
     */
    protected resetNodeLocation() {
        const numNodes = this.force.resetNodeLocations();
        this.flashMsg = this.lionFn('fl_reset_node_locations') +
            '(' + String(numNodes) + ')';
        this.log.debug('resetting ', numNodes, 'node(s) location');
    }

    /**
     * Toggle floating nodes between pinned and frozen
     * If there are floating nodes selected toggle only these
     */
    protected unpinOrFreezeNodes() {
        const pinned: boolean = !Boolean(this.prefsState.pinned);
        const numNodes = this.force.unpinOrFreezeNodes(pinned);
        this.flashMsg = this.lionFn(pinned ?
            'fl_pinned_floating_nodes' : 'fl_unpinned_floating_nodes') +
            '(' + String(numNodes) + ')';
        this.updatePrefsState(PREF_PINNED, pinned ? 1 : 0);
        this.log.debug('Toggling pinning for floating ', numNodes, 'nodes', pinned);
    }

    /**
     * Check to see if this is needed anymore
     * @param what - a key stroke
     */
    protected notValid(what) {
        this.log.warn('topo.js getActionEntry(): Not a valid ' + what);
    }

    /**
     * Check to see if this is needed anymore
     * @param key - a key stroke
     */
    getActionEntry(key) {
        let entry;

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

        entry = this.actionMap()[key];

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

    /**
     * An event handler that updates the details panel as items are
     * selected in the forcesvg layer
     *
     * @param nodesOrLink the item(s) to display details of
     */
    nodeSelected(nodesOrLink: UiElement[]) {
        this.details.ngOnChanges({'selectedNodes':
            new SimpleChange(undefined, nodesOrLink, true)});
    }

    /**
     * Cancel traffic monitoring
     */
    cancelTraffic() {
        this.flashMsg = this.lionFn('fl_monitoring_canceled');
        this.trs.cancelTraffic();
    }

    changeMap(map: MapObject) {
        this.mapSelShown = false; // Hide the MapSelector component
        this.mapIdState = map;
        this.ps.setPrefs(TOPO_MAPID_PREFS, this.mapIdState);
        this.log.debug('Map has been changed to ', map);
    }

    mapExtentsZoom(zoomMapExtents: TopoZoomPrefs) {
        // this.zoomDirective.updateZoomState(zoomPrefs.tx, zoomPrefs.ty, zoomPrefs.sc);
        this.zoomDirective.changeZoomLevel(zoomMapExtents);
        this.log.debug('Map zoom prefs updated', zoomMapExtents);
    }

    backgroundClicked(event: MouseEvent) {
        const elemTagName = event.target['tagName'] + ' ' + event.target['id'];
        if (BACKGROUND_ELEMENTS.includes(elemTagName)) {
            this.force.updateSelected(
                <SelectedEvent>{
                    uiElement: undefined,
                    deselecting: true
                }
            );
        }
        this.ts.cancelHighlights();
        this.force.cancelAllLinkHighlightsNow();
    }

    /**
     * Read the LION bundle for Toolbar and set up the lionFn
     */
    doLion() {
        this.lionFn = this.lion.bundle('core.view.Topo');
    }

    /**
     * A dummy implementation of the lionFn until the response is received and the LION
     * bundle is received from the WebSocket
     */
    dummyLion(key: string): string {
        return '%' + key + '%';
    }
}
