// # EventEmitterClass
// Lightweigt EventEmitter
// Just does what is needs to do
// TODO: make it follow the Nodejs EventEmitter API
// It acts entirely as documented on nodejs with one expection:
// http://nodejs.org/docs/v0.5.1/api/events.html#emitter.listeners
// EventEmitter.listeners(type) is available
// But it will return only the recuring listeners (not the once listeners)
// It will return false when there are no listeners for that type

VNLS.addClass("EventEmitter",function(){
    function EventEmitter(){
        this._listeners = {};
        this._oncelisteners = {};
        this._counter = 0;
        this._max = 10;
    };
    
    EventEmitter.prototype.addListener =  function(type, listener){
        if(this._counter >= this._max){
            throw "MaxListeners exceeded use: 'setMaxListeners(n)' to raise";
        }
        
        if (typeof(this._listeners[type]) == "undefined"){
            this._listeners[type] = [];
        };
        this._counter ++;
        this._listeners[type].push(listener);
        this.emit("newListener",listener);
        return this;
    };
    EventEmitter.prototype.on = function(type, listener){
        this.addListener(type, listener);
    };
    
    EventEmitter.prototype.once =  function(type, listener){
        if(this._counter >= this._max){
            throw "MaxListeners exceeded use: 'setMaxListeners(n)' to raise";
        }
        
        if (typeof(this._oncelisteners[type]) == "undefined"){
            this._oncelisteners[type] = [];
        };
        this._counter ++;
        this._oncelisteners[type].push(listener);
        this.emit("newListener",listener);
        return this;
    };
    
   EventEmitter.prototype.emit = function(event){
        if (typeof(event) == "string"){
            event = { type: event };
        }
        if (!event.target){
            event.target = this;
        }
        
        if (!event.type){  //falsy
            throw new Error("Event object missing 'type' property.");
        }
        // Fire NORMAL listeneers
        if (this._listeners[event.type] instanceof Array){
            var pass_prams = [];
            for(var i = 0; i < arguments.length; i++){
                if(i>0){
                    pass_prams.push(arguments[i]);
                }
            }
            var listeners = this._listeners[event.type]
            for (var i=0, len=listeners.length; i < len; i++){
                listeners[i].apply(event.target, pass_prams);
            }
        };  
        
         // Fire ONCE listeners and clear them
        if (this._oncelisteners[event.type] instanceof Array){
            var pass_prams = [];
            for(var i = 0; i < arguments.length; i++){
                if(i>0){
                    pass_prams.push(arguments[i]);
                }
            }
            var listeners = this._oncelisteners[event.type]
            for (var i=0, len=listeners.length; i < len; i++){
                listeners[i].apply(event.target, pass_prams);
            }
            // Clear the once listeners
            this._removeAllOnceListeners(event.type);
        }   
        return this;
   };
   EventEmitter.prototype.listeners = function(type){
        if (this._listeners[type] instanceof Array){
            return  this._listeners[type];
        }
        return false;
   };
   EventEmitter.prototype.removeListener = function(type, listener){
        // Remove from normal listeners
        if (this._listeners[type] instanceof Array){
            var listeners = this._listeners[type];
            for (var i=0, len=listeners.length; i < len; i++){
                if (listeners[i] === listener){
                     this._counter --;
                    listeners.splice(i, 1);
                    break;
                }
            }
        }
        // Remove from ONCE listeners
        if (this._oncelisteners[type] instanceof Array){
            var listeners = this._oncelisteners[type];
            for (var i=0, len=listeners.length; i < len; i++){
                if (listeners[i] === listener){
                     this._counter --;
                    listeners.splice(i, 1);
                    break;
                }
            }
        }
        return this;
   };
   EventEmitter.prototype.removeAllListeners = function(type){
            if (typeof(type) == "string"){
               if (this._listeners[type] instanceof Array){
                   this._counter -= this._listeners[type].length;
                   this._listeners[type] = undefined;
               }
               if (this._oncelisteners[type] instanceof Array){
                   this._counter -= this._oncelisteners[type].length;
                   this._oncelisteners[type] = undefined;
               }
            }else{
                this._counter = 0;
                this._listeners = {};
                this._oncelisteners = {};
            }
            
            return this;
   };
   EventEmitter.prototype.setMaxListeners = function(n){
        this._max = n;
        return this;
   };
   
    EventEmitter.prototype._removeAllOnceListeners = function(type){
            if (typeof(type) == "string"){
               if (this._oncelisteners[type] instanceof Array){
                   this._counter -= this._oncelisteners[type].length;
                   this._oncelisteners[type] = undefined;
               }
            }
            return this;
   };
   
   return EventEmitter;
});
