import { _decorator, Button, Component, EventTouch, find, native, Label, math, Node, Prefab, sp, Sprite, SpriteAtlas, Tween, tween, Vec3 } from 'cc';
import { GameRollNode } from './GameRollNode';
import { GameConstant } from './GameConstant';
import { ResourceLoader } from './ResourceLoader';
import { Player } from './Player';

const { ccclass, property } = _decorator;

@ccclass('GameScene')
export class GameScene extends Component {
    @property(Node)
    bgNode: Node = null;

    @property(Node)
    slotRectNode: Node = null;

    @property(Node)
    rollNode: Node = null;

    @property(Node)
    btnStart: Node = null;

    @property(Node)
    btnStop: Node = null;

    @property(Node)
    btnStopAuto: Node = null;

    @property(Node)
    btnBetSub: Node = null;

    @property(Node)
    btnBetAdd: Node = null;

    @property(Node)
    btnAuto: Node = null;

    @property(Node)
    autoNode: Node = null;

    @property(Node)
    betScoreNode: Node = null;

    @property(Node)
    winTitle: Node = null;
    
    @property(Node)
    winScore: Node = null;

    @property(Node)
    playerScore: Node = null;

    @property(Node)
    hintTitle: Node = null;

    @property(Node)
    freeCountNode: Node = null;

    @property(Node)
    buyFreeNode: Node = null;

    @property(Node)
    buyFreeWindow: Node = null;
    
    @property(Node)
    transitionSpine: Node = null;

    @property(Node)
    resultNode: Node = null;

    @property(Node)
    freeWindowNode: Node = null;

    public bSpecialGame = false;
    public bQuickGame = false;
    public bAutoGame = false;
    public nAutoCount = 0;
    public autoIndex = -1;
    public curBetIndex = 0;
    public isGameEnd = true;
    public gameEndData = {
        "m_desk_data": [[1,4,7,6,2,10],[9,10,9,11,12,12],[6,3,11,11,8,12],[8,9,2,10,4,6]],//[[12,11,11,8,2,12],[12,11,9,8,8,4],[8,0,5,12,10,11],[8,12,1,12,10,9]],
        "m_wildTimes_data": [[1,0,0,0,0,0],[0,0,0,0,0,0],[0,0,0,0,0,0],[0,0,0,0,0,0]],//[[0,0,0,0,0,0],[0,0,0,0,0,0],[0,0,0,0,0,0],[0,0,0,0,0,0]],
        "m_isSpecialGame": 0,
        "m_freeCount": 0,
        "m_freeCountAdd": 0,
        "m_betIndex": 0,
        "m_lottery_size": 5000,
        "m_lCurScore":0,
        "m_line_icon": [],
        "m_line_size": [],
        "m_line_icon_active": [],
        "m_line_times": [],
        "m_line_index": [],
        "totalFreeCount": 0
    }
    public gameConfig = {
        "nJetton": [100,200,300,400,500],
    }

    public winAniIdx = -1;
    public allWinScore = 0;
    public currentScore = 0;
    public lastScore = 0;
    public isPlayingScoreAddAni = false;
    public upScoreLabel = undefined;
    public bFreeState = 0;
    public freeCount = 0;
    public freeCountAdd = 0;
    public isShowTransitionSpine = false;
    public isShowReverse = false;
    public gameResults =
    {
        "results": [],
        "totalFreeCount": 0,
    };
    public gameCounts = 0;
    public filePath = "";

    private httpRetryCount: number = 0;
    private maxRetries: number = 3;
    private hasHttpResponse: boolean = false;
    
    start() {
        this.upBetAddOrDelState();
        this.changeBtnState(false);
        this.gameConfig.nJetton = Player.getInstance().betConfig;
        this.playerScore.getComponent(Label).string = GameConstant.formatNumber(Player.getInstance().score);
        this.betScoreNode.getComponent(Label).string = GameConstant.formatNumber(this.gameConfig.nJetton[this.curBetIndex]);
        this.lastScore = Player.getInstance().score;
    }

