import CSMessage from "../../../Base/CSMessage";
import { BJ_Casino_Bot } from "../../../BJ_Casino_Bot";
import { BJ_Casino_Bot_Slot } from "../../../BJ_Casino_Bot_Slot";
import { INetResponse } from "../../../Engine/CatanEngine/NetManagerV2/Core/INetResponse";
import { NumberEx } from "../../../Engine/Utils/Number/NumberEx";
import { CommonSlotFgSpinRequest, CommonSlotSpinRequest } from "../Request/CommonSlotRequest";
import { Slot_ChoiceRequest } from "../Request/SlotRequest";

export class SlotBase {
    //#region public

    public get ID(): number { return this._bj_Casino_Bot.LobbyScript.Slot; }
    public get FreeID(): number { return 1; }
    public get HasChoiceFreeGame(): boolean { return false; }
    public get SlotReqRespIsCount(): boolean { return false; }
    public get HasRetriggerFreeSpin(): boolean { return false; }
    public GameRunData: JSON = null;
    public ChoiceFreeCount: Object = {};

    //#endregion

    //#region protected

    protected _bj_Casino_Bot: BJ_Casino_Bot;

    protected _bj_Slot: BJ_Casino_Bot_Slot;

    //#endregion

    //#region Lifecycle

    /**
     *
     */
    constructor(bj_Casino_Bot: BJ_Casino_Bot, bj_Slot: BJ_Casino_Bot_Slot,) {
        this._bj_Casino_Bot = bj_Casino_Bot;
        this._bj_Slot = bj_Slot;
        this.onLoad();
    }

    public async onLoad(): Promise<void> {
        //
    }

    //#endregion

    //#region Custom

    public async Spin(): Promise<void> {
        let gameRunData: JSON = null;
        let req: CommonSlotSpinRequest = new CommonSlotSpinRequest(this.ID, this._bj_Slot.NowBet);
        await req.SendAsync();
        let resp: INetResponse<JSON> = req.Result;
        if (resp.IsValid) {
            gameRunData = this.GameRunData = resp.Data;
        } else {
            CSMessage.NetError(resp.Method, resp.Status);
        }
        let money: number = gameRunData["money"] ? +gameRunData["money"] : 0;
        let winMoney: number = 0;
        let winMoneyLog: string = "";
        let freeLog: string = "";
        let resources: any[] = gameRunData["get"];
        let free: any = gameRunData["free"];
        let choiceFreeGame: boolean = gameRunData["rs"] === 0;
        if (resources) {
            winMoney = this._getWinMoney(resources);
        }
        if (choiceFreeGame && this.HasChoiceFreeGame) {
            free = true;
        }
        if (free) {
            let freeCount: number = await this._getFreeCount();
            let fswinMoney: number = 0;
            let fsmoney: number = 0;
            [freeCount, fswinMoney, fsmoney] = await this.FreeSpin(freeCount);
            if (fsmoney > 0) {
                money = fsmoney;
            }
            if (fswinMoney > 0) {
                winMoney = fswinMoney;
            }
            freeLog = `, hasFree: ${freeCount}`;
        }
        if (winMoney > 0) {
            winMoneyLog = `, winMoney: ${winMoney}`;
        }
        this._bj_Casino_Bot.UserData.Money = money;
        this._bj_Casino_Bot.SetUI();
        let scale: number = winMoney > 0 ? NumberEx.divide(winMoney, this._bj_Slot.NowBet) : 0;
        this._bj_Casino_Bot.AddLog(`Slot${this.ID} Spin Bet: ${this._bj_Slot.NowBet}, Money: ${money}${winMoneyLog}${freeLog}`);
    }

    public async FreeSpin(freeCount: number): Promise<number[]> {
        let fswinMoney: number = 0;
        let fsmoney: number = 0;
        for (let i: number = 0; i < freeCount; i++) {
            let gameRunData: JSON = null;
            let req: CommonSlotFgSpinRequest = new CommonSlotFgSpinRequest(this.ID);
            await req.SendAsync();
            let resp: INetResponse<JSON> = req.Result;
            if (resp.IsValid) {
                gameRunData = resp.Data;
                if (this.HasRetriggerFreeSpin) {
                    let retriggercount: number = this._getRetriggerFreeSpinCount(gameRunData);
                    freeCount += retriggercount;
                }
                if (i === freeCount - 1) {
                    let resources: any[] = gameRunData["get"];
                    if (resources) {
                        fswinMoney = this._getWinMoney(resources);
                    }
                    fsmoney = gameRunData["money"] ? +gameRunData["money"] : 0;
                }
            } else {
                CSMessage.NetError(resp.Method, resp.Status);
            }
            this._bj_Casino_Bot.AddLog(`Slot${this.ID} FreeSpin MaxCount: ${freeCount}, Count: ${i + 1}`);
        }
        return [freeCount, fswinMoney, fsmoney];
    }

    protected _getWinMoney(resources: any[]): number {
        for (let i: number = 0; i < resources.length; i++) {
            const resource: any[] = resources[i];
            if (resource[0] === 1) {
                return resource[1];
            }
        }
        return 0;
    }

    protected _getRetriggerFreeSpinCount(gameRunData: JSON): number {
        if (gameRunData["free"]) {
            return gameRunData["free"][1];
        }
        return 0;
    }

    protected async _getFreeCount(): Promise<number> {
        if (this.HasChoiceFreeGame) {
            return await this._getChoiceFreeCount();
        } else {
            return this.GameRunData["free"][1];
        }
    }

    protected async _getChoiceFreeCount(): Promise<number> {
        let id: number = this._getFreeID();
        let request: Slot_ChoiceRequest = new Slot_ChoiceRequest(id);
        await request.SendAsync(true);
        var result: INetResponse<number> = request.Result;
        if (result.IsValid) {
            if (this.SlotReqRespIsCount) {
                return result.Data;
            } else if (this.ChoiceFreeCount[result.Data]) {
                return this.ChoiceFreeCount[result.Data];
            }
        }
        return 0;
    }

    protected _getFreeID(): number {
        return this.FreeID;
    }

    //#endregion
}

export default SlotBase;