/*
 * Copyright 2015-present Open Networking Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { Injectable } from '@angular/core';
import { FnService } from '../util/fn.service';
import { GlyphService } from '../svg/glyph.service';
import { LogService } from '../../log.service';
import { UrlFnService } from './urlfn.service';
import { VeilComponent } from '../layer/veil/veil.component';
import { WSock } from './wsock.service';

/**
 * Event Type structure for the WebSocketService
 */
export interface EventType {
    event: string;
    payload: Object;
}

export interface Callback {
    id: number;
    error: string;
    cb(host: string, url: string): void;
}

interface ClusterNode {
    id: string;
    ip: string;
    m_uiAttached: boolean;
}

interface Bootstrap {
    user: string;
    clusterNodes: ClusterNode[];
    glyphs: any[]; // TODO: narrow this down to a known type
}

interface ErrorData {
    message: string;
}

export interface WsOptions {
    wsport: number;
}

/**
 * ONOS GUI -- Remote -- Web Socket Service
 *
 * To see debug messages add ?debug=txrx to the URL
 */
@Injectable({
  providedIn: 'root',
})
export class WebSocketService {
    // internal state
    private webSockOpts: WsOptions; // web socket options
    private ws: WebSocket = null; // web socket reference
    private wsUp: boolean = false; // web socket is good to go

    // A map of event handler bindings - names and functions (that accept data and return void)
    private handlers = new Map<string, (data: any) => void>([]);
    private pendingEvents: EventType[] = []; // events TX'd while socket not up
    private host: string; // web socket host
    private url; // web socket URL
    private clusterNodes: ClusterNode[] = []; // ONOS instances data for failover
    private clusterIndex = -1; // the instance to which we are connected
    private glyphs = [];
    private connectRetries: number = 0; // limit our attempts at reconnecting

    // A map of registered Callbacks for websocket open()
    private openListeners = new Map<number, Callback>([]);
    private nextListenerId: number = 1; // internal ID for open listeners
    private loggedInUser = null; // name of logged-in user
    private lcd: any; // The loading component delegate
    private vcd: any; // The veil component delegate

    /**
     * built-in handler for the 'boostrap' event
     */
    private bootstrap(data: Bootstrap) {
        this.log.debug('bootstrap data', data);
        this.loggedInUser = data.user;

        this.clusterNodes = data.clusterNodes;
        this.clusterNodes.forEach((d, i) => {
            if (d.m_uiAttached) {
                this.clusterIndex = i;
                this.log.info('Connected to cluster node ' + d.ip);
                // TODO: add connect info to masthead somewhere
            }
        });
        this.glyphs = data.glyphs;
        const glyphsMap = new Map<string, string>([]);
        this.glyphs.forEach((d, i) => {
            glyphsMap.set('_' + d.id, d.viewbox);
            glyphsMap.set(d.id, d.path);
            this.gs.registerGlyphs(glyphsMap);
        });
    }

    private error(data: ErrorData) {
        const m: string = data.message || 'error from server';
        this.log.error(m, data);

        // Unrecoverable error - throw up the veil...
        if (this.vcd) {
            this.vcd.show([
                'Oops!',
                'Server reports error...',
                m,
            ]);
        }
    }

    constructor(
        private fs: FnService,
        private gs: GlyphService,
        private log: LogService,
        private ufs: UrlFnService,
        private wsock: WSock,
        private window: Window
    ) {
        this.log.debug(window.location.hostname);

        // Bind the boot strap event by default
        this.bindHandlers(new Map<string, (data) => void>([
            ['bootstrap', (data) => this.bootstrap(data)],
            ['error', (data) => this.error(data)]
        ]));

        this.log.debug('WebSocketService constructed');
    }


    // ==========================
    // === Web socket callbacks