    // onClick函数块------------------------------------------------------------------------
    onClickStart() {
        this.onStartRoll();
    }

    onClickStop() {
        this.onStopRoll();
    }

    onClickSkip() {
        // this.rollNode.getComponent(GameRollNode).showPrizes();
        // this.showGameWinScore();
        // this.showFreeWindow(0, false);
        this.showTransitionSpine(this.gameCounts++ % 2, ()=>{});
    }

    onClickBetSub() {
        this.curBetIndex--;
        // this.playButtonEffect();
        this.refreshBet();
    }

    onClickBetAdd() {
        this.curBetIndex++;
        // this.playButtonEffect();
        this.refreshBet();
    }

    onClickMax() {
        this.curBetIndex = this.gameConfig.nJetton.length-1;
        // this.playButtonEffect();
        this.refreshBet();
    }

    onClickAuto() {
        this.autoNode.active = true;
    }

    onClickAutoNumber(event: EventTouch, customData: string) {
        this.autoNode.active = false;
        this.nAutoCount = GameConstant.AUTO_TYPE_COUNT[parseInt(customData)];
        this.bAutoGame = true;
        // this.showStartAndStopButton(false);
        this.onStartRoll();
    }

    onClickStopAuto() {
        this.onCancelAutoRoll();
    }

    onCancelAutoRoll() {
        this.bAutoGame = false;
        this.nAutoCount = 0;
        // if(this._gameState == GAME_FREE) {
        //     this.resetAllBtn();
        // }
        this.btnStopAuto.active = false;
    }

    onClickGameRule() {
        //
    }

    onClickBuyFree() {
        this.buyFreeWindow.active = true;
    }

    onClickBuyFreeWindowClose() {
        this.buyFreeWindow.active = false;
    }

    onClickBuyFreeWindowSure() {
        this.buyFreeWindow.active = false;
    }

    onClickResultMask() {
        // console.log("onClickResultMask this.isPlayingScoreAddAni = " + this.isPlayingScoreAddAni);
        if(this.isPlayingScoreAddAni) {
            this.skipScoreAdd(this.resultNode.getChildByName("scoreNode").getChildByName("scoreBg").getChildByName("score"));
        }else{
            // this.hideResultPanel();
        }
    }

    onClickFreeWindowMask() {
        this.freeWindowNode.active = false;
        if (this.isShowTransitionSpine) {
            this.showTransitionSpine(this.isShowReverse, ()=>{this.delayStartNextRoll(1);});
        } else {
            this.delayStartNextRoll(1);
        }
        this.isShowTransitionSpine = false;
        this.isShowReverse = false;
        Tween.stopAllByTarget(this.freeWindowNode);
    }

    onClickAutoMask() {
        this.autoNode.active = false;
    }
    // onClick函数块------------------------------------------------------------------------

    // UI刷新模块---------------------------------------------------------------------------
    refreshBet() {
        this.upBetAddOrDelState();
        let bet = this.gameConfig.nJetton[this.curBetIndex];
        this.betScoreNode.getComponent(Label).string = GameConstant.formatNumber(bet);
    }

    upBetAddOrDelState() {
        this.upBtnInteractable(this.btnBetSub, this.curBetIndex>0);
        this.upBtnInteractable(this.btnBetAdd, this.curBetIndex<this.gameConfig.nJetton.length-1);
    }

    upBtnInteractable(btn, state) {
        btn.getComponent(Button).interactable = state;
    }

    resetAllBtn() {
        if(this.bAutoGame || this.bSpecialGame) return;
        this.upBtnInteractable(this.btnStart, true);
        this.upBtnInteractable(this.btnStop, true);
        this.upBtnInteractable(this.btnAuto, true);
        // this.upBtnInteractable(this.maxBtn, true);

        this.upBetAddOrDelState();
    }

