function sub(type,handler){
    checkScope.apply(this);
        
    if(!this._events_[type])
        this._events_[type]=[];
        
    this._events_[type].push(handler);
}

function unsub(type,handler){
    checkScope.apply(this);
    
    if(type=='*'){
        var params=Array.prototype.slice.call(arguments,1);
        for(
            var keys    = Object.keys(this._events_),
                count   = keys.length,
                i=0;
            i<count;
            i++
        ){
            var args=params.unshift(keys[i]);
            this.off.call(args);
        }
    }
        
    if(!this._events_[type])
        return;
    
    if(!handler){
        delete this._events_[type];
        return;
    }
    
    if(this._events_[type].length<2){
        delete this._events_[type];
        return;
    }
    
    for(var i=0, 
            count=this._events_[type].length;
        i<count;
        i++
    ){
        if(this._events_[type][i]==handler)
            this._events_[type].splice(i,1);
        return;
    }
}

function pub(type){
    checkScope.apply(this);
    
    if(this._events_['*'] && type!='*'){
        var params=Array.prototype.slice.call(arguments);
        params.unshift('*');
        this.trigger.apply(this,params);
    }
    
    if(!this._events_[type])
        return;
        
    for(var i=0, 
            events=this._events_[type], 
            count=events.length,
            args=Array.prototype.slice.call(arguments,1); 
    i<count; 
    i++){
        events[i].apply(this, args);
    }
}

function checkScope(){
    if(!this._events_)
        this._events_={};
}

function init(scope){
    if(!scope)
        return {
            on:sub,
            off:unsub,
            trigger:pub
        };
        
    scope.on=(
        function(scope){
            return function(){
                sub.apply(
                    scope, 
                    Array.prototype.slice.call(arguments)
                );
            }
        }
    )(scope);
    
    scope.off=(
        function(scope){
            return function(){
                unsub.apply(
                    scope, 
                    Array.prototype.slice.call(arguments)
                );
            }
        }
    )(scope);
    
    scope.trigger=(
        function(scope){
            return function(){
                pub.apply(
                    scope, 
                    Array.prototype.slice.call(arguments)
                );
            }
        }
    )(scope);
    
    scope._events_={};
}

module.exports=init