/**
 * creating a observer for handling custom events
 * @param id  - unique observer id
 * @param handleOwnEvents boolean - flag, if own events are fired to objects (default false)
 */
Emv.Observer = function (id, handleOwnEvents)
{
//	console.log('construct Emv.Observer [Id:' + id + ']');
	// Id of the element/object
    this.id = id;

    /**
     * list with all Objects registered within this observer
     * each of this objects handleEvent is called from push
     */
    this.registeredObjects = new Array();

    /**
     * default callbacks
     * all callbacks are null so nothing is done by default
     * 
     * @todo - use general callback  (no mediathek specific)
     * 
     * @param Mediacenter.Clipplayer.Callback
     */
    this.callbacks = new Emv.Observer.Callback();
    
    this.handleOwnEvents = false;
    if('undefined' != typeof handleOwnEvents)
    {
        this.handleOwnEvents = handleOwnEvents;
    }
    
    /**
     * returns observer id
     * @return String id
     */
    this.getId = function()
    {
    	return this.id;
    };
    
	/**
	 * Push/Fire an event to all registered objects.
	 * @param Emv.Observer.Event event
	 */
    this.push = function(event)
    {
//        console.log("Emv.Observer.push() " + this.id + ": " + event.name + " from " + event.sourceId);
        // Check if we have an valid callback event to call first. 
        if (eval("this.callbacks." + event.name))
        {
            var func = eval("this.callbacks." + event.name);

            eval(func + "(event)");
        }

        // Loop all registered objects and push/fire the event to them.
        // Handle the event for all other observer objects, but not for the eventīs object.
        for (var i=0; i<this.registeredObjects.length; i++)
        {   
//        	console.log('Emv.Observer.handlingEvent for ' + this.registeredObjects[i].getId())
            if(this.registeredObjects[i].getId() != event.sourceId || this.handleOwnEvents)
            {
//	           console.log('Emv.Observer give event to object ' + this.registeredObjects[i].getId())
        	   this.registeredObjects[i].handleEvent(event);
            }
        }
    };
    
    /**
     * registering a object 
     * if no getId() function is defined
     */
    this.registerObject = function(obj)
    {
//    	console.log('Emv.Observer.registerObject [ObserverID: '+this.id+' -> Id: ' + obj.getId() + ']');
        if('undefined' == typeof(obj.getId))
        {
        	throw 'no function getId() defined for given object';
        }
        if(!this.isClientRegistered(obj.getId()))
        {
//        	console.log('registering object ' + obj.getId() + ' for observer ' + this.id);
            this.registeredObjects[this.registeredObjects.length] = obj;
        }
        else
        {
//        	console.log('WARNING: Emv.Observer.registerObject() client with id ' + obj.getId() + ' is already registered');
        }
    };
    
    /**
     * checking all registered objects from client array, if a client with given id already exists
     * @return boolean
     */
    this.isClientRegistered = function(clientId)
    {
//    	console.log('Observer['+this.id+']: isClientRegistered ('+clientId+')');
    	var j = 0;
    	for (j = 0; j < this.registeredObjects.length; j++)
    	{
    		var cObj = this.registeredObjects[j];
    		if(cObj.getId() == clientId)
    		{
    			return true;
    		}
    	}
    	return false;
    };
};

Emv.Observer.Callback = function()
{
	this.init = false;
};

/**
 * single instance for a Event may be fired by an Observer
 */
Emv.Observer.Event = function (name)
{
	this.name = name;
	/**
	 * json list with all params
	 */
	this.params=null;
	
	/**
	 * Elementīs id which fires the event.
	 */
    this.sourceId=null;

    /**
     * Observer id which handles this event
     */
    this.observerId=null;
};

/**
 * global observer controller - holds all instances of observers
 */
Emv.Observer.Controller = 
{
	observerList: new Array(),
	
	/**
	 * returns the observer for given id - or null if observer is not set
	 * 
	 * @param id String observer id
	 * @return Emv.Observer | null
	 */
	getObserver: function(id)
	{
		var i = 0;
		for (i = 0; i < this.observerList.length; i++)
		{
			var cObs = this.observerList[i];
			if(cObs.getId() == id)
			{
				return cObs;
			}
		}
		return null;
	},
	
	/**
	 * checks if observer for given id exists
	 * @param id String observer id
	 * @return boolean - true if exists
	 */
	hasObserver: function(id)
	{
		var i = 0;
		for (i = 0; i < this.observerList.length; i++)
		{
			var cObs = this.observerList[i];
			if(cObs.getId() == id)
			{
				return true;
			}
		}
		return false;
	},

	/**
	 * adds given Emv.Observer to observerlist
	 * @throws Exception if observer for id already exists
	 */
	addObserver: function(obs)
	{
//		console.log('add observer: ' + obs.getId());
		if(this.hasObserver(obs.getId()))
		{
			throw 'an Observer with id ' + obs.getId() +' already exists!';
		}
		else
		{
//			console.log('adding observer: ' + obs.getId());
			this.observerList[this.observerList.length] = obs;
//			console.log(this.observerList);
		}
	}, 
	
	/**
	 * firing an event  source id may be also given within the params json string
	 * params.sourceId
	 * 
	 * @param String name of the event
	 * @param Object par - params 
	 * @param int srcId  - id of the firing object
	 */
	fireEvent: function(name, par, srcId)
	{
//		console.log('fireEvent: ' + name);
		// Evaluate the params into a object.
		var params = 0;
		if(typeof(par) == 'object')
		{
			params = par;
		}
		else
		{
			params = eval("(" + par +")");
		}

        //getting source id 
        var sourceId;
        if('undefined' != typeof(srcId))
        {
            sourceId = srcId;
        }
        else if('undefined' != typeof(params.sourceId))
        {
        	sourceId = params.sourceId;
        }
        //no source id given - exception
        else
        {
//        	console.log('Emv.Observer.Controller.fireEvent: no sourceId for current event "' + name +'" given');
        	return false;
        }
//		console.log("Emv.Observer.Controller.fireEvent(): " + name + ' | source: ' + sourceId);

	    // Create an FPC_ObserverEvent object and set the params.

	    var eventObject = new Emv.Observer.Event(name);
	    eventObject.sourceId = sourceId;
	    eventObject.params = params;

	    // Get the observer for the event and push the event.
	    this.pushObserversForClient(sourceId, eventObject);
	},
	
	/**
	 * pushing an event for a clientId - only observers, where this clientId is registered
	 * getting this event pushed
	 * @param int clientId
	 * @param Emv.Observer.Event event
	 */
	pushObserversForClient: function(clientId, event)
	{
//		console.log('pushObserversForClient: ' + clientId + "->Event: " + event.name + " | " + this.observerList.length + " observers");
		var i = 0;
//		console.log(this.observerList);
		for (i = 0; i < this.observerList.length; i++)
		{
			var cObs = this.observerList[i];
			if(cObs.isClientRegistered(clientId))
			{
//				console.log('pushing Event "' + event.name + '" to observer "' + cObs.getId() +'"');
				cObs.push(event);
			}
			else
			{
//				console.log('Emv.Observer(' + cObs.id + ') [WARNING] client "' +clientId + '" not registered');
			}
		}
	}
	
};

/**
 * global fire event 
 * this function is called f.e. from flashapplications
 * @param string eventName
 * @param string eventParams (JSON formatted)  
 */
function fireEvent(eventName, eventParams)
{
	Emv.Observer.Controller.fireEvent(eventName, eventParams);
}