/* File requires:
- Dave Glass yuiloader.js (eventually)
- YUI custom events
- prototype-1.4.0.js
*/
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), 1 );                
                }
                else
                {       
                    try
                    {
                        //this.m_listeners[i](arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],arguments[5],arguments[6],arguments[7],arguments[8],arguments[9]);
                        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 EventStateManager = Class.create();
EventStateManager.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( typeof this.m_eventNames != "undefined" &&
            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( typeof this.m_eventNames != "undefined" &&
            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);
            } 
        } 
    }
    
//    /**
//    * Set a new state type
//    * Set handlers with addEventStateListener
//    * @throws Exceptions.STATE_EXISTS
//    */
//    addState : function(
//      stateId/*int*/)
//    {
//        if( !false /*state is already registered*/ )
//        {
//        
//        }
//        else
//        {
//            throw Exceptions.STATE_EXISTS;
//        }
//    },
//    
//    /**
//    * Set state as active state. Requires that the stateId has been registered with addState
//    *
//    * @throws Exceptions.UNKNOWN_STATE
//    */
//    setState : function(
//      stateId/*int*/)
//    {
//        if( true /*state is registered*/ )
//        {}
//        else
//        {
//            throw Exceptions.UNKNOWN_STATE;
//        }
//    },
//    
//    /**
//    * Add event listeners for given state
//    * @param eventStateListeners
//    *   An object notation object, with pairs of eventname/eventhandler. E.g.:
//    *   {
//    *     "click" : myGlobalObject.callbackClick,
//    *     "contentLoaded" : myGlobalObject.callbackContentLoaded 
//    *   }
//    * @throws Exceptions.UNKNOWN_STATE
//    */
//    addEventStateListener : function(
//      stateId /*int*/, 
//      eventStateListeners /*object*/)
//    {
//        if( true /*state is registered*/ )
//        {}
//        else
//        {
//            throw Exceptions.UNKNOWN_STATE;
//        }
//    }
}

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."}
};
//Object.extend(EventStateManager.prototype, {
//    Exceptions : 
//    {
//        UNKNOWN_EVENT : "Unknown event.",
//        UNKNOWN_STATE : "Uknown state.",
//        STATE_EXISTS : "State already exists.",
//        EVENT_EXISTS : "Event already registered.",
//        INVALID_ARGUMENT : "Invalid argument."
//    }
//});





/*
Extend with:
Map.StateManager = Class.create();

Map.StateManager.prototype = Object.extend(new Component.StateManager(), {
  test : function(test) {
    alert(test);
  }
*/

//Map.StateHandler.registerHandle = function()
//{
//    
//}

/**
* StateHandler. Extend object prototype and use as state handler for specialized state manager
* @constructor
*/
//Object.extend(Map, {
//    StateHandler : function(stateId, callbackEvents)
//    {
//        var m_stateId = stateId;
//        var m_callbackEvents = callbackEvents;
//    }
//});