    /**
     * Called when WebSocket has just opened
     *
     * Lift the Veil if it is displayed
     * If there are any events pending, send them
     * Mark the WSS as up and inform any listeners for this open event
     */
    handleOpen(): void {
        this.log.info('Web socket open - ', this.url);
        // Hide the veil
        if (this.vcd) {
            this.vcd.hide();
        }

        if (this.fs.debugOn('txrx')) {
            this.log.debug('Sending ' + this.pendingEvents.length + ' pending event(s)...');
        }
        this.pendingEvents.forEach((ev) => {
            this.send(ev);
        });
        this.pendingEvents = [];

        this.connectRetries = 0;
        this.wsUp = true;
        this.informListeners(this.host, this.url);
    }

    /**
     * Function called when WebSocket send a message
     */
    handleMessage(msgEvent: MessageEvent): void {
        let ev: EventType;
        let h;
        try {
            ev = JSON.parse(msgEvent.data);
        } catch (e) {
            this.log.error('Message.data is not valid JSON', msgEvent.data, e);
            return null;
        }
        if (this.fs.debugOn('txrx')) {
            this.log.debug(' << *Rx* ', ev.event, ev.payload);
        }
        h = this.handlers.get(ev.event);
        if (h) {
            try {
                h(ev.payload);
            } catch (e) {
                this.log.error('Problem handling event:', ev, e);
                return null;
            }
        } else {
            this.log.warn('Unhandled event:', ev);
        }
    }

    /**
     * Called by the WebSocket if it is closed from the server end
     *
     * If the loading component is shown, call stop() on it
     * Try to find another node in the cluster to connect to
     * If this is not possible then show the Veil Component
     */
    handleClose(): void {
        this.log.warn('Web socket closed');
        if (this.lcd) {
            this.lcd.stop();
        }
        this.wsUp = false;
        let gsucc;

        if (gsucc = this.findGuiSuccessor()) {
            this.url = this.createWebSocket(this.webSockOpts, gsucc);
        } else {
            // If no controllers left to contact, show the Veil...
            if (this.vcd) {
                this.vcd.show([
                    'Oops!',  // TODO: Localize this
                    'Web-socket connection to server closed...',
                    'Try refreshing the page.',
                ]);
            }
        }
    }

    // ==============================
    // === Private Helper Functions

    /**
     * Find the next node in the ONOS cluster.
     *
     * This is used if the WebSocket connection closes because a
     * node in the cluster ges down - fail over should be automatic
     */
    findGuiSuccessor(): string {
        const ncn = this.clusterNodes.length;
        let ip: string;
        let node;

        while (this.connectRetries < ncn && !ip) {
            this.connectRetries++;
            this.clusterIndex = (this.clusterIndex + 1) % ncn;
            node = this.clusterNodes[this.clusterIndex];
            ip = node && node.ip;
        }

        return ip;
    }

    /**
     * When the WebSocket is opened, inform any listeners that registered
     * for that event
     */
    informListeners(host: string, url: string): void {
        for (const [key, cb] of this.openListeners.entries()) {
            cb.cb(host, url);
        }
    }

    send(ev: EventType): void {
        if (this.fs.debugOn('txrx')) {
            this.log.debug(' *Tx* >> ', ev.event, ev.payload);
        }
        this.ws.send(JSON.stringify(ev));
    }

    /**
     * Check if there are no WSS event handlers left
     */
    noHandlersWarn(handlers: Map<string, Object>, caller: string): boolean {
        if (!handlers || handlers.size === 0) {
            this.log.warn('WSS.' + caller + '(): no event handlers');
            return true;
        }
        return false;
    }

    /* ===================
     * === API Functions
     */

    /**
     * Required for unit tests to set to known state
     */
    resetState(): void {
        this.webSockOpts = undefined;
        this.ws = null;
        this.wsUp = false;
        this.host = undefined;
        this.url = undefined;
        this.pendingEvents = [];
        this.handlers.clear();
        this.clusterNodes = [];
        this.clusterIndex = -1;
        this.glyphs = [];
        this.connectRetries = 0;
        this.openListeners.clear();
        this.nextListenerId = 1;

    }