    onStartRoll() {
        if(!this.isGameEnd) return;
        Tween.stopAllByTarget(this.node);

        //是否可以开始游戏
        if(!this.judgeCannotRollGame()) {
            this.showStartAndStopButton(true);
            return;
        }

        this.isGameEnd = false;
        
        this.upLeftCount();
        this.onSendRoll();
        this.showCenterNormal();
        this.onGameStart();
        this.rollNode.getComponent(GameRollNode).startRollActions();
    }

    onStopRoll() {
        if(this.isGameEnd) {
            return;
        }

        this.rollNode.getComponent(GameRollNode).openPrizes(true, this.bQuickGame);
        this.onGameEnd();
    }

    upLeftCount() {
        if (this.bSpecialGame) {
            this.freeCount--;
            this.freeCountNode.active = true;
            this.freeCountNode.getChildByName("count").getComponent(Label).string = this.freeCount.toString();
            return;
        }
        if(!this.bAutoGame) return;
        this.nAutoCount--;
        this.bAutoGame = this.nAutoCount != 0;
        this.btnStopAuto.active = this.bAutoGame;
        let left = this.btnStopAuto.getChildByName("Label");
        left.active = true;
        if (this.nAutoCount > 0)
            left.getComponent(Label).string = this.nAutoCount.toString();
        else if (this.nAutoCount < 0)
            left.getComponent(Label).string = "∞";
    }

    showCenterNormal() {
        // console.log("enter showCenterNormal");
        if(this.bSpecialGame) return;
        this.winScore.getComponent(Label).string = "$" + '0';
        this.winScore.active = false;
        this.winTitle.active = false;

        this.hintTitle.active = true;
        this.hintTitle.getComponent(Label).string = "GOOD LUCK!";
    }

    showWinScoreTitle(score) {
        // console.log("enter showWinScoreTitle");
        this.winScore.getComponent(Label).string = GameConstant.formatNumber(score);
        this.winScore.active = true;
        this.winTitle.active = true;

        this.hintTitle.getComponent(Label).string = "GOOD LUCK!";
        this.hintTitle.active = false;
    }

    onGameStart() {
        this.upBtnInteractable(this.btnStart, false);
        this.upBtnInteractable(this.btnBetAdd, false);
        this.upBtnInteractable(this.btnBetSub, false);
        this.upBtnInteractable(this.btnAuto, false);
    }

    onGameEnd() {
        this.changeBtnState(false);
    }

    showGameEnd() {
        this.isGameEnd = true;

        //获得免费次数
        if (this.freeCountAdd > 0) {
            this.showFreeWindow(this.freeCountAdd, true);
        } else if(this.bFreeState == 1) {
            this.showFreeWindow(this.freeCount, false);
        } else if(this.winAniIdx < 0 || this.bSpecialGame){
            this.delayStartNextRoll(0.5);
        }
    }

    showGameWinScore() {
        this.winAniIdx = -1;
        //所有赢钱
        this.allWinScore += this.gameEndData.m_lottery_size;
        let score = this.gameEndData.m_lottery_size;

        console.log("showGameWinScore this.bSpecialGame = " + this.bSpecialGame + ", this.gameResults.results.length = " + this.gameResults.results.length + ", this.gameCounts = " + this.gameCounts);
        //免费游戏中
        if(this.bSpecialGame) {   
            // if(this.bFreeState) {
            //     this.playEffect("freestart");
            // }
            // let nnode = this.node.getChildByName("FuncBtnNode").getChildByName("betInfoBg").getChildByName("img_1");
            // nnode.getChildByName("normalNode").active = false;
            // nnode.getChildByName("winNode").active = true;
            this.showWinScoreTitle(this.allWinScore);
            return;
        }

        //免费游戏结束
        if(this.gameResults.results.length > 1 && this.gameCounts == 1) {
            // this.nowPlayBgm = "bgm";
            // cc.vv.audioMgr.playBGM("bgm"); 
            // this.needPlayinfScore = this.allWinScore;
            
            this.lastScore = this.currentScore + this.allWinScore;
            this.currentScore = this.lastScore;
            this.upPlayerScore(this.currentScore);
            
            this.showWinScoreTitle(this.allWinScore);
            this.showFreeWin();
            return;
        }
        this.lastScore = this.currentScore + this.allWinScore;
        let timers = Math.floor(score / this.gameConfig.nJetton[this.curBetIndex]);
        this.currentScore = this.lastScore;
        this.upPlayerScore(this.currentScore);
        
        if(score <= 0){
            return;
        }

        if (timers >= 50)
            this.winAniIdx = 3;
        else if (timers >= 35)
            this.winAniIdx = 2;
        else if (timers >= 20)
            this.winAniIdx = 1;
        else if (timers >= 5)
            this.winAniIdx = 0;
        else
            this.showWinScoreTitle(this.allWinScore);
        
        if(this.winAniIdx >= 0) {
            this.showResultPanel();
        }
    }

