import { _decorator, Component, easing, Graphics, Label, Animation, misc, Node, Tween, tween, v3, UIOpacity } from "cc";
import { Global } from "../Global";
import Svga from "../../../../Component/Svga/Svga";

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;

    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, length } = Global.stageConfig[1];

        this.goalTxt.string = `${time}秒长度达到${length}`;
        this.bannerArr[1].getChildByName("txt")
            .getComponent(Label)
            .string = `${time}秒长度达到${length}`;
        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() {
        this.topCard.active = true;
        this.top.active = false;
    }

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

    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();
        };
    })();

}