    /*
     * Currently supported opts:
     *  wsport: web socket port (other than default 8181)
     *  host:   if defined, is the host address to use
     */
    createWebSocket(opts?: WsOptions, host?: string) {
        this.webSockOpts = opts; // preserved for future calls
        this.host = host === undefined ? this.window.location.host : host;
        this.url = this.ufs.wsUrl('core', opts === undefined ? '' : opts['wsport'].toString(), host);

        this.log.debug('Attempting to open websocket to: ' + this.url);
        this.ws = this.wsock.newWebSocket(this.url);
        if (this.ws) {
            // fat arrow => syntax means that the 'this' context passed will
            // be of WebSocketService, not the WebSocket
            this.ws.onopen = (() => this.handleOpen());
            this.ws.onmessage = ((msgEvent) => this.handleMessage(msgEvent));
            this.ws.onclose = (() => this.handleClose());

            this.sendEvent('authentication token', { token: 'testAuth' });
        }
        // Note: Wsock logs an error if the new WebSocket call fails
        return this.url;
    }


    /**
     * Binds the message handlers to their message type (event type) as
     *  specified in the given map. Note that keys are the event IDs; values
     *  are either:
     *     * the event handler function, or
     *     * an API object which has an event handler for the key
     */
    bindHandlers(handlerMap: Map<string, (data) => void>): void {
        const dups: string[] = [];

        if (this.noHandlersWarn(handlerMap, 'bindHandlers')) {
            return null;
        }
        for (const [eventId, api] of handlerMap) {
            this.log.debug('Adding handler for ', eventId);
            const fn = this.fs.isF(api) || this.fs.isF(api[eventId]);
            if (!fn) {
                this.log.warn(eventId + ' handler not a function');
                return;
            }

            if (this.handlers.get(eventId)) {
                dups.push(eventId);
            } else {
                this.handlers.set(eventId, fn);
            }
        }
        if (dups.length) {
            this.log.warn('duplicate bindings ignored:', dups);
        }
    }

    /**
     * Unbinds the specified message handlers.
     *   Expected that the same map will be used, but we only care about keys
     */
    unbindHandlers(handlerMap: Map<string, (data) => void>): void {
        if (this.noHandlersWarn(handlerMap, 'unbindHandlers')) {
            return null;
        }

        for (const [eventId, api] of handlerMap) {
            this.handlers.delete(eventId);
        }
    }

    /**
     * Add a listener function for listening for WebSocket opening.
     * The function must give a host and url and return void
     */
    addOpenListener(callback: (host: string, url: string) => void ): Callback {
        const id: number = this.nextListenerId++;
        const cb = this.fs.isF(callback);
        const o: Callback = <Callback>{ id: id, cb: cb };

        if (cb) {
            this.openListeners.set(id, o);
        } else {
            this.log.error('WSS.addOpenListener(): callback not a function');
            o.error = 'No callback defined';
        }
        return o;
    }

    /**
     * Remove a listener of WebSocket opening
     */
    removeOpenListener(lsnr: Callback): void {
        const id = this.fs.isO(lsnr) && lsnr.id;
        let o;

        if (!id) {
            this.log.warn('WSS.removeOpenListener(): invalid listener', lsnr);
            return null;
        }
        o = this.openListeners[id];

        if (o) {
            this.openListeners.delete(id);
        }
    }

    /**
     * Formulates an event message and sends it via the web-socket.
     * If the websocket is not up yet, we store it in a pending list.
     */
    sendEvent(evType: string, payload: Object ): void {
        const ev = <EventType> {
            event: evType,
            payload: payload
        };

        if (this.wsUp) {
            this.send(ev);
        } else {
            this.pendingEvents.push(ev);
        }
    }

    /**
     * Binds the veil service as a delegate.
     */
    setVeilDelegate(vd: VeilComponent): void {
        this.vcd = vd;
    }

    /**
     * Binds the loading service as a delegate
     */
    setLoadingDelegate(ld: any): void {
        // TODO - Investigate changing Loading Service to LoadingComponent
        this.log.debug('Loading delegate set', ld);
        this.lcd = ld;
    }

}
