import IEventDispatcher from "./IEventDispatcher";


/**
 * 事件分发器
 */
export class EventDispatcher implements IEventDispatcher {

    /**
     * 对象已经注册的处理器
     */
    private callerMap:Map<any,EventHandler[]>=new Map<any,EventHandler[]>();

    /**
     * 事件派发器上所监听的处理器
     */
    private keyMap:Map<string,EventHandler[]>=new Map<string,EventHandler[]>();

    /**
     * 添加事件
     * @param key 
     * @param caller 
     * @param func 
     * @param priority 优先级（数字越小优先级越高）
     */
    AddEvent(key:string,caller:any,func:Function,priority:number=0):void{
        let handlerList:EventHandler[];
        let handler:EventHandler;
        if(this.keyMap.has(key)){
            handlerList=this.keyMap.get(key);
            for (const iterator of handlerList) {
                if(iterator.target==caller&&iterator.func==func){
                    console.error("重复添加同一个事件监听："+key+" "+caller+" "+func);
                    return;
                }
            }
        }else{
            handlerList=[];
            this.keyMap.set(key,handlerList);
        }
        handler=new EventHandler(key,caller,func);
        handlerList.push(handler);
        //按照优先级排序
        handlerList.sort((a,b)=>a.priority - priority);

        //处理器关联处理
        if(this.callerMap.has(caller)){
            handlerList=this.callerMap.get(caller);
            for (const iterator of handlerList) {
                if(iterator.key==key&&iterator.func==func)
                {
                    console.error("事件系统 处理器关联错误："+key+" "+caller+" "+func);
                }
            }
        }else{
            handlerList=[];
            this.callerMap.set(caller,handlerList);
        }
        handlerList.push(handler);
    }

    /**
     * 删除事件监听
     * @param key 
     * @param caller 
     * @param func 
     */
    RemoveEvent(key:string,caller:any,func:Function):void{
        if(this.keyMap.has(key)==false){
            return;
        }
        let handlerList:EventHandler[]=this.keyMap.get(key);
        let handler:EventHandler;
        let deleteHandler:EventHandler;
        //删除
        for (let index = 0; index < handlerList.length; index++) {
            handler = handlerList[index];
            if(handler.target==caller&&handler.func==func){
                deleteHandler=handler;
                handlerList.splice(index,1);
                break;
            }
        }
        handlerList=this.callerMap.get(caller);
         //删除
        for (let index = 0; index < handlerList.length; index++) {
            handler = handlerList[index];
            if(handler.key==key&&handler.func==func){
                deleteHandler=handler;
                handlerList.splice(index,1);
                break;
            }
        }
        //销毁处理器
        deleteHandler.Destroy();
    }

    /**
     * 删除指定对象所有的事件处理
     * @param caller 
     */
    RemoveEventByCaller(caller:any):void{
        let handlerList:EventHandler[]=this.callerMap.get(caller);
        let handler:EventHandler;
        //逐个删除
        while (handlerList.length) {
            handler=handlerList[0];
            this.RemoveEvent(handler.key,handler.target,handler.func);
        }
        //删除空列表
        this.callerMap.delete(caller);
    }

    /**
     * 删除所有事件监听
     */
    RemoveAllEvent():void{
        this.keyMap.forEach(handlerList => {
            handlerList.forEach(handler => {
                handler.Destroy();
            });
        });
        this.keyMap.clear();
        this.callerMap.clear();
    }

    /**
     * 派发事件
     * @param key 
     * @param data 
     */
    DispatchEvent(key:string,data?:any):void{
        if(this.keyMap.has(key)==false){
            return;
        }
        let handlerList:EventHandler[]=this.keyMap.get(key);
        let handler:EventHandler;
        for (let index = 0; index < handlerList.length; index++) {
            handler = handlerList[index];
            handler.func.apply(handler.target,[data]);
        }
    }

    /**
     * 是否有事件监听
     * @param key 
     */
    HasEvent(key:string):boolean{
        return this.keyMap.has(key);
    }

    /**
     * 是否包含指定函数事件监听
     * @param key 
     * @param caller 
     * @param func 
     */
    HasEventHandler(key:string,caller:any,func:Function):boolean{
        if(this.keyMap.has(key)==false){
            return false;
        }
        let handlerList:EventHandler[]=this.keyMap.get(key);
        let handler:EventHandler;
        for (let index = 0; index < handlerList.length; index++) {
            handler = handlerList[index];
            if(handler.target==caller&&handler.func==func){
                return true;
            }
        }
        return false;
    }
}

class EventHandler{
    key:string;
    target:any;
    func:Function;
    priority:number;

    constructor(key:string,target:any,func:Function){
        this.key=key;
        this.target=target;
        this.func=func;
    }

    Destroy(){
        this.target=null;
        this.key=null;
        this.func=null;
    }
}
