import { _decorator, Component, easing, Graphics, Label, Animation, misc, Node, Tween, tween, v3, UIOpacity, Prefab, instantiate, Layout, AnimationClip } from "cc";
import { Global } from "../Global";
import Svga from "../../../../Component/Svga/Svga";
import { ECard, EPropType, ESporpType } from "../Common/Enums";
import { progress } from "./progress";
import { AudioMgr } from "db://assets/core_tgx/base/AudioMgr";

const { ccclass, property, executeInEditMode } = _decorator;

@ccclass("Target")
@executeInEditMode()
export class Target extends Component {

    private static _ins: Target = null;
    static get ins() {
        return this._ins;
    }

    @property(Graphics) graphics: Graphics = null;

    @property(Label) cdTxt: Label = null;

    @property(Label) goalTxt: Label = null;

    @property(Node) cdFlicker: Node = null;

    @property(Node) mask: Node = null;

    @property(Node) svga: Node = null;

    @property(Node) bannerBg: Node = null;

    @property(Node) banner: Node = null;

    @property([Node]) bannerArr: Node[] = [];

    @property(Node) top: Node = null;


    /**顶部合成卡 */
    @property(Node) topCard: Node = null;

    @property(Node) topCardList: Node = null;

    @property(Prefab) cardAPrefab: Prefab = null;

    @property(Prefab) cardBPrefab: Prefab = null;

    @property(Prefab) cardCPrefab: Prefab = null;

    @property(Node) composeAni: Node = null;

    @property(Node) getTextNode: Node = null;

    @property(Label) getTxt: Label = null;
    /**顶部合成卡 */


    /**道具倒计时 */

    @property(Node) proConLayout: Node = null;

    @property(Prefab) progressPrefab: Prefab = null;

    progressObj = {}
    timerObj = { pro: 0 }

    /**道具倒计时 */


    constructor() {
        super();
        Target._ins = this;
    }

    protected onLoad() {
        this.node.active = true;

        this.bannerArr.forEach((banner) => {
            banner.active = false;
        });
        this.cdFlicker.active = false;

    }

    onDestroy() {
        if (Target._ins == this) {
            Target._ins = null;
        }
    }

    start() {
    }

    async showBanner(bannerNode: Node) {
        await new Promise<void>((resolve) => {
            bannerNode.active = true;
            this.bannerBg.active = false;
            this.banner.active = true;
            this.mask.active = true;
            this.svga.active = true;
            this.svga.getComponent(Svga).play();

            const bannerOpacity = this.banner.getComponent(UIOpacity);
            bannerOpacity.opacity = 0;
            tween(bannerOpacity)
                .to(0.466, { opacity: 255 })
                .call(() => {
                    this.svga.active = false;
                    this.bannerBg.active = true;
                })
                .start();

            tween(this.banner)
                .delay(2.666)
                .to(0.666, {
                    position: v3(0, 345, 0),
                    scale: v3(0.15, 0.15, 1)
                }, { easing: easing.quadInOut })
                .delay(0.1)
                .call(() => {
                    this.banner.active = false;
                    this.mask.active = false;
                    this.svga.active = false;
                    bannerNode.active = false;
                    resolve();
                })
                .start();
        });
    }

    async showTarget3() {
        this.showTopCard()
        await this.showBanner(this.bannerArr[2]);
    }

    async showTarget2() {
        this.showTop()
        const { time, energy } = Global.stageConfig[1];

        this.goalTxt.string = `${time}秒长度达到${energy}`;
        this.bannerArr[1].getChildByName("txt")
            .getComponent(Label)
            .string = `${time}秒长度达到${energy}`;
        await this.showBanner(this.bannerArr[1]);
    }

    async showTarget1() {
        this.showTop()
        const { time } = Global.stageConfig[0];
        this.goalTxt.string = `存活${time}秒`;
        this.bannerArr[0].getChildByName("txt")
            .getComponent(Label)
            .string = `存活${time}秒`;
        await this.showBanner(this.bannerArr[0]);
    }

    showTopCard() {
        if (!this.topCard.active) {
            this.topCard.active = true;
            this.top.active = false;
        }
    }

    showTop() {
        if (!this.top.active) {
            this.top.active = true;
            this.topCard.active = false
        }
    }

    updateCard(cardType: ECard) {
        this.showTopCard()
        let card = null
        switch (cardType) {
            case EPropType.CARD_A:
                card = instantiate(this.cardAPrefab)
                break;
            case EPropType.CARD_B:
                card = instantiate(this.cardBPrefab)
                break;
            case EPropType.CARD_C:
                card = instantiate(this.cardCPrefab)
                break;
        }
        this.topCardList.addChild(card)
    }

    composeCard(txt) {
        
        return new Promise(r => {
            AudioMgr.ins.playOneShot("audio/零食卡合成音效");
            let tweenDuration: number = .5;
            tween(this.topCardList.getComponent(Layout)).to(
                tweenDuration,
                { spacingX: -32 }, { easing: 'smooth' }
            ).call(() => {
                this.composeAni.active = true
                this.composeAni.getComponent(Animation).play()
                this.scheduleOnce(() => {
                    this.composeAni.active = false
                    this.topCardList.removeAllChildren()
                    this.topCardList.getComponent(Layout).spacingX = 32
                    this.getTextNode.active = true
                    this.getTxt.string = txt
                    this.scheduleOnce(() => {
                        this.getTextNode.active = false
                        r(1)
                    }, .5)
                }, .2)
            }).start();
        })


        // this.topCardList.addChild()
    }



