/*
 * This services handles subscription to various event types.
 *
 * To use it, implement a listener that will receive updates (encoded in JSON)
 * Pass this listener to the subscribe() function, along with the type of event it
 * is listening for.
*/
angular.module('events.module', []).service('eventSubscriptionService', function($http)
    {
    var service = {};
    service.source = null;
    service.subscriptions = [];
    var event_types_as_of_last_subscription_update = [];
    service.subscribedSummaryMetricListeners = [];

    // create the subscription and open the EventSource
    service.then = $http.post('/controller/events/subscribe').then(
    	function(data) {
    		service.sub_id = JSON.parse(data.data);
    		service.source = new EventSource('/controller/events/listen/' + service.sub_id);
        },
        function() {
        	console.log("Failed to subscribe.");
        });

    function getSubscribedEventTypes() {
    	return _.unique(_.pluck(service.subscriptions,'event'));
    }
    
    /*
     * Update the server with information about what events we want to listen to.
     */
    function sendSubscriptionsToServer()
		{
    	var event_types = getSubscribedEventTypes();
    	if( _.isEmpty(_.xor(event_types_as_of_last_subscription_update, event_types)) )
    		return null;  //as a premature optimization, don't update the server about the event types if they haven't changed
    	
    	var query = "?";
    	
    	for (var i=0; i<event_types.length; i++)
    		{
    		if (i > 0)
    			query = query + "&";
    		query = query + "event=" + event_types[i];
    		}
    
    	// and inform the controller event service of our new event types
    	return $http.post('/controller/events/types/' + service.sub_id + query).then(new function() {
    		event_types_as_of_last_subscription_update = event_types.slice();
    	});
		}

    /*
     * Subscribe to some type of event using the given listener.
     */
    service.subscribe = function(event_type, listener)
    	{
    	function doIt()
    		{
    		service.subscriptions.push({event: event_type, listener: listener});
    	
    		// keep a list of metric listeners - this is for testing charts with the fake_metrics_generator service
    		if (event_type === 'SummaryMetrics')
    			service.subscribedSummaryMetricListeners.push(listener);

            if (service.source !== null)
        	    service.source.addEventListener(event_type, listener, false);
        	return sendSubscriptionsToServer();
    		}
    		
    	service.then = service.then.then(doIt, doIt);
    	};

    service.injectSummaryMetrics = function(message)
        {
        for (var i=0; i<service.subscribedSummaryMetricListeners.length; i++)
            service.subscribedSummaryMetricListeners[i](message);
        };

    return service;
    });

