
const {ccclass, property} = cc._decorator;

import {gameMY, moduleState, columnCondition} from './gameModule';


export enum columnState {
    Ready = 1,
    Start = 2,
    Delay = 3,
    Spining = 4,
    Slowing = 5,
    Stopping = 6,


    EngStop = 99,

}


@ccclass
export class columnControl extends cc.Component {

    // @property({type: gameMY}) 這句不行
    // public gameModule: gameMY | null = null;

    @property((cc.Node))
    gameModule: cc.Node;

    @property(Number)
    rollMinSpeed:number = 1;

    @property(Number)
    rollMaxSpeed:number = 10;

    private itemPool:Array<number>;  // 全部的 item 對應
    private waitingList:Array<number> = []; // 預計要顯示的item
    private finalList:Array<number> = []; // 預計要停下的item
    private currentList:Array<number> = []; // 現在正在顯示的item
    private speedFactor:number = 0; // 調速用變數
    private N:number; // 調速用變數
    private M:number; // 調速用變數
    private t:number; // 調速用變數
    private gameModuleScript:gameMY;
    nowState:columnState; // 狀態機previousState
    spinCondition:columnCondition; // 從 gameModule 吃過來的旋轉資訊


    protected onLoad () {
        // 一些防呆
        if(this.rollMaxSpeed < this.rollMinSpeed) throw new Error('rollMaxSpeed need to greater than rollMinSpeed');

        this.gameModuleScript = this.gameModule.getComponent('gameMY');
    }

    protected start () {

        this.itemPool = Object.values(this.gameModuleScript.itemNameMapping);

        // column 位置初始化
        this.node.y = this.gameModuleScript.itemSize;

        // 隨機初始化 item 圖片
        for(let i=0;i<this.node.childrenCount;i++){
            let a = this.itemPool[Math.floor(Math.random() * 12)];
            this.currentList.push( a );
            this.node.children[i].getComponent(cc.Sprite).spriteFrame = this.gameModuleScript.item_spriteFrame[a]
        }

        this.t = 0;
 
        this.nowState = columnState.Ready;
    }

    protected update (dt) {

        // let dY = Math.ceil(this.rollMinSpeed * this.gameModuleScript.itemSize * dt);
        let dY = this.speedFactor * (this.rollMaxSpeed - this.rollMinSpeed) + this.rollMinSpeed;
        dY = Math.ceil(dY * this.gameModuleScript.itemSize * dt);

        this.t += dt;


        switch(this.nowState){
            case columnState.Ready:
                //狀態檢查與更新
                if(this.gameModuleScript.nowState == moduleState.SetSpin){
                    this.nowState = columnState.Start;
                }
                break;
            case columnState.Start:
                this.spinCondition = this.gameModuleScript.columnConditionList[this.node.name];
                this.finalList = [...this.spinCondition.finalResult];
                this.N = this.spinCondition.N;
                this.M = 0.25 * (this.rollMaxSpeed - this.rollMinSpeed) * this.spinCondition.slowdownTime * Math.PI;
                this.M += this.rollMinSpeed * this.spinCondition.slowdownTime;
                this.M = Math.max(this.M, 4)  // 防呆 預防 M 小於 3

                // cc.log(this.M) // dev

                this.nowState = columnState.Delay; 
                setTimeout(()=>{ 
                    this.nowState = columnState.Spining; 
                    this.gameModule.emit("AColumnStart", this.node.name);
                    this.t = 0;
                }, this.spinCondition.delayTime);

                break;
            case columnState.Delay:
                cc.log("this is delay inside : " + this.node.name) // dev
                break;
            case columnState.Spining:
            case columnState.Slowing:
                this.speedFactor = this.updateSpeedFactor(this.t);
                if(this.node.y - dY <= 0){
                    //移動位置
                    this.node.y = this.node.y + this.gameModuleScript.itemSize - dY;
                    //更新圖片與狀態變化
                    this.updateShowItem(); 
                }else{this.node.y -= dY;}
                break;
            case columnState.Stopping:
                this.speedFactor = this.updateSpeedFactor(this.t);
                if(this.node.y - dY <= 0){
                    //移動位置
                    this.node.y = this.gameModuleScript.itemSize;
                    //更新圖片與狀態變化
                    this.updateShowItem(); 
                    //狀態檢查與更新
                    this.nowState = columnState.Ready; // 狀態復歸

                    this.gameModule.emit("AColumnStop", this.node.name)
                }else{this.node.y -= dY;}
                break;
            case columnState.EngStop:
                // To Nothing just pending whole column
                break;
        }
    }

    temp = 0; //dev
    updateShowItem() {

        let a:number;
        a = this.itemPool[Math.floor(Math.random() * this.itemPool.length)];

        this.temp+=1;
        // 持平階段會計數 N 值
        if((this.t > this.spinCondition.accelerateTime) && (this.nowState == columnState.Spining)) 
            {this.N -= 1;}

        // 減速階段會計數 M 值
        if(this.nowState == columnState.Slowing) this.M -= 1;

        // M小於3了，就出最終 item
        if(this.M <= 3 && this.M > 0 && this.nowState == columnState.Slowing) {
            a = this.finalList.pop();
        }

        // N歸零了，進到減速階段
        if(this.N == 0 && this.nowState == columnState.Spining) {
            this.nowState = columnState.Slowing;
            this.t = 0
        // 最終 item 結束，進到停止階段。
        } else if(this.finalList.length == 0) {
            this.nowState = columnState.Stopping;}
        

        this.currentList.unshift( a );
        this.currentList.pop();

        for(let i=0;i<this.currentList.length;i++){
            this.node.children[i].getComponent(cc.Sprite).spriteFrame = this.gameModuleScript.item_spriteFrame[this.currentList[i]];
        }
    }

    updateSpeedFactor(t){
        let result = 0;
        if((this.nowState == columnState.Spining)&&(t < this.spinCondition.accelerateTime)){
            result = 1 - ( Math.pow(t - this.spinCondition.accelerateTime,2) / Math.pow(this.spinCondition.accelerateTime,2) );
            result = Math.pow(result,0.5);
        }else if((this.nowState == columnState.Spining)&&(t > this.spinCondition.accelerateTime)){
            result = 1;
        }else if((this.nowState == columnState.Slowing)&&(t < this.spinCondition.slowdownTime)){
            result = 1 - ( Math.pow(t,2) / Math.pow(this.spinCondition.slowdownTime,2) );
            result = Math.pow(result,0.5);
        }else{
            result = 0;
        }

        return result;
    }

}



        