import ComponentBase from "../Components/ComponentBase";
import SpTimer from "../Game/SpTimer";

function setPropertyDecorator(target: ComponentBase, name: string, callback: (context: ComponentBase) => void) {
    if (!target["decoratorCallback"]) {
        target["decoratorCallback"] = {};
    }
    target["decoratorCallback"]["LightRotate_" + name] = callback;
}


export namespace Decorator {

    /**
     * 
     * @param period 周期 单位：毫秒
     */
    export function LightRotate(period: number) {
        return function (target: ComponentBase, name: string) {
            setPropertyDecorator(target, name, (context: ComponentBase) => {
                let callback = () => {
                    egret.Tween.get(context[name]).to({ rotation: 360 }, period).call(callback);
                }
                callback();
                // context[name]["alpha"] = 0;
                // egret.Tween.get(context[name]).wait(250).to({ alpha: 1 }, 200).call(callback);
            });
        }
    }

    export interface IDefaultCallback {
        onUpdate?(deltaTime?: number): void;
        onLoad?(): void;
        onDestroy?(): void;
    }
    export function DefaultCallback<T extends { new(...arg: any[]): {} }>(target: T) {
        return class extends target {
            constructor(...arg: any[]) {
                super();
                this["onUpdate"] = this["onUpdate"] || (() => { });
                this["onLoad"] = this["onLoad"] || (() => { });

                let onUpdateCallback = () => this["onUpdate"](SpTimer.deltaTime);
                this["addEventListener"](egret.Event.ENTER_FRAME, onUpdateCallback, this);
                this["addEventListener"](egret.Event.ADDED_TO_STAGE, this["onLoad"], this);
                this["addEventListener"](egret.Event.REMOVED_FROM_STAGE, () => {
                    this["removeEventListener"](egret.Event.ENTER_FRAME, onUpdateCallback, this);
                    this["removeEventListener"](egret.Event.ADDED_TO_STAGE, this["onLoad"], this)
                    this["onDestroy"] && this["onDestroy"]();
                }, this);
            }
        }
    }

    export function OnLoad<T extends { new(...arg: any[]): {} }>(target: T) {
        return class extends target {
            constructor(...arg: any[]) {
                super(...arg);
                this["onLoad"] = this["onLoad"] || (() => { });
                this["addEventListener"](egret.Event.ADDED_TO_STAGE, this["onLoad"], this);
            }
        }
    }

    export function OnDestroy<T extends { new(...arg: any[]): {} }>(target: T) {
        return class extends target {
            constructor(...arg: any[]) {
                super(...arg);

                this["addEventListener"](egret.Event.REMOVED_FROM_STAGE, () => {
                    this["onDestroy"] && this["onDestroy"]();
                }, this);
            }
        }
    }

    export function OnUpdate<T extends { new(...arg: any[]): {} }>(target: T) {
        return class extends target {
            constructor(...arg: any[]) {
                super(...arg);
                this["onUpdate"] = this["onUpdate"] || (() => { });
                let onUpdateCallback = () => this["onUpdate"](SpTimer.deltaTime);
                this["addEventListener"](egret.Event.ENTER_FRAME, onUpdateCallback, this);

                this["addEventListener"](egret.Event.REMOVED_FROM_STAGE, () => {
                    this["removeEventListener"](egret.Event.ENTER_FRAME, onUpdateCallback, this);
                }, this);
            }
        }
    }

    export function ClassName(className: string) {
        return function (constructor: Function) {
            constructor.prototype["className"] = className;
        }
    }


    export interface ISkin {
        onSkinComplete?(): void;
        preLoad?(): Promise<void>;
    }
    export function Skin(name: string) {
        return function <T extends { new(...arg: any[]): {} }>(target: T) {
            return class extends target {
                constructor(...arg: any[]) {
                    super(...arg);
                    let setSkin = () => {
                        this["skinName"] = `resource/skins/${name}Skin.exml`;
                        if (this["skin"]) {
                            this["onSkinComplete"] && this["onSkinComplete"]();
                        } else {
                            this["addEventListener"](eui.UIEvent.COMPLETE, this["onSkinComplete"] || (() => { }), this);
                        }
                    }

                    new Promise(async resolve => {
                        //把skinKey转换为groupName
                        let isFirst = true;
                        let result: string[] = [];
                        for (let char of name) {
                            if (char.isUpperCase()) {
                                if (isFirst) {
                                    isFirst = false;
                                } else {
                                    result.push("_");
                                }
                            }
                            result.push(char.toLowerCase());
                        }

                        await RES.loadGroup(result.join(""));

                        if (this["preLoad"]) {
                            this["preLoad"]().then(() => resolve());
                        } else
                            resolve();
                    }).then(setSkin);
                }
            }
        }
    }

}