const { ccclass, property, executeInEditMode, playOnFocus } = cc._decorator;

/**
 * 帧动画播放组件
 * ### 开放的接口;
 * #### play 播放
 * #### stop 停止播放
 * #### gotoAndPlay 跳转到某帧并播放
 * #### gotoAndStop 跳转到某帧并停止播放
 * #### isPlayEnd 是否播放结束
 * ### 开放的事件
 * #### completeTimes 单次播完完成事件
 * #### complete 全部次数完成事件
 * @author 薛鸿潇
 */
@ccclass
@executeInEditMode()
@playOnFocus()
export default class FrameAnimation extends cc.Component {

    @property({ displayName: '精灵纹理', type: cc.SpriteFrame })
    private images: cc.SpriteFrame[] = [];
    @property({ displayName: '每帧间隔' })
    private frameTime: number = 0.1;
    @property({ displayName: '播放次数' })
    private playTimes: number = 0;
    @property({ displayName: "是否倒播", tooltip: "勾选，倒着播放，不钩，顺序播放" })
    private reverse: boolean = false;
    @property({ displayName: '自动播放' })
    private autoPlayOnLoad: boolean = true;
    @property({ displayName: "自动销毁", tooltip: '播完自动销毁' })
    private autoDestroy: boolean = false;
    @property({ displayName: "每帧回调", type: cc.Component.EventHandler })
    onFrameCall: cc.Component.EventHandler = new cc.Component.EventHandler();
    @property({ displayName: "结束回调", type: cc.Component.EventHandler })
    onCompleteCall: cc.Component.EventHandler = new cc.Component.EventHandler();
    /** 编辑器预览 */
    private _edit_play: boolean = false;
    @property({ displayName: '编辑器预览' })
    get edit_play(): boolean {
        if (this._edit_play && !this.edit_playing) {
            this.edit_playing = true;
            this.play();
        }
        this.running = this._edit_play;
        return this._edit_play;
    }
    set edit_play(v: boolean) {
        this._edit_play = v;
    }
    /** 编辑器是否正在播放 */
    private edit_playing = false;

    /** 动画帧数量 */
    public frameNum: number = 0;
    /** 当前帧下标 */
    public frameIndex: number = 0;
    /** 下一帧下标 */
    public nextFrameIndex: number = 0;
    /** 是否允许播放 */
    public running: boolean = true;
    /** 精灵组件 */
    private comp_spr: cc.Sprite;
    /** 播放下一帧的倒计时 */
    private time: number = 0;
    /** 每完成一轮的回调 */
    public completeTimesCallback: Function;
    /** 全部播完回调 */
    public completeCallback: Function;
    /** 每帧回调 */
    public frameCallback: Function;
    /** 当前轮播次数 */
    private currentTimes: number = 0;

    onLoad() {
        this.comp_spr = this.getComponent(cc.Sprite);
    }

    start() {
        if (this.images.length != 0) {
            this.frameNum = this.images.length;
        }

        if (this.reverse) {
            this.frameIndex = this.frameNum - 1;
            this.nextFrameIndex = this.frameNum - 1;
        }
        if (CC_EDITOR) {
            this.running = this.edit_playing;
        } else {
            this.running = this.autoPlayOnLoad;
        }

    }
    
    update(dt) {

        if (!this.running) return;
        if (this.images.length == 0) return;
        if (this.playTimes != 0 && this.currentTimes > this.playTimes) {
            this.running = false;
            return;
        }

        this.time -= dt;
        if (this.time <= 0) {
            this.time = this.frameTime;
            if (!this.reverse) {
                this.frameIndex = this.nextFrameIndex % this.frameNum;
                this.nextFrameIndex = this.frameIndex + 1;
            } else {
                this.frameIndex = (this.nextFrameIndex + this.frameNum) % this.frameNum;
                this.nextFrameIndex = this.frameIndex - 1;
            }
            this.playing();
            if (this.frameIndex == 0) {
                this.playEnd();
            }
        }
    }

    /** 播放中 */
    private playing() {
        this.comp_spr.spriteFrame = this.images[this.frameIndex];

        if (this.comp_spr.spriteFrame) {
            var rect: cc.Rect = this.comp_spr.spriteFrame.getRect();
            this.node.width = rect.width;
            this.node.height = rect.height;
        }
        // 事件回调
        this.onFrameCall.emit([]);
        if (this.frameCallback != null) {
            this.frameCallback(this.frameIndex);
        }
    }

    /** 播放结束 */
    private playEnd() {
        this.currentTimes++;

        // 完成一次
        this.node.emit("completeTimes", this.currentTimes);
        if (this.completeTimesCallback != null) {
            this.completeTimesCallback(this.currentTimes);
        }

        // 全部完成
        if (this.playTimes != 0 && this.currentTimes > this.playTimes) {
            // 事件回调
            this.node.emit("complete");
            this.onCompleteCall.emit([]);
            if (this.completeCallback != null) {
                this.completeCallback();
            }

            if (this.autoDestroy && !CC_EDITOR) {
                this.node.destroy();
            }
            // this.edit_play = false;
            this._edit_play = false;
            this.edit_playing = false;
        }
    }

    /**
     * 开始播放
     * @param frameCallback 
     * @param completeCallback 
     */
    public play(frameCallback: Function = null, completeCallback: Function = null) {

        this.frameCallback = frameCallback;
        this.completeCallback = completeCallback;

        this.running = true;
        this.frameIndex = 0;
        this.currentTimes = 0;

        this.time = this.frameTime;

        if (this.images.length != 0) {
            this.frameNum = this.images.length;

            if (this.reverse) {
                this.frameIndex = this.frameNum - 1;
                this.nextFrameIndex = this.frameNum - 1;
            }

        }

        if (!this.comp_spr) {
            this.comp_spr = this.getComponent(cc.Sprite);
        }

        if (this.comp_spr)
            this.comp_spr.spriteFrame = this.images[0];


        if (this.comp_spr.spriteFrame) {
            var rect: cc.Rect = this.comp_spr.spriteFrame.getRect();
            this.node.width = rect.width;
            this.node.height = rect.height;
        }

    }

    /**
     * 跳转到某帧并开始播放
     * @param frameIndex 帧下标
     */
    public gotoAndPlay(frameIndex: number) {
        if (!this.comp_spr) {
            this.comp_spr = this.getComponent(cc.Sprite);
        }

        this.running = true;
        this.frameIndex = frameIndex;
        this.nextFrameIndex = frameIndex;
        this.currentTimes = 0;
    }

    /** 停止 */
    public stop() {
        this.running = false;
    }

    /**
     * 跳转到某帧并停止播放
     * @param frameIndex 帧下标
     */
    public gotoAndStop(frameIndex: number) {
        this.frameIndex = frameIndex;

        if (this.frameIndex < 0)
            this.frameIndex = 0;

        if (this.frameIndex > this.images.length - 1)
            this.frameIndex = this.images.length - 1;

        if (!this.comp_spr) {
            this.comp_spr = this.getComponent(cc.Sprite);
        }

        this.comp_spr.spriteFrame = this.images[this.frameIndex];

        if (this.comp_spr.spriteFrame) {
            var rect: cc.Rect = this.comp_spr.spriteFrame.getRect();
            this.node.width = rect.width;
            this.node.height = rect.height;
        }

        this.running = false;
    }
    
    /**
     * 是否播放结束
     * @returns 
     */
    public isPlayEnd(): boolean {
        return this.frameIndex == this.frameNum;
    }
}