var EventHandler = Class.create();
EventHandler.prototype = {
    m_listeners: [],

    _addListener: function(listener/*function*/) {
        if (typeof (listener) == "function") {
            this.m_listeners.push(listener);
        }
        else {
            throw Exceptions.INVALID_ARGUMENT;
        }
    },

    initialize: function() {
        this.m_listeners = [];
    },

    /**
    * Called by implementing component to trigger all event handlers.
    * @returns bool true if any listeners, otherwise false.
    */
    fire: function(/*arguments*/) {
        if (this.m_listeners.length > 0) {
            for (var i = 0; i < this.m_listeners.length; i++) {
                if (false) {
                    //trigger listeners async
                    setTimeout(
                        (function(index, args) {

                            try {
                                //Move all arguments to function above index 0 to new arguments array and pass to handler
                                if (args.length == 0) {
                                    this.m_listeners[index]();
                                }
                                else {
                                    //this.m_listeners[index](args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
                                    this.m_listeners[index].apply(this, args);
                                }
                            }
                            catch (e) { }
                        }).bind(this, i, arguments), 0);
                }
                else {
                    try {
                        this.m_listeners[i].apply(this, arguments);
                    }
                    catch (e) {  }
                }
            }
            return true;
        }
        else return false;
    }
}

/**
* StateManager. Extend object prototype and use as state manager for component
* @constructor
*/
var EventHandlerManager = Class.create();
EventHandlerManager.prototype = {
    m_eventNames : [], //Array of event names.
    m_eventHandlers : [], //Array containing Component.EventHandler
    
    initialize : function()
    {
        this.m_eventNames = [];
        this.m_eventHandlers = [];
    },
    
    /**
    * Create new event type
    *
    * @throws Exceptions.EVENT_EXISTS
    * @returns Component.EventHandler
    */
    addEventType : function(
      t_eventName/*string*/)
    {
        if( this.m_eventNames.indexOf(t_eventName) == -1 /*event is not registered*/ )
        {
            //Create internal event handler (Component.EventHandler);
            this.m_eventNames.push(t_eventName);
            
            var t_handler = new EventHandler();
            this.m_eventHandlers.push(t_handler);
            return t_handler;
        }
        else
        {
            throw Exceptions.EVENT_EXISTS;
        }        
    },
    
    /**
    * Trigger all event listeners for event. Use this if there is no
    * handle to the EventHandler-object. Otherwise, use eventhandler.fire(args)
    *
    * @throws throw Exceptions.UNKNOWN_EVENT
    */
    fireEvent : function(
        t_eventName/*string*//*, arguments*/ )
    {
        if( $defined(this.m_eventNames) &&
            this.m_eventNames != null )
        {
            var t_eventIndex = this.m_eventNames.indexOf(t_eventName);
            if( t_eventIndex != -1 /*event is registered*/ )
            {
                //Move all arguments to function above index 0 to new arguments array and pass to handler
                var t_subargs = [];
                for(var i=1; i<arguments.length; i++)
                {
                    t_subargs.push(arguments[i]);
                }
            
                this.m_eventHandlers[t_eventIndex](t_subargs);
            }
            else
            {
                throw Exceptions.UNKNOWN_EVENT(t_eventName);
            }
        }
    },
    
    /**
    * Add global event listener that will be triggered no matter state.
    *
    * @throws throw Exceptions.UNKNOWN_EVENT
    */
    addEventListener : function(
      t_eventName/*string*/, 
      t_eventListener/*function*/)
    {
        if( $defined(this.m_eventNames) &&
            this.m_eventNames != null )
        {
            var t_eventIndex = this.m_eventNames.indexOf(t_eventName);    
              
            if( t_eventIndex != -1 /*event is registered*/ )
            {
                //Add listener to event
                this.m_eventHandlers[t_eventIndex]._addListener(t_eventListener);
            }
            else
            {
                throw Exceptions.UNKNOWN_EVENT(t_eventName);
            } 
        } 
    }
}

var Exceptions = {
    UNKNOWN_EVENT :     function(name){
                            return {message:"Unknown event: " + name};
                        },
    UNKNOWN_STATE :     {message:"Uknown state."},
    STATE_EXISTS :      {message:"State already exists."},
    EVENT_EXISTS :      {message:"Event already registered."},
    INVALID_ARGUMENT :  {message:"Invalid argument."},
    TOO_MANY_ARGUMENTS :{message:"EventHandler.fire only supports 10 arguments."}
};
