
/**
 * @class MovieClip
 * @since 1.0.0
 * @public
 * @extends Container
 */
export class MovieClip extends egret.DisplayObjectContainer {

    /**
     * 锁步将按时间间隔来执行动画
     * 有可能捕捉不到完成事件
     */
    lockStep = false;
    /**
     * mc的当前帧,从1开始
     * @property currentFrame
     * @public
     * @since 1.0.0
     * @type {number}
     * @default 1
     * @readonly
     */
    get currentFrame() {
        return this._curFrame;
    }

    /**
     * @property _curFrame
     * @type {number}
     * @private
     * @since 2.0.0
     * @default 1
     */
    _curFrame = 1;

    /**
     * 当前动画是否处于播放状态
     * @property isPlaying
     * @readOnly
     * @public
     * @since 1.0.0
     * @type {boolean}
     * @default true
     * @readonly
     */
    get isPlaying() {
        return this._isPlaying;
    }

    /**
     * @property _isPlaying
     * @type {boolean}
     * @private
     * @since 2.0.0
     * @default true
     */
    _isPlaying = true;

    /**
     * 动画的播放方向,是顺着播还是在倒着播
     * @property isFront
     * @public
     * @since 1.0.0
     * @type {boolean}
     * @default true
     * @readonly
     */
    get isFront() {
        return this._isFront;
    }

    /**
     * @property _isFront
     * @type {boolean}
     * @private
     * @default true
     */
    _isFront = true;

    /**
     * 当前动画的总帧数
     * @property totalFrames
     * @public
     * @since 1.0.0
     * @type {number}
     * @default 1
     * @readonly
     */
    totalFrames;

    loops = 0;
    /**
     * 所有textures缓存
     */
    textures = {};

    /**
     * 锁步的时间间隔，按fps定,毫秒
     */
    timeInterval;

    /**
     * 前提引擎按60设置
     */
    deltaFrame;
    /**
     * 中间帧计时
     */
    frameCount = 0;
    /**
     * 构造函数
     * @method MovieClip
     * @public
     * @since 1.0.0
     */
    constructor(mv) {
        super();
        let s = this;
        //初始化
        if (mv) {
            s.init(mv);
        } else {
            s.totalFrames = 0;
        }
    }

    /**
     * 可以手动用init，
     * @param mv 
     */
    init(mv) {
        //记录基本信息，fps，每秒输出帧数，frames，总帧数，videoSize暂时不管
        //如果fps小于60怎么处理。update时怎么处理
        this.timeInterval = 1000 / mv.FPS;
        this.startTime = Date.now();
        this.startFrame = 1;
        this.totalFrames = mv.frames
        //间隔帧数，
        this.deltaFrame = 60 / mv.FPS;
        this.frameCount = this.deltaFrame;
        this._curFrame = 1;

        const images = mv.images;
        for (let key in images) {
            let imgTag = images[key];
            var bitmapData = new egret.BitmapData(imgTag);
            var texture = new egret.Texture();
            texture.bitmapData = bitmapData;
            this.textures[key] = texture;
        }
        this.initChildren(mv.sprites);
        //到时找替代的方法，用这个去循环好像，移除了还在执行
        this.addEventListener(egret.Event.ENTER_FRAME, function () {
            if (!this.stage) return
            this.updateFrame()
        }, this)
    }

    initChildren(sprites) {
        for (var i = 0, len = sprites.length; i < len; i++) {
            var ele = sprites[i];
            if (ele.imageKey) {
                var child
                var splitArr = ele.imageKey.split("_");
                //需要标记的,预留其他类型
                if (splitArr[1] && splitArr[1] == "spr") {
                    child = new egret.Bitmap(this.textures[ele.imageKey]);
                    this[splitArr[0]] = child;
                }
                //一般不需要标记的
                else {
                    child = new egret.Bitmap(this.textures[ele.imageKey]);
                }
                //透明度处理
                if (ele.frames[0].alpha < 0.05) {
                    child.visible = false;
                } else {
                    child.alpha = ele.frames[0].alpha;
                }
                child["frames"] = ele.frames;
                var transform = ele.frames[0].transform
                child.matrix = new egret.Matrix().copyFrom(transform);
                // child.x = 0;
                // child.y = 0;
                this.addChild(child)

            }
        }
        // console.log(this)
    }

    /**
     * 调用止方法将停止当前帧
     * @method stop
     * @public
     * @since 1.0.0
     */
    stop() {
        let s = this;
        s._isPlaying = false;
    }

    /**
     * 将播放头向后移一帧并停在下一帧,如果本身在最后一帧则不做任何反应
     * @method nextFrame
     * @since 1.0.0
     * @public
     */
    nextFrame() {
        let s = this;
        if (s._curFrame < s.totalFrames) {
            s._curFrame++;
        }
        s._isPlaying = false;
    }

