/**
 * 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)
{
    // 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)
    {
        // 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++)
        {
            if(this.registeredObjects[i].getId() != event.sourceId || this.handleOwnEvents)
            {
               this.registeredObjects[i].handleEvent(event);
            }
        }
    };

    /**
     * registering a object
     * if no getId() function is defined
     */
    this.registerObject = function(obj)
    {

        if('undefined' == typeof(obj.getId))
        {
            throw 'no function getId() defined for given object';
        }
        if(!this.isClientRegistered(obj.getId()))
        {
            this.registeredObjects[this.registeredObjects.length] = obj;
        }
    };

    /**
     * checking all registered objects from client array, if a client with given id already exists
     * @return boolean
     */
    this.isClientRegistered = function(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)
    {
        if(this.hasObserver(obs.getId()))
        {
            throw 'an Observer with id ' + obs.getId() +' already exists!';
        }
        else
        {
            this.observerList[this.observerList.length] = obs;
        }
    },

    /**
     * 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)
    {
        // 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
        {
            return false;
        }

        // 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)
    {
        var i = 0;
        for (i = 0; i < this.observerList.length; i++)
        {
            var cObs = this.observerList[i];
            if(cObs.isClientRegistered(clientId))
            {
                cObs.push(event);
            }
        }
    }
};

/**
 * 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);
}