    hideResultPanel() {
        this.resultNode.active = false;
        let title = this.resultNode.getChildByName("scoreNode").getChildByName("title");
        Tween.stopAllByTarget(title);
        this.showWinScoreTitle(this.allWinScore);
    }

    showResultPanel() {
        this.resultNode.active = true;
        let goldAni = this.resultNode.getChildByName("goldAni");
        let title = this.resultNode.getChildByName("scoreNode").getChildByName("title");
        let winScore = this.resultNode.getChildByName("scoreNode").getChildByName("scoreBg").getChildByName("score");
        winScore.getComponent(Label).string = "$0";
        this.isPlayingScoreAddAni = true;
        // console.log("showResultPanel this.isPlayingScoreAddAni = " + this.isPlayingScoreAddAni);

        goldAni.active = this.winAniIdx > 0;
        goldAni.getComponent(sp.Skeleton).setAnimation(0, "a" + this.winAniIdx, true);
        let spriteFrameName = GameConstant.RESULT_TITLE[this.winAniIdx];
        title.getComponent(Sprite).spriteFrame = ResourceLoader.instance.getResource<SpriteAtlas>("atlas_BigWinCustom").getSpriteFrame(spriteFrameName);

        tween(title)
            .sequence(
                tween().to(0.5, {scale: new Vec3(1.2, 1.2, 1.2)}),
                tween().to(0.5, {scale: new Vec3(1, 1, 1)})
            )
            .repeatForever()
            .start()

        this.playScoreAddAni(winScore);
        // tween(this.resultNode)
        //     .delay(0.3)
        //     .call(()=>{
        //         winScore.active = true;
        //         this.playScoreAddAni(winScore);
        //     })
        //     .start()
    }

    playScoreAddAni(sLabel) {
        let start = 0;
        let bet = this.gameConfig.nJetton[this.curBetIndex];
        let endScore = this.allWinScore;
        let add = 0.01;

        Tween.stopAllByTarget(sLabel);
        this.upScoreLabel = ()=>{
            start += add;
            if(start >= endScore) {
                this.skipScoreAdd(sLabel);
            }else{
                sLabel.getComponent(Label).string = "$" + start.toFixed(2);
            }
        }

        if(this.upScoreLabel) {
            this.unschedule(this.upScoreLabel);
        } 
        this.schedule(this.upScoreLabel, 0.01);
    }

    skipScoreAdd(sLabel) {
        if(this.upScoreLabel) {
            this.unschedule(this.upScoreLabel);
        }

        let score = this.allWinScore;
        sLabel.getComponent(Label).string = GameConstant.formatNumber(score);
        tween(sLabel)
            .repeat(
                3,
                tween()
                    .to(0.2, { scale: new Vec3(1.2,1.2,1.2) })
                    .to(0.2, { scale: new Vec3(1.0,1.0,1.0) })
            )
            .call(()=>{
                this.hideResultPanel();
                this.delayStartNextRoll(1);
            })
            .start();
        
        this.isPlayingScoreAddAni = false;
        // console.log("skipScoreAdd this.isPlayingScoreAddAni = " + this.isPlayingScoreAddAni);
    }

