/*
 * 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
            };
        }]);
})();
