import { _decorator, Asset, Component, Sprite, SpriteFrame, Texture2D, } from "cc";

const {ccclass, property, requireComponent} = _decorator;
import menu = _decorator.menu;
import disallowMultiple = _decorator.disallowMultiple;
import executeInEditMode = _decorator.executeInEditMode;
import playOnFocus = _decorator.playOnFocus;

const wran = "⚠️实验组件，性能很差，不建议使用";

@ccclass("SvgaOffScreen")
@executeInEditMode
@disallowMultiple
@playOnFocus
@requireComponent(Sprite)
@menu('自定义组件/Svga离屏渲染器(⚠️实验)(⚠️性能很差)')
export default class SvgaOffScreen extends Component {

    @property({tooltip: wran, displayName: wran})
    tips: boolean = true;
    isPlaying: boolean = false;
    canvas: HTMLCanvasElement = null;
    sf: SpriteFrame;
    player: SVGA.Player;
    /************************ on Editor ************************/
    private edit_update: boolean = false;

    /************************ on Editor ************************/
    // 初始化就播放
    @property({tooltip: "是否自动播放"})
    private autoPlay: boolean = true;

    /************************  ************************/

    @property(Asset)
    private _svga: Asset = null;

    @property(Asset)
    get svga() {
        return this._svga;
    }

    set svga(svga) {
        this._svga = svga;
        this.mount();
    }

    // 是否循环
    @property
    private _loop: boolean = false;

    @property({tooltip: "是否循环"})
    get loop() {
        return this._loop;
    }

    set loop(loop) {
        this._loop = loop;
        this.player.config.loop = loop ? 0 : 1;
        this.player.animator.loop = loop ? Infinity : 1;
        CC_EDITOR && this.play();
    }

    // 总时间，秒计
    get totalTime(): number {
        return this.player.animator?.duration / 1000;
    };

    // 总帧数
    get totalFrames() {
        return this.player.totalFrames;
    }

    // fps
    @property
    private _fps: number = 0;

    @property
    get fps() {
        return this._fps || this.player?.videoEntity?.fps || 0;
    }

    set fps(fps) {
        this._fps = fps;
        if (this.player.videoEntity) {
            this.player.videoEntity.fps = fps;
            this.player.animator.duration = this.player.videoEntity.frames * (1.0 / fps) * 1000;
        }
    }

    // 当前帧
    get curFrame() {
        return this.player.currentFrame;
    }

    set curFrame(frame) {
        this.player.currentFrame = frame;
        this.player.animator && (this.player.animator.startValue = frame);
    }

    onFocusInEditor() {
        this.edit_update = true;
        this.play(0);
    }

    onLostFocusInEditor() {
        this.edit_update = false;
    }

    async resetInEditor() {
        await this.mount();
        this.edit_update = true;
        this.play(0);
    }

    onEnable() {
        CC_EDITOR && this.play(0);
    }

    async onLoad() {

        console.warn(`[${this.name}] -> ${wran}`);

        this.canvas = document.createElement("canvas");
        ;
        this.player = new SVGA.Player({
            container: this.canvas,
            isUseIntersectionObserver: false,
            isCacheFrames: false,
            loop: this.loop ? 0 : 1,
        });

        await this.mount();

        this.sf = SpriteFrame.createWithImage(this.canvas);

        this.getComponent(Sprite).spriteFrame = this.sf;
    }

    start() {

    }

    async mount() {
        if (!this.svga) return;

        this.canvas.width = this.svga["_file"].size.width;
        this.canvas.height = this.svga["_file"].size.height;

        await this.player.mount(this.svga["_file"]);

        this.fps = this.fps;

        if (this.autoPlay) this.play(0);
    }

    update(dt) {
        (this.sf?.texture as Texture2D).updateImage();
    }

    onDestroy() {
        this.player.destroy();
    }

    play(frame = 0) {
        if (!this.player) return;
        this.player.start();

        this.curFrame = frame;
        this.isPlaying = true;
        return this;
    }

    stop(isReset: boolean = false) {
        if (!this.player) return;

        if (isReset) this.curFrame = 0;

        this.player.stop();

        this.isPlaying = false;
        return this;
    }
}