    changeBtnState(bEnd) {
        if (this.bAutoGame) return;
        this.btnStop.active = bEnd;
        this.btnStart.active = !bEnd;
    }

    showStartAndStopButton(isShow) {
        this.btnStop.active = isShow;
        this.btnStart.active = isShow;
    }

    delayStartNextRoll(delayTime) {
        this.resetAllBtn();
        Tween.stopAllByTarget(this.node);
        tween(this.node)
            .delay(delayTime)
            .call(()=>{
                if(this.bAutoGame || this.bSpecialGame){    //自动游戏时
                    this.onStartRoll();
                }
            })
            .start()
    }

    showFreeWindow(freeCount, isAdd) {
        console.log(freeCount, isAdd);
        this.isShowTransitionSpine = !isAdd;
        this.freeWindowNode.active = true;
        this.freeWindowNode.getChildByName("bg").getChildByName("freeCountsNode").active = false;
        this.freeWindowNode.getChildByName("bg").getChildByName("freeSpins").active = true;
        let freeCountLabel = this.freeWindowNode.getChildByName("bg").getChildByName("scoreBg").getChildByName("freeCount").getComponent(Label);
        freeCountLabel.string = (isAdd ? "+" : "") + freeCount.toString();

        this.freeCountNode.active = true;
        this.freeCountNode.getChildByName("count").getComponent(Label).string = this.freeCount.toString();

        tween(this.freeWindowNode)
            .delay(2)
            .call(()=>{ this.onClickFreeWindowMask(); })
            .start();
    }

    showFreeWin() {
        this.isShowTransitionSpine = true;
        this.isShowReverse = true;
        this.freeWindowNode.active = true;
        this.freeWindowNode.getChildByName("bg").getChildByName("freeCountsNode").active = true;
        this.freeWindowNode.getChildByName("bg").getChildByName("freeSpins").active = false;
        let freeCountLabel = this.freeWindowNode.getChildByName("bg").getChildByName("scoreBg").getChildByName("freeCount").getComponent(Label);
        freeCountLabel.string = GameConstant.formatNumber(this.allWinScore);

        find("bg/freeCountsNode/freeCount", this.freeWindowNode).getComponent(Label).string = "" + this.gameResults.totalFreeCount;

        this.freeCountNode.active = false;

        tween(this.freeWindowNode)
            .delay(2)
            .call(()=>{ this.onClickFreeWindowMask(); })
            .start();
    }
    // UI刷新模块---------------------------------------------------------------------------

    judgeCannotRollGame() {
        //下注配置为空 
        if(!this.gameConfig || !this.gameConfig.nJetton || this.curBetIndex == null) {
            return false;
        }
        if(this.freeCount > 0) {
            return true;
        }
        //检测钱是否够用
        if(this.lastScore < this.gameConfig.nJetton[this.curBetIndex]) {
            // this.showLowLackMoney();
            return false;
        }
        this.currentScore = this.lastScore - this.gameConfig.nJetton[this.curBetIndex];
        this.upPlayerScore(this.currentScore);
        return true;
    }