    /**
     * 将播放头向前移一帧并停在下一帧,如果本身在第一帧则不做任何反应
     * @method prevFrame
     * @since 1.0.0
     * @public
     */
    prevFrame() {
        let s = this;
        if (s._curFrame > 1) {
            s._curFrame--;
        }
        s._isPlaying = false;
    }

    /**
     * 将播放头跳转到指定帧并停在那一帧,如果本身在第一帧则不做任何反应
     * @method gotoAndStop
     * @public
     * @since 1.0.0
     * @param {number} frameIndex 批定帧的帧数或指定帧的标签名
     */
    gotoAndStop(frameIndex) {
        let s = this;
        s._isPlaying = false;
        if (frameIndex > s.totalFrames) {
            frameIndex = s.totalFrames;
        }
        if (frameIndex < 1) {
            frameIndex = 1;
        }
        s._curFrame = Math.round(frameIndex);
    }

    /**
     * 如果当前时间轴停在某一帧,调用此方法将继续播放.
     * @method play
     * @public
     * @since 1.0.0
     */
    play(isFront) {
        let s = this;
        s.frameCount = s.deltaFrame;
        s.startTime = Date.now();
        s.startFrame = s._curFrame;
        s._isPlaying = true;
        s._isFront = isFront === undefined ? true : isFront;
    }

    /**
     * @property _lastFrame
     * @type {number}
     * @private
     * @default 0
     */
    _lastFrame = 0;

    /**
     * 刚执行到的帧数，用于帧监听时判断用
     * 不是60fps的videoItem的中间有几帧curFrame会不变，判断只执行一次监听时会出错，刚好动画满帧60fps时就无所谓
     */
    get isInTimeFrame() {
        //相等时就是刚开始的curFrame
        return this.frameCount == this.deltaFrame;
    }


    /**
     * 将播放头跳转到指定帧并从那一帧开始继续播放
     * @method gotoAndPlay
     * @public
     * @since 1.0.0
     * @param {number} frameIndex 批定帧的帧数或指定帧的标签名
     * @param {boolean} isFront 跳到指定帧后是向前播放, 还是向后播放.不设置些参数将默认向前播放
     */
    gotoAndPlay(frameIndex, isFront = true) {
        let s = this;
        s._isFront = isFront === undefined ? true : isFront;
        s._isPlaying = true;
        if (frameIndex > s.totalFrames) {
            frameIndex = s.totalFrames;
        }
        if (frameIndex < 1) {
            frameIndex = 1;
        }
        s.frameCount = s.deltaFrame;
        s.startTime = Date.now();
        s._curFrame = frameIndex;
        s.startFrame = s._curFrame;
    }

    /**
     * 播放范围动画，
     * @param beginFrame 开始帧
     * @param endFrame 结束帧
     * @param loops 默认一次
     * @param callback 
     */
    startAniRange(
        beginFrame,
        endFrame,
        loops,
        callback
    ) {
        beginFrame = beginFrame || 1;
        endFrame = endFrame || this.totalFrames;
        loops = loops || 1;
        if (beginFrame < 1) {
            beginFrame = 1;
        }
        if (beginFrame > this.totalFrames) {
            beginFrame = this.totalFrames;
        }
        if (endFrame < 1) {
            endFrame = 1;
        }
        if (endFrame > this.totalFrames) {
            endFrame = this.totalFrames;
        }
        if (beginFrame === endFrame) {
            this.gotoAndStop(beginFrame)
            //如果相等
            return
        } else if (beginFrame < endFrame) {
            this._isFront = true;

        } else {
            this._isFront = false;
            var temp = beginFrame;
            beginFrame = endFrame;
            endFrame = temp;
        }
        this._curFrame = beginFrame;
        //赋值count最大
        this.frameCount = this.deltaFrame;
        this.startTime = Date.now();
        this.startFrame = this._curFrame;
        this._isPlaying = true;
        let func;
        let loopCount = loops > 0 ? (loops + 0.5 >> 0) : Infinity;
        this.addEventListener(egret.Event.ENTER_FRAME, func = function (e) {
            if (!this.stage) return;
            if (e.target._isFront) {
                //多判断个锁步的时候怎么算loopCount-- 到时实在不行就定时器
                if (e.target.currentFrame >= endFrame || e.target._endMark) {
                    loopCount--
                    if (loopCount <= 0) {
                        e.target.gotoAndStop(endFrame);
                        e.target.removeEventListener(egret.Event.ENTER_FRAME, func, this);
                        callback && callback();
                    } else {
                        e.target.gotoAndPlay(beginFrame)
                    }
                }
            } else {
                if (e.target.currentFrame <= beginFrame || e.target._endMark) {
                    loopCount--
                    if (loopCount <= 0) {
                        e.target.gotoAndStop(beginFrame);
                        e.target.removeEventListener(egret.Event.ENTER_FRAME, func, this);
                        callback && callback();
                    } else {
                        e.target.gotoAndPlay(endFrame, false);
                    }
                }
            }
        }, this)

    }

