/*
 * Copyright 2016-present 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 GUI -- Topology Event Module.

 Defines the conduit between the client and the server:
 - provides a clean API for sending events to the server
 - dispatches incoming events from the server to the appropriate sub-module

 */

(function () {
    'use strict';

    // injected refs
    var $log, wss, t2fs;

    // internal state
    var handlerMap,
        openListener;

    // TODO: only add heartbeat timer etc. if we really need to be doing that..
    // ========================== Helper Functions

    function createHandlerMap() {
        handlerMap = {
            topo2AllInstances: t2fs,
            topo2CurrentLayout: t2fs,
            topo2CurrentRegion: t2fs,
            topo2PeerRegions: t2fs,
            topo2StartDone: t2fs,

            topo2UiModelEvent: t2fs

            // Add further event names / module references as needed
        };
    }

    function wsOpen(host, url) {
        $log.debug('topo2Event: WSopen - cluster node:', host, 'URL:', url);
        // tell the server we are ready to receive topo events
        wss.sendEvent('topo2Start');
    }

    // bind our event handlers to the web socket service, so that our
    //  callbacks get invoked for incoming events
    function bindHandlers() {
        wss.bindHandlers(handlerMap);
        $log.debug('topo2 event handlers bound');
    }

    // tell the server we are ready to receive topology events
    function start() {
        // in case we fail over to a new server,
        // listen for wsock-open events
        openListener = wss.addOpenListener(wsOpen);
        wss.sendEvent('topo2Start');
        $log.debug('topo2 comms started');
    }

    // tell the server we no longer wish to receive topology events
    function stop() {
        wss.sendEvent('topo2Stop');
        wss.unbindHandlers(handlerMap);
        wss.removeOpenListener(openListener);
        openListener = null;
        $log.debug('topo2 comms stopped');
    }

    // ========================== Main Service Definition

    angular.module('ovTopo2')
    .factory('Topo2EventService', [
        '$log', 'WebSocketService', 'Topo2ForceService',

        function (_$log_, _wss_, _t2fs_) {
            $log = _$log_;
            wss = _wss_;
            t2fs = _t2fs_;

            // deferred creation of handler map, so module references are good
            createHandlerMap();

            return {
                bindHandlers: bindHandlers,
                start: start,
                stop: stop
            };
        }]);
})();