    showTransitionSpine(isReverse, callback) {
        this.transitionSpine.active = true;
        this.transitionSpine.getComponent(sp.Skeleton).setAnimation(0, isReverse ? "transition_reverse" : "transition", false);
        this.transitionSpine.getComponent(sp.Skeleton).setCompleteListener((event)=>{
            this.transitionSpine.getComponent(sp.Skeleton).setCompleteListener(null)

            let bgFs = ResourceLoader.instance.getResource<SpriteAtlas>("bg_opaque_fs_landscape").getSpriteFrame("landscape");
            let bgNormal = ResourceLoader.instance.getResource<SpriteAtlas>("bg_opaque_normal_landscape").getSpriteFrame("bg_normal_landscape");
            let slotBgFs = ResourceLoader.instance.getResource<SpriteAtlas>("playfield_common").getSpriteFrame("playfield_frame_fs");
            let slotBgNormal = ResourceLoader.instance.getResource<SpriteAtlas>("playfield_common").getSpriteFrame("playfield_frame");
            this.bgNode.getComponent(Sprite).spriteFrame = event.animation.name == "transition" ? bgFs : bgNormal;
            this.slotRectNode.getComponent(Sprite).spriteFrame = event.animation.name == "transition" ? slotBgFs : slotBgNormal;

            callback();
            this.transitionSpine.active = false;
        });
    }

    /**
     * 发送游戏信息请求，失败会重试三次
     */
    sendHttpRequest() {
        const url = GameConstant.HTTP_HOST + "game-api/" + GameConstant.GAMEID + "/v2/spin";
        console.log("请求游戏信息:", url);

        GameConstant.httpRequest("POST", url, {cs: this.gameConfig.nJetton[this.curBetIndex], ml: 1}, false)
            .then((res: any) => {
                console.log("HTTP 回包成功:", res);
                this.hasHttpResponse = true;

                if (res.dt) {
                    if (res.dt.si) {
                        this.gameResults = res.dt.si;
                    } else {
                        this.gameResults = res.dt;
                    }
                    
                    this.gameEndData = this.gameResults.results[0];
                    this.gameCounts = this.gameResults.results.length;
                    this.onRollEndInfo(this.gameEndData);
                }
            })
            .catch((err: any) => {
                this.httpRetryCount++;
                console.error(`HTTP 请求失败 (第 ${this.httpRetryCount} 次):`, err);

                if (this.httpRetryCount < this.maxRetries) {
                    this.scheduleOnce(() => this.sendHttpRequest(), 0.5);
                } else {
                    // TODO: 弹出提示框，提示用户重试或退出游戏
                    console.error("三次重试失败，停止请求。");
                }
            });
    }

    onSendRoll() {
        if (this.gameResults.results.length > 1 && this.gameCounts > 1) {
            this.gameCounts--;
            this.gameEndData = this.gameResults.results[this.gameResults.results.length - this.gameCounts];
            this.scheduleOnce(()=>{
                this.onRollEndInfo(this.gameEndData);
            }, 0.5);
        } else {
            // spin请求
            this.sendHttpRequest();
            // this.scheduleOnce(()=>{
            //     let results = GameConstant.playRound(this.gameConfig.nJetton[this.curBetIndex]);
            //     console.log(results);
            //     this.gameResults = results;
            //     this.gameEndData = results.results[0];
            //     this.gameCounts = results.results.length;
            //     this.onRollEndInfo(this.gameEndData);
            // }, 0.5);
        }
    }

    onRollEndInfo(data) {
        if(!this.bQuickGame)
            this.changeBtnState(true);
        this.gameEndData = data;

        if(this.gameResults.results.length > 1) {
            // this.upFreeCount();
        }else{
            this.allWinScore = 0;
            this.freeCountAdd = 0;
        }
        this.bFreeState = data.m_isSpecialGame;
        this.freeCount = data.m_curTotalFreeCount;
        this.freeCountAdd = data.m_freeCountAdd
        this.bSpecialGame = data.m_curTotalFreeCount > 0;

        // 转动层数值传递
        this.rollNode.getComponent(GameRollNode).setRollDatas(data, this.bSpecialGame);
        this.rollNode.getComponent(GameRollNode).openPrizes(false, this.bQuickGame);
    }

    getSingleLineBet() {
        return this.gameConfig.nJetton[0];
    }

    upPlayerScore(score) {
        // cc.vv.globalUserInfo.setUserScore(score);
        this.playerScore.getComponent(Label).string = GameConstant.formatNumber(score);
    }
}


