
/**
 * 游戏事件管理类
 * @author 冯聪
 */
export default class EventSystem {

    /** 监听数组 */
    private listeners: { [key: string]: Observer[] } = {};
    
    /** 
     * 注册事件
     * @param name     事件名称
     * @param callback 回调函数
     * @param target   目标脚本（this）
     */
    public register(name: string, callback: Function, target: any) {

        //如果没有该事件
        if (!this.listeners[name]) {
            this.listeners[name] = [];
        }

        let observers: Observer[] = this.listeners[name];

        let length = observers.length;
        for (let i = 0; i < length; i++) {
            let observer = observers[i];
            if (observer.compare(target)) {
                console.warn("[EventMgr]重复添加监听,请检查事件:", name)
                return;
            }
        }
        this.listeners[name].push(new Observer(callback, target));
    }

    /**
     * 移除事件
     * @param name     事件名称
     * @param callback 回调函数
     * @param target   目标脚本（this)
     */
    public remove(name: string, callback: Function, target: any) {

        let observers: Observer[] = this.listeners[name];
        if (!observers) return;
        let length = observers.length;
        for (let i = 0; i < length; i++) {
            let observer = observers[i];
            if (observer.compare(target)) {
                observers.splice(i, 1);
                break;
            }
        }
        if (observers.length == 0) {
            delete this.listeners[name];
        }
    }

    /**
     * 发送事件
     * @param name 事件名称
     */
    public emit(name: string, ...args: any[]) {

        let observers: Observer[] = this.listeners[name];
        if (!observers) return;

        //克隆一个新数组(暂时concat代替),然后分发事件,防止那边remove之后,[0 1] 变成 [1] 然后1号位为undefined
        let tempObservers: Observer[] = observers.concat();
        let length = tempObservers.length;
        for (let i = 0; i < length; i++) {
            let observer = tempObservers[i];
            observer.notify(...args, name);
        }
        //置空释放
        tempObservers = null;
    }
}

/**事件观察者类*/
class Observer {

    /** 回调函数 */
    private callback: Function = null;
    /** 目标脚本 */
    private target: any = null;

    /** 构造函数 */
    constructor(callback: Function, target: any) {
        let self = this;
        self.callback = callback;
        self.target = target;
    }

    /**
     * 发送通知
     * @param args 不定参数
     */
    notify(...args: any[]): void {
        let self = this;
        self.callback.call(self.target, ...args);
    }

    /**
     * 脚本比较
     * @param target 绑定的对象脚本
     */
    compare(target: any): boolean {
        return target == this.target;
    }
}