import {ApiCall, TsrpcError} from 'tsrpc';
import {FightControl} from '../shared/fightControl/fightCntrol';
import {formatNpcData} from '../shared/fightControl/fightFun';
import {fightResult, joinFightData, roleDataType} from '../shared/fightControl/fightType';
import {rankInfo} from '../shared/protocols/type';
import {HeroShared} from '../shared/public/hero';
import {PlayerShared} from '../shared/public/player';
import {HeroFun} from './hero';
import {UserFun} from './user';
import {re, string} from "mathjs";
import {getGud} from './gud';
import {PushGiftFun} from "./pushgift";

type fightType = 'tanxian' | 'pata' | 'jjc' | 'gbtx' | 'qjzzd' | 'meirishilian' | 'wzrycross';


let fights:{[key:string]:FightControl} = {
    
};
function clearFights (){
    //定时清理战斗
    setInterval(()=>{
        let now = Date.now();
        for (let key in fights){
            if (now - fights[key].startTime > 30000){
                console.log("清理战斗",key);
                try{
                    fights[key].release();
                }catch(e){
                    console.error(e);
                }
                delete fights[key];
            }
        }
    },5000);
}
clearFights();

export class FightFun {
    static fightIndex:number = 0;

    static fight(data: joinFightData[], maxRoundNums = 30, fightType: "pvp" | "pve" = 'pvp') {
        this.fightIndex++;
        fights[this.fightIndex] = new FightControl(data, maxRoundNums, fightType);

        return fights[this.fightIndex].getResult();
    }

    /**获取玩家数据 */
    static async getPlayerFightData(uid: string) {

        //const player = await G.mongodb.collection('user').findOne({uid: uid});
        const player = await getGud(uid);

        if (!player) return null;

        let posObj = player.heroPos;
        if (player.selectMatrix && player.matrixPos[player.selectMatrix]) {
            posObj = player.matrixPos[player.selectMatrix];
        }
        const roles: k_v<roleDataType> = {};
        const heros = await HeroFun.getHeros(player, Object.values(posObj).filter(_id => _id != ''));

        Object.entries(posObj).forEach(obj => {
            const pos = obj[0];
            const _id = obj[1];
            const hero = heros.filter(h => h._id == _id)[0];

            if (hero) {
                roles[pos] = {
                    ...hero,
                    attr: {
                        ...HeroShared.getHeroBasicAttr(hero, {
                            ...UserFun.getOtherBuff(player),
                            allBuff: HeroShared.getAllBuff(heros)
                        }, Number(pos))
                    }
                };
            }
        });

        return {
            player: {...player, buff: PlayerShared.getBuff(player)},
            roles: roles
        };
    }

    /**挑战竞技场 */
    static async fightJJc(call: ApiCall, rankInfo: rankInfo) {
        if (rankInfo.player.uid.indexOf('npc_') != -1) return await this.fightNpc(call, G.gc.jjc_npc[rankInfo.player.uid].npcId, 'jjc', await this.getPlayerFightData(call.conn.uid));

        let result = this.fight([await this.getPlayerFightData(call.conn.uid), await this.getPlayerFightData(rankInfo.player.uid)]);

        // 竞技场 战败触发推送礼包
        if (result.winSide != 0) {
            PushGiftFun.chkLoseGift(call.uid)
        }

        return result
    }

    /**挑战npc */
    static async fightNpc(call: ApiCall, npcId: string | number, type: fightType, data?: joinFightData) {

        let my = data || await call.conn.getDefaultFightData();

        if (Object.keys(my.roles).length < 1) {
            throw new TsrpcError('至少需要上阵一个英雄');
        }

        if (!G.gc.npc[npcId]) {
            throw new TsrpcError(`npcId: ${npcId} 不存在`);
        }

        let npc = formatNpcData(npcId);

        let result = this.fight([my, npc], 30, 'pve');

        // 主线 爬塔 战败触发推送礼包
        if (result.winSide != 0 && ["tanxian", "pata"].includes(type)) {
            PushGiftFun.chkLoseGift(call.uid)
        }
        return result
    }

    /**
     * 记录战斗日志白名单，存在列表里的类型才会记录
     * @param uid
     * @param type
     * @param result
     */
    static async saveLog(uid: string, type: string, result: fightResult) {
        let writeList = ['ganhai', 'jjc', 'hbzbJfs', 'hbzbZbs', 'slzd', 'clsl'] 
        if (uid.indexOf('npc') != -1 || !writeList.includes(type)) return;

        G.mongodb.collection('fightLog').insertOne({uid, type, ...result})

    }

    static async readLog(uid: string, type: string, len = 20) {
        return await G.mongodb.collection('fightLog').find({uid, type}).limit(len).toArray() || []
    }
}