    /**
    * 开始时间，每次有play的时候就需要
    * 锁步思想，设置开始时间，后面每帧实际时间与开始时间相减，加上开始帧数，得到当前帧数
    *
    */
    startTime;
    /**
    * 开始时的frame（锁步时用）
    */
    startFrame;

    /**
    * 上一次的DeltaFrame（锁步时用）
    */
    lastDeltaFrame

    commonDeltaTime = 1000 / 60;
    updateFrame() {
        var s = this;
        //1帧的时候也有相应的frameCount，无用，return
        if (s.totalFrames == 0 || s.totalFrames == 1) return;
        let isNeedUpdate = false;
        if (s._lastFrame != s._curFrame) {
            //帧不相等
            isNeedUpdate = true;
            s._lastFrame = s._curFrame;

            s.startTime = Date.now();
            s.startFrame = s._curFrame;

            //锁步的时候
            s._endMark = false;
        } else {
            if (s._isPlaying) {
                if (s.lockStep) {
                    isNeedUpdate = s.getCurFrameWhenLockStep();
                } else {
                    if (--s.frameCount == 0) {
                        s.frameCount = s.deltaFrame;
                        isNeedUpdate = true;
                        if (s._isFront) {
                            s._curFrame++;
                            if (s._curFrame > s.totalFrames) {
                                s._curFrame = 1;
                            }
                        } else {
                            s._curFrame--;
                            if (s._curFrame < 1) {
                                s._curFrame = s.totalFrames;
                            }
                        }
                        s._lastFrame = s._curFrame;
                    }
                }
            }
        }
        //如果需要更新
        if (isNeedUpdate) {
            //对每个child还原对应的transform，alpha为0的默认visible设为false,避免计算
            for (var i = 0, len = s.$children.length; i < len; i++) {
                var child = s.$children[i]
                //只修改动画加入的child，不修改手动加入的，,所以想要修改动画中的元素属性，直接去掉frames属性，将不会执行动画
                if (child["frames"] && child["frames"][s._curFrame - 1]) {
                    var frame = child["frames"][s._curFrame - 1];
                    //layout不晓得干嘛用，暂不管
                    if (frame.alpha < 0.05) {
                        child.visible = false;
                    } else {
                        child.visible = true;
                        child.alpha = frame.alpha;
                        //先判断transform是否相等
                        if (!child.matrix.equals(frame.transform)) {
                            child.matrix = new egret.Matrix().copyFrom(frame.transform);
                        }
                    }
                }
            }
            //事件播放结束监听,不确定白鹭是否是COMPLETE，待试验
            if (!s.lockStep) {
                if (((s._curFrame == 1 && !s._isFront) || (s._curFrame == s.totalFrames && s._isFront)) && s.hasEventListener(egret.Event.COMPLETE)) {
                    s.dispatchEvent(new egret.Event(egret.Event.COMPLETE));
                }
            } else {
                //锁步的时候另外判断
                if (s._endMark && s.hasEventListener(egret.Event.COMPLETE)) {
                    s.dispatchEvent(new egret.Event(egret.Event.COMPLETE));
                }
            }
        }

    }

    getCurFrameWhenLockStep() {
        var dateNow = Date.now()
        //相差
        var deltaFrame = ((dateNow - this.startTime) / this.timeInterval) >> 0;
        //间隔帧数与上一帧一致
        if (deltaFrame == this.lastDeltaFrame) {
            //设置不等
            this.frameCount = 0;
            return false
        }
        this._endMark = false;
        //相等，刚好执行切换
        this.frameCount = this.deltaFrame;
        this.lastDeltaFrame = deltaFrame
        if (this._isFront) {
            //取余数
            this._curFrame = (this.startFrame + deltaFrame) % this.totalFrames;
            if (this._curFrame == 0) {
                this._curFrame = this.totalFrames;
                this._endMark = true;
            }
            //当上一帧大于_curFrame,并且上一帧不是totalFrames时，说明跳过了最后一帧
            else if (this._lastFrame > this._curFrame &&
                this._lastFrame != this.totalFrames) {
                this._endMark = true;
            }
        } else {
            this._curFrame = (this.startFrame - deltaFrame) % this.totalFrames;
            if (this._curFrame == 0) {
                this._curFrame = this.totalFrames;
            } else if (this._curFrame < 0) {
                this._curFrame += this.totalFrames;
            }
            if (this._curFrame == 1) {
                this._endMark = true;
            }
            //当上一帧小于_curFrame,并且上一帧不是1时，说明跳过了第一帧
            else if (this._lastFrame < this._curFrame &&
                this._lastFrame != 1) {
                this._endMark = true;
            }
        }
        this._lastFrame = this._curFrame;
        return true
    }
}