    updateProgress(type: ESporpType, pro: number, leftTime: number) {
        // MAGNET, // 磁铁 黄色 5
        // SPEED,  // 加速 蓝色 6
        // SHIELD, // 护盾 绿色 7
        // DOUBLE_EXP, // 双倍经验 黄色 9

        let type2type = {
            [EPropType.MAGNET]: 0,
            [EPropType.SPEED]: 1,
            [EPropType.SHIELD]: 2,
            [EPropType.DOUBLE_EXP]: 3
        }

        let progressItem = this.progressObj[type]
        if (!progressItem) {
            progressItem = instantiate(this.progressPrefab)
            progressItem.getComponent(progress).changeSpFrame(type2type[type])
            this.proConLayout.insertChild(progressItem, 0)
            this.progressObj[type] = progressItem
        }

        if (pro <= 0) {
            /**先直接移除 */
            progressItem.removeFromParent()
            this.progressObj[type] = null
            return
        }

        (progressItem.getComponent(progress) as progress).leftTime = leftTime;
        (progressItem.getComponent(progress) as progress).changePro(pro)




    }




    private _cd = 0;

    get cd() {
        return this._cd;
    }

    set cd(val) {
        this._cd = val;
        this.cdTxt.string = `${~~this.cd}`;
        this.drawProcess(this.cd / this.totalCd);

        if (!this.cdFlicker.active && val <= 5) {
            this.cdFlicker.active = true;
            this.cdFlicker.getComponent(Animation).play();
        }

    }

    totalCd = 0;

    cdTween: Tween<Target> = null;

    startCd(cd: number, onComplete = () => { }) {
        this.graphics.node.active = true;
        this.cd = this.totalCd = cd;
        this.cdTween = tween(this as Target)
            .to(cd, { cd: 0 }, {
                // onUpdate: (target: Target, ratio: number) => {
                //     this.drawProcess(1 - (this.cd / this.totalCd));
                //     this.cdTxt.string = `${~~this.cd}`;
                // },
                onComplete: () => {
                    this.cdTxt.string = `0`;
                    this.graphics.node.active = false;
                    this.cdFlicker.active = false;
                    this.cdFlicker.getComponent(Animation).stop();
                    onComplete();
                }
            })
            .start();
    }

    pauseCd() {
        if (!this.cdTween) return;
        this.cdTween.stop();
    }

    resetCd() {
        if (!this.cdTween) return;
        this.cdTween.start();
    }


    drawProcess = (() => {
        const phases = [
            51,
            Math.PI / 2 * 10,
            220,
            Math.PI / 2 * 10,
            51,
        ];

        const totalLength = phases.reduce((a, b, i) => a + b, 0);

        // Tip: 注意此时phases的结果

        return (process: number) => {
            // Ensure process is between 0 and 1
            process = misc.clampf(process, 0, 1);

            this.graphics.clear();

            const targetLength = totalLength * process;
            let currentLength = 0;

            this.graphics.moveTo(120, 0);

            // Draw vertical line on right
            const rightVertical = Math.min(51, targetLength - currentLength);
            if (rightVertical > 0) {
                this.graphics.lineTo(120, -rightVertical);
                currentLength += rightVertical;
                if (currentLength >= targetLength) {
                    this.graphics.stroke();
                    return;
                }
            }

            // Draw right arc
            const rightArcLength = Math.PI * 10 / 2;
            if (targetLength > currentLength) {
                const rightArcAngle = Math.min((targetLength - currentLength) / 10, Math.PI / 2);
                this.graphics.arc(110, -51, 10, 0, -rightArcAngle, false);
                currentLength += rightArcLength;
                if (currentLength >= targetLength) {
                    this.graphics.stroke();
                    return;
                }
            }

            // Draw horizontal line
            const horizontalLength = Math.min(220, targetLength - currentLength);
            if (horizontalLength > 0) {
                this.graphics.lineTo(-110 + (220 - horizontalLength), -61);
                currentLength += horizontalLength;
                if (currentLength >= targetLength) {
                    this.graphics.stroke();
                    return;
                }
            }

            // Draw left arc
            const leftArcLength = Math.PI * 10 / 2;
            if (targetLength > currentLength) {
                const leftArcAngle = Math.min((targetLength - currentLength) / 10, Math.PI / 2);
                this.graphics.arc(-110, -51, 10, -Math.PI / 2, -Math.PI / 2 - leftArcAngle, false);
                currentLength += leftArcLength;
                if (currentLength >= targetLength) {
                    this.graphics.stroke();
                    return;
                }
            }

            // Draw vertical line on left
            const leftVertical = Math.min(51, targetLength - currentLength);
            if (leftVertical > 0) {
                this.graphics.lineTo(-120, -51 + leftVertical);
            }

            this.graphics.stroke();
        };
    })();

}
