import { MemComBtlTeam } from './../domain/battleField/ComBattleTeamField';
import { ItemModel } from './../db/Item';
import { BATTLE_REWARD_TYPE, ITEM_CHANGE_REASON, IT_TYPE, PUSH_ROUTE } from './../consts';
import { FriendRelationModel } from './../db/FriendRelation';
import { RoleModel, RoleType } from './../db/Role';
import { EquipPrintDropType, EquipPrintDropModel } from './../db/EquipPrintDrop';
import { STATUS } from './../consts/statusCode';
import { COM_TEAM_STATUS, FRIEND_DROP_TYPE, COM_BTL_CONST, FRIEND_DROP_MAX } from './../consts';
import { RoleStatus, ComBattleTeamModel, ComBattleTeamType, ComBattleReward } from './../db/ComBattleTeam';
import { getRandEelm, getRandValue, resResult, ratioReward, getRandValueByMinMax, getRandEelmWithWeight, getRobotInfo, getRandSingleEelm } from "../pubUtils/util";
import { getRandRobot } from "./battleService";
import { Channel, ChannelService, pinus } from 'pinus';
import { TREASURE, EXTERIOR, FRIEND } from '../pubUtils/dicParam';
import { getFriendLvAdd } from './friendService';
import { getRoleIds } from '../pubUtils/friendUtil';
import { getComTeamSidByCode, getCreatedTeamByLv, getTeamSearchByLv, rmCreatedTeamFromRedis, rmRoleFromQueue, setCreatedTeamToRedis } from './redisService';
import { getRewardByBlueprtId, gameData, getBossHpByBlueprtId, getDicBlueprtById } from '../pubUtils/data';
import { getZeroPointD, nowSeconds } from '../pubUtils/timeUtil';
import { addItems, getFriendPointObject, handleCost } from './role/rewardService';
import { addUserToTeamChannel, delTeamChannel, sendMessageToTeam, sendMessageToUsersWithSuc, sendMessageToUserWithSuc } from './pushService';
import { checkTaskInComBattleEnd } from './task/taskService';
import moment = require('moment');
import { RewardInter } from '../pubUtils/interface';
import { FriendPointModel } from '../db/FriendPoint';

/**
 * 在给定的品质列表中随机返回一定数量的藏宝图Id
 * @param lv 品质数组，在所有给定品质的藏宝图中筛选1
 * @param cnt 返回藏宝图数量
 */
export function getRandBlueprtId(lvs: number[], cnt = 1) {
    if (!lvs || !lvs.length) return null;

    let blueprtIdArr: number[] = [];
    for (let lv of lvs) {
        blueprtIdArr = blueprtIdArr.concat(gameData.blueprtByLv.get(lv));
    }
    if (blueprtIdArr.length === 0) return null;

    const res = getRandEelm(blueprtIdArr, cnt);
    // console.log('******** getRandBlueprtId', blueprtIdArr, cnt, res)
    return res;
}

export function getRandComBtlRobots(topLineupCe: number, ceLimit: number, lv: number, cnt: number) {
    let robotHeroes = getRandRobot(cnt); // 随机几个阵容
    let robotInfos: { robotRoleName: string, robotRoleId: string }[] = []; // 随机几个机器人信息
    for (let i = 0; i < cnt; i++) {
        robotInfos.push(getRobotInfo());
    }
    // 创建并添加机器人
    let robotStArr: RoleStatus[] = [], robotIdArr: string[] = [];
    if (robotHeroes && robotInfos && robotHeroes.length && robotInfos.length && robotInfos.length === robotHeroes.length) {
        robotHeroes.forEach((robot, idx) => {
            let robotCe = 0;
            if (ceLimit && ceLimit > 0) {
                robotCe = getRandValueByMinMax(ceLimit, (topLineupCe || 0) * (1 + COM_BTL_CONST.ROBOT_CE_RATIO), 0);
            } else {
                robotCe = getRandValue(topLineupCe || 0, COM_BTL_CONST.ROBOT_CE_RATIO, 0);
            }
            let robotLv = getRandValue(lv, COM_BTL_CONST.ROBOT_CE_RATIO, 0);
            if(robotLv > gameData.maxPlayerLv.max) robotLv = gameData.maxPlayerLv.max;
            // const imgHid = robot[Math.floor(Math.random() * robot.length)];
            const { robotRoleId, robotRoleName } = robotInfos[idx];
            let robotStatus = new RoleStatus({
                roleId: robotRoleId, 
                roleName: robotRoleName,
                topLineupCe: robotCe,
                lv: robotLv
            }, '', false, false, robot, true);
            robotStArr.push(robotStatus);
            robotIdArr.push(robotRoleId);
        });
    }
    return {
        robotStArr, robotIdArr
    }
}

export function checkComBattleResult(teamStatus) {
    if (teamStatus.bossCurHp === 0) {
        return COM_TEAM_STATUS.WIN;
    } else {
        let allPlayerKilled = true;
        let robotRestHurt = 0;
        // 看看是否还有活人
        teamStatus.roleStatus.forEach(st => {
            // 设置了阵容，且阵容人数和阵亡人数一样，说明玩家战败
            if (!st.isRobot && st.battleStatus != 2 && st.heroes && ((st.heroes.length > 0 && st.killed.length < st.heroes.length) || st.heroes.length === 0 )) {
                allPlayerKilled = false
            }
        });
        // 没有活人的话看看还有没有机器人没打完伤害
        if (allPlayerKilled && teamStatus.curRnd < COM_BTL_CONST.ROBOT_RND_LMT) {
            teamStatus.roleStatus.forEach(st => {
                if (st.isRobot) {
                    const deltaRnd = COM_BTL_CONST.ROBOT_RND_LMT - teamStatus.curRnd;
                    let hurtHp = getRandValue(teamStatus.bossHp / COM_BTL_CONST.ROBOT_RND_LMT * COM_BTL_CONST.ROBOT_HURT_RATIO, COM_BTL_CONST.ROBOT_HURT_CH_RATIO, 0) * deltaRnd; // 1 个机器人对 boss 造成的总伤害
                    robotRestHurt += hurtHp;
                }
            })
        }
        if (allPlayerKilled) {
            // 没有活人且机器人剩余伤害打不死 boss，战败
            if (teamStatus.bossCurHp > robotRestHurt) {
                return COM_TEAM_STATUS.LOOSE;
            } else {
                return COM_TEAM_STATUS.WIN;
            }
        }
    }
    return COM_TEAM_STATUS.FIGHTING;
}

// /**
//  * ! deprecated
//  * @description 计算寻宝结算
//  * @export
//  * @param {string} roleId
//  * @param {string} battleCode
//  * @returns
//  */
// export async function checkComBattleDrop(roleId: string, battleCode: string) {
//     let team = await ComBattleTeamModel.getTeamByRoleAndBattleCode(roleId, battleCode);
//     if (team.status !== COM_TEAM_STATUS.WIN) return { status: -1, resResult: resResult(STATUS.COM_BATTLE_REWARD_ERR) };
//     let roleSt = null;
//     team.roleStatus.forEach(st => {
//         if (st.roleId === roleId) {
//             roleSt = st;
//         }
//     });
//     if (!roleSt || roleSt.gotReward) return { status: -1, resResult: resResult(STATUS.COM_BATTLE_REWARD_ERR) };
//     let { fixReward, teammateReward } = getRewardByBlueprtId(team.blueprtId);
//     if (!roleSt.isCap) {
//         if (roleSt.isFrd) {
//             fixReward = [];
//         } else {
//             fixReward = teammateReward;
//         }
//     }
//     await ComBattleTeamModel.updateRewardSt(team.teamCode, roleId, true);
//     return { status: 0, fixReward };
// }

export function clearComBtlTimer(teamCode: string, timerMap: Map<string, NodeJS.Timer>) {
    let timer = timerMap.get(teamCode);
    if (timer) {
        clearTimeout(timer);
    }
}

export function setComBtlTimer(teamCode: string, timer: NodeJS.Timer, timerMap: Map<string, NodeJS.Timer>) {
    let preTimer = timerMap.get(teamCode);
    if (preTimer) {
        clearTimeout(preTimer);
    }
    timerMap.set(teamCode, timer);
}

export async function getRealReward(blueprtId: number, roleSts: RoleStatus[], roleSt: RoleStatus, hasTimeExtraReward: boolean): Promise<ComBattleReward[]> {
    let dicReward = getRewardByBlueprtId(blueprtId);
    if(!dicReward) return [];
    
    let fixRewards: RewardInter[] = [], extraRewards: RewardInter[] = [], hasExtraReward = true;
    if (roleSt.isCap) {
        fixRewards.push(...dicReward.captainReward);
        if(roleSt.isFrd && !roleSt.isRobot) {
            hasExtraReward = false;
        }
    } else {
        if (roleSt.isFrd && !roleSt.isRobot) {
            // 情谊值有上限，送到上限为止
            let frdPointRec = await FriendPointModel.getFrdPointRecToday(roleSt.roleId, FRIEND_DROP_TYPE.COM_BATTLE);
            let { comBattleCnt = 0 } = frdPointRec || {};
            if(comBattleCnt < FRIEND.FRIEND_FRIENDPOINT_MAX) {
                let count = FRIEND.FRIEND_FRIENDPOINT_MAX - comBattleCnt > TREASURE.REWARD_FRIENDPOINT? TREASURE.REWARD_FRIENDPOINT: FRIEND.FRIEND_FRIENDPOINT_MAX - comBattleCnt;
                fixRewards.push(getFriendPointObject(count));
                await FriendPointModel.updateComBattleCntToday(roleSt.roleId, roleSt.roleName, count, FRIEND.FRIEND_FRIENDPOINT_MAX, FRIEND_DROP_TYPE.COM_BATTLE);
            } 
            hasExtraReward = false;
        } else {
            fixRewards.push(...dicReward.teammateReward)
        }
    }
    if(hasTimeExtraReward && hasExtraReward) {
        let sameGuildCnt = roleSts.filter(cur => cur.guildCode == roleSt.guildCode && cur.roleId != roleSt.roleId).length;
        if(sameGuildCnt > 0) {
            let dicGuildReward = roleSt.isCap? dicReward.captainTimeGuildReward: dicReward.teammateTimeGuildReward;
            let guildRewards = dicGuildReward.get(sameGuildCnt)||[]
            extraRewards.push(...guildRewards);
        } else {
            let guildRewards = roleSt.isCap? dicReward.captainTimeReward: dicReward.teammateTimeReward;
            extraRewards.push(...guildRewards);
        }
    }
    return [
        ...fixRewards.map(reward => ({ type: BATTLE_REWARD_TYPE.FIX_REWARD, ...reward })),
        ...extraRewards.map(reward => ({ type: BATTLE_REWARD_TYPE.EXTRA_REWARD, ...reward }))
    ]
}

export async function getAllAssistCnt(roleId: string) {
    let teams = await ComBattleTeamModel.getAssistTeamsByTime(roleId, getZeroPointD(), true);
    if (teams.length > 0) {
        // 过滤掉情谊助战次数
        teams = teams.filter(team => {
            let roleSt = team.roleStatus.find(st => st.roleId === roleId);
            return !roleSt.isFrd;
        });
    }
    return teams.length;
}

export async function getCapExtraCnt(roleId: string) {
    let teams = await ComBattleTeamModel.getCapExtraRewardCnt(roleId, getZeroPointD());
    return teams.length;
}

export async function getFrd(roleId: string) {
    let isFrd = false;
    let cnt = await getAllAssistCnt(roleId);
    if (cnt >= TREASURE.TREASURE_ASSIST_TIME) isFrd = true;
    return isFrd;
}

export async function getCapFrd(roleId: string) {
    let isFrd = false;
    let cnt = await getCapExtraCnt(roleId);
    if (cnt >= TREASURE.TREASURE_CAP_EXTRA_TIME) isFrd = true;
    return isFrd;
}

/**
 * @description 更新队伍状态
 * @export
 * @param {number} preStatus 更新前状态，作为筛选条件
 * @param {number} newStatus 要设置的新状态
 */
export async function updateTeamStatus(preStatus: number, newStatus: number) {
    if (preStatus === newStatus) return;
    await ComBattleTeamModel.updateStatusByStatus(preStatus, newStatus);
}

/**
 * @description 计算机器人每次对 boss 造成的伤害
 * @param {number} bossHp boss 总血量
 */
function robotEachHurt(bossHp: number, bossCnt: number) {
    const robotTotalHurt = bossHp * COM_BTL_CONST.ROBOT_HURT_RATIO;
    const robotAverageHurt = robotTotalHurt / COM_BTL_CONST.ROBOT_ACT_LMT / bossCnt;
    return getRandValue(robotAverageHurt, COM_BTL_CONST.ROBOT_HURT_CH_RATIO, 0)
}

/**
 * @description 更新机器人阵亡情况
 * @param {number} bossHp
 * @param {RoleStatus} roleSt
 */
function updateRobotKilled(bossHp: number, roleSt: RoleStatus) {
    const robotTotalHurt = bossHp * COM_BTL_CONST.ROBOT_HURT_RATIO;
    // 让阵亡人数和打出伤害的进度同步，比如有 5 个武将，每打出目标总伤害的 1 / 5 应该增加一个阵亡武将
    const dmgProgress = Math.floor(roleSt.totalDmg / (robotTotalHurt / roleSt.heroes.length));
    if (dmgProgress > roleSt.killed.length && dmgProgress <= roleSt.heroes.length) {
        const newKilledCnt = dmgProgress - roleSt.killed.length;
        const aliveHeroes = roleSt.heroes.filter(hero => {
            return roleSt.killed.indexOf(hero.id) == -1; 
        }).map(cur => cur.id);
        const newKilledHeroes = getRandEelm(aliveHeroes, newKilledCnt);
        roleSt.killed = roleSt.killed.concat(newKilledHeroes);
    }
}

export async function handleComBtlProgress(teamStatus: MemComBtlTeam, robotHurtTimer: Map<string, NodeJS.Timer>, teamMap: Map<string, MemComBtlTeam>) {
    const { teamCode } = teamStatus;
    // 判断战斗是否结束
    let battleSt = checkComBattleResult(teamStatus);
    teamStatus.status = battleSt;
    if (battleSt === COM_TEAM_STATUS.WIN || battleSt === COM_TEAM_STATUS.LOOSE) {
        let result = battleSt === COM_TEAM_STATUS.WIN;
        if (result) {
            teamStatus.bossHpArr.forEach(bs => {
                bs.curHp = 0;
            });
            for (let st of teamStatus.roleStatus) {
                st.rewards = await getRealReward(teamStatus.blueprtId, teamStatus.roleStatus, st, teamStatus.hasTimeExtraReward);
            };
            await checkTaskInComBattleEnd(teamStatus.roleStatus, teamStatus.capId);
        }
        let team = await ComBattleTeamModel.syncTeamData({ teamCode, status: battleSt, roleStatus: teamStatus.roleStatus, bossHpArr: teamStatus.bossHpArr, endTime: teamStatus.endTime });
        if (!team) return resResult(STATUS.COM_BATTLE_RESULT_ERR);

        // 战斗胜利队长扣减藏宝图
        if (result && teamStatus.capId != 'robot') {
            let res = await handleCost(teamStatus.capId, teamStatus.sid, [{ id: teamStatus.blueprtId, count: 1 }], ITEM_CHANGE_REASON.COM_BATTLE_USE_BLUEPRT);
            if (res === false) return resResult(STATUS.COM_BATTLE_BLUEPRT_NOT_ENOUGH);
        }

        clearRobotHurtTimer(teamStatus, robotHurtTimer);
        sendMessageToTeam(teamCode, PUSH_ROUTE.TEAM_COMPLETE, { teamCode, result });

        teamMap.delete(teamCode);
    }
}

/**
 * @description 更新机器人对 boss 的伤害
 * @export
 * @param {*} teamStatus 要更新的队伍信息
 * @param {RoleStatus} roleSt 要更新的玩家信息
 */
export function updateRobotHurt(teamStatus: MemComBtlTeam, roleSt: RoleStatus) {
    // 机器人的伤害为：boss 血量的一定比例，平均到一定回合数内，再平均到每个敌军，上下浮动一定比例
    let eachHurtHp = robotEachHurt(teamStatus.bossHp, teamStatus.bossHpArr.length);
    let robotTotalHurt = 0;
    let actBossHurts = [];
    let hero = getRandSingleEelm(roleSt.heroes);
    for (let boss of teamStatus.bossHpArr) {
        if (boss.curHp === 0) continue;
        if (boss.curHp >= eachHurtHp) {
            actBossHurts.push({ dataId: boss.dataId, hurtHp: eachHurtHp });
            robotTotalHurt += eachHurtHp;
            boss.curHp -= eachHurtHp;
            hero.addDamage(eachHurtHp);
        } else if (boss.curHp > 0) { // 丢弃溢出的伤害
            actBossHurts.push({ dataId: boss.dataId, hurtHp: boss.curHp });
            robotTotalHurt += boss.curHp;
            hero.addDamage(boss.curHp);
            boss.curHp = 0;
        }
        break;
    }
    teamStatus.bossCurHp -= robotTotalHurt;
    roleSt.totalDmg += robotTotalHurt;
    updateRobotKilled(teamStatus.bossHp, roleSt);
    sendMessageToTeam(teamStatus.teamCode, PUSH_ROUTE.TEAMMATE_ACT, { teamCode: teamStatus.teamCode, bossCurHp: teamStatus.bossCurHp, bossHpArr: teamStatus.bossHpArr, roleStatus: teamStatus.roleStatus, actRoleId: roleSt.roleId, actBossHurts });
}

/**
 * @description 按一定时间间隔刷新机器人伤害
 * @export
 * @param {*} teamStatus
 * @param {RoleStatus} roleSt
 * @param {number} interval
 * @param {Channel} channel
 * @param {Map<string, NodeJS.Timer>} robotHurtTimer
 */
export function updateRobotHurtByTime(teamStatus: MemComBtlTeam, roleSt: RoleStatus, interval: number, robotHurtTimer: Map<string, NodeJS.Timer>, teamMap: Map<string, MemComBtlTeam>) {
    const timerKey = `${teamStatus.teamCode}_${roleSt.roleId}`;
    const robotTimer = setInterval(() => {
        const robotTotalHurt = teamStatus.bossHp * COM_BTL_CONST.ROBOT_HURT_RATIO;
        if (roleSt.totalDmg < robotTotalHurt && teamStatus.bossCurHp > 0 && teamMap.has(teamStatus.teamCode)) {
            updateRobotHurt(teamStatus, roleSt);
            handleComBtlProgress(teamStatus, robotHurtTimer, teamMap);
        } else {
            clearInterval(robotTimer);
        }
    }, interval * 1000);
    if (!robotHurtTimer.has(timerKey)) {
        robotHurtTimer.set(timerKey, robotTimer);
    }
}

/**
 * @description 清理机器人伤害的 timer
 * @export
 * @param {*} teamStatus 寻宝队伍状态
 * @param {Map<string, NodeJS.Timer>} robotHurtTimer
 */
export function clearRobotHurtTimer(teamStatus, robotHurtTimer: Map<string, NodeJS.Timer>) {
    teamStatus.roleStatus.forEach(st => {
        const timerKey = `${teamStatus.teamCode}_${st.roleId}`;
        if (st.isRobot === true && robotHurtTimer.has(timerKey)) {
            clearInterval(robotHurtTimer.get(timerKey));
        }
    });
}

/**
 * @description 检查寻宝等级是否合法
 * @export
 * @param {number} playerLv 玩家等级
 * @param {number} blueprtLv 藏宝图等级
 * @returns
 */
export function comBtlLvInvalid(playerLv: number, blueprtLvs: number[]) {
    for(let blueprtLv of blueprtLvs) {
        const range = gameData.comBtlLvRange.get(blueprtLv);
        if (!range) return true;
        let { min, max } = range;
        if(playerLv < min || playerLv > max) return true;
    }
    return false
}

export function getComBtlLvByPlayerLv(playerLv: number) {
    let lvs: number[] = [];
    for(let [lv, {min, max}] of gameData.comBtlLvRange) {
        if(playerLv >= min && playerLv <= max) lvs.push(lv);
    }
    let minLv = Math.min(...lvs);
    let maxLv = Math.max(...lvs);
    return { minLv, maxLv }
}

export async function dismissTeam(teamStatus: MemComBtlTeam, teamMap: Map<string, MemComBtlTeam>, roleId: string, teamDisTimer: Map<string, NodeJS.Timer>) {
    const { teamCode } = teamStatus;
    if (!teamStatus || !teamStatus.roleIds || teamStatus.roleIds.indexOf(roleId) === -1) return resResult(STATUS.COM_BATTLE_TEAM_INVALID);
    if (teamStatus.status !== COM_TEAM_STATUS.DEFAULT) return resResult(STATUS.COM_BATTLE_DISSMISS_ERR);
    if (roleId !== teamStatus.capId) return resResult(STATUS.COM_BATTLE_CAP_ONLY);

    let team = await ComBattleTeamModel.removeTeam(teamCode);
    if (!team) return resResult(STATUS.COM_BATTLE_DISSMISS_ERR);

    let rmSt = teamMap.delete(teamCode);
    if (!rmSt) return resResult(STATUS.COM_BATTLE_DISSMISS_ERR);

    rmCreatedTeamFromRedis(teamCode, teamStatus.lv);
    sendMessageToTeam(teamCode, PUSH_ROUTE.TEAM_DISMISS, { teamCode });
    delTeamChannel(teamCode);
    clearComBtlTimer(teamCode, teamDisTimer); // 队伍解散停止解散计时
    return resResult(STATUS.SUCCESS);
}

export function setDismissTimer(teamStatus: MemComBtlTeam, teamMap: Map<string, MemComBtlTeam>, roleId: string, teamDisTimer: Map<string, NodeJS.Timer>) {
    // if (teamIsFullToStart(teamStatus)) {
        clearComBtlTimer(teamStatus.teamCode, teamDisTimer);
        let timer = setTimeout(async () => {
            await dismissTeam(teamStatus, teamMap, roleId, teamDisTimer);
        }, COM_BTL_CONST.CAP_START_TIME);
        teamDisTimer.set(teamStatus.teamCode, timer);
    // }
}

/**
 * 按照好友关系，新增加成
 * 
 * @param {RoleStatus[]} roleStatus 队伍内的所有队友
 */
export async function getComBattleFriendAdd(roleStatus: RoleStatus[]) {
    let hasAdd: string[] = []; //roleIds
    for (let myRoleStatus of roleStatus) {
        for (let rs of roleStatus) {
            if (myRoleStatus.roleId == rs.roleId) continue;
            if (myRoleStatus.isRobot || rs.isRobot) continue;

            let { roleIds } = getRoleIds([myRoleStatus.roleId, rs.roleId]);
            if (hasAdd.includes(roleIds)) continue;

            let add = await getFriendLvAdd(myRoleStatus.roleId, rs.roleId);
            rs.addFrdRatio(add);
            myRoleStatus.addFrdRatio(add);

            hasAdd.push(roleIds);
        }
    }
}

/**
 * @description 检查玩家是否符合加入队伍的条件
 * @param {Partial<RoleType>} roleInfo 要加入玩家的信息
 * @param {string} roleId 要加入玩家的 id
 * @param {string[]} roleIds 队伍中当前玩家列表
 * @param {number} ceLimit
 * @returns
 */
async function teammateValid(roleInfo: Partial<RoleType>, roleId: string, roleIds: string[], ceLimit: number) {
    if (!roleInfo || roleIds.indexOf(roleId) !== -1) return false;

    const isBlack = await teammateInBlackList(roleId, roleIds);
    if (isBlack) return false;

    let { topLineupCe } = roleInfo;
    if (topLineupCe < ceLimit) return false;

    return true;
}

/**
 * @description 将用户信息转换成寻宝组队所需的 RoleStatus
 * @export
 * @param {string} roleId 要加入玩家的信息
 * @param {string[]} roleIds 队伍中当前玩家列表
 * @param {number} ceLimit
 * @returns
 */
export async function getValidTeammateRoleSt(roleId: string, roleIds: string[], ceLimit: number, sid: string) {
    let roleInfo = await RoleModel.findByRoleId(roleId, null, true);

    const valid = await teammateValid(roleInfo, roleId, roleIds, ceLimit);
    if (!valid) return null;

    let isFrd = await getFrd(roleId);
    const result = new RoleStatus(roleInfo, sid, false, isFrd);
    return result;
}

/**
 * @description 检查队伍中是否有人互为黑名单
 * @export
 * @param {string} roleId 要加入队伍的玩家 id
 * @param {string[]} roleIds 队伍中已有的玩家 id
 * @returns
 */
export async function teammateInBlackList(roleId: string, roleIds: string[]) {
    for (let teammateRoleId of roleIds) {
        const isBlack = await FriendRelationModel.isInBlackList(roleId, teammateRoleId);
        if (isBlack === true) return true;
    }
    return false;
}

export function blueprtIdValid(id: number) {
    return gameData.blueprt.has(id);
}

/**
 * @description 检查是否有足够的藏宝图，未结束的战斗也占用一张藏宝图
 * @export
 * @param {string} roleId
 * @param {number} blueprtId
 * @returns
 */
export async function hasEnoughBlueprt(roleId: string, sid: string, blueprtId: number) {
    let blueprt = await ItemModel.findbyRoleAndGidAndCount(roleId, blueprtId, 1);
    if (!blueprt || blueprt.count <= 0) return false;
    // 检查是否有已创建未结束的寻宝，预先占用一张藏宝图
    // // 背包中占用的藏宝图不显示，所以这里就扣掉，结束再加回去
    // let result = await handleCost(roleId, sid, [{ id: blueprtId, count: 1 }]);
    // return result;
    let teams = await ComBattleTeamModel.getBlueprtInUse(roleId, COM_TEAM_STATUS.FIGHTING, blueprtId);
    console.log('hasEnoughBlueprt', blueprt.count, teams.length)
    if (teams && blueprt.count <= teams.length) return false;
    return true
}

/**
 * @description 将玩家加入到队伍数据结构中，需将玩家信息做转化
 * @export
 * @param {MemComBtlTeam} comTeam 队伍数据结构
 * @param {RoleType} roleInfo 原始玩家信息
 * @param {boolean} isCap
 * @param {boolean} isFrd
 */
export function addRoleToTeam(comTeam: MemComBtlTeam, roleInfo: RoleType, sid: string, isCap: boolean, isFrd: boolean) {
    const roleSt = new RoleStatus(roleInfo, sid, isCap, isFrd);
    addRoleStToTeam(comTeam, roleSt);
}

/**
 * @description 将玩家加入到队伍数据结构中
 * @export
 * @param {MemComBtlTeam} comTeam 队伍数据结构
 * @param {RoleStatus} roleSt 要加入的玩家数据
 */
export function addRoleStToTeam(comTeam: MemComBtlTeam, roleSt: RoleStatus) {
    const { roleStatus = [], roleIds = [] } = comTeam;
    comTeam.roleStatus = [roleSt, ...roleStatus];
    comTeam.roleIds = [roleSt.roleId, ...roleIds];

    if(!validToJoin(comTeam)) { // 无人可匹配时，删除存在redis中的匹配信息
        rmCreatedTeamFromRedis(comTeam.teamCode, comTeam.lv);
    }
}

/**
 * @description 将符合要求的用户匹配到队伍中
 * @export
 * @param {MemComBtlTeam} comTeam 队伍数据
 * @param {string} sid 当前用户 sid
 * @returns
 */
export async function addValidSearchingRoles(comTeam: MemComBtlTeam) {
    const { lv } = getDicBlueprtById(comTeam.blueprtId);
    let teammates = await getTeamSearchByLv(lv);
    if (teammates && teammates.length) {
        for (let teammate of teammates) {
            const { roleId: teammateRoleId, sid } = teammate;
            const st = await getValidTeammateRoleSt(teammateRoleId, comTeam.roleIds, comTeam.ceLimit, sid);
            if (!st) continue;
            await rmRoleFromQueue(teammateRoleId, sid); // 匹配成功后删除redis中该用户的匹配记录
            addRoleStToTeam(comTeam, st);
            addUserToTeamChannel(comTeam.teamCode, false, teammateRoleId, sid);
        }
        sendMessageToUsersWithSuc(PUSH_ROUTE.TEAM_JOIN, { teamInfo: comTeam }, teammates.map(t => { return { uid: t.roleId, sid: t.sid } }));
    }
}

export async function addToSearchingTeams(roleId: string, sid: string, lvs: number[]) {
    let teamCodes = await getCreatedTeamByLv(lvs);
    if(teamCodes.length <= 0) return false;

    let {lv, teamCode} = getRandSingleEelm(teamCodes);
    let battleServer = await getComTeamSidByCode(lv, teamCode);
    if(!battleServer) return false;

    return await pinus.app.rpc.battle.comBattleRemote.addToSearchingTeams.toServer(battleServer, teamCode, roleId, sid);
}

export async function _addToSearchingTeams(teamCode: string, roleId: string, sid: string) {
    let teamMap = pinus.app.get('teamMap');
    let teamStatus: MemComBtlTeam = teamMap && teamMap.get(teamCode);
    if(!teamStatus) return false;
    if(!validToJoin(teamStatus, roleId)) return false;
    const st = await getValidTeammateRoleSt(roleId, teamStatus.roleIds, teamStatus.ceLimit, sid);
    if (!st) return false;

    addRoleStToTeam(teamStatus, st);
    await rmRoleFromQueue(roleId, sid); // 匹配成功后删除redis中该用户的匹配记录
    addUserToTeamChannel(teamCode, false, roleId, sid);
    sendMessageToTeam(teamCode, PUSH_ROUTE.TEAM_JOIN, { teamInfo: teamStatus });
    await ComBattleTeamModel.addRole(teamCode, st);
}

/**
 * @description 判断队伍是否处于可加入状态
 * @export
 * @param {MemComBtlTeam} comTeam
 * @param {string} [roleId=''] 要加入的玩家 id
 * @returns
 */
export function validToJoin(comTeam: MemComBtlTeam, roleId = '') {
    return comTeam && comTeam.roleIds && comTeam.status === COM_TEAM_STATUS.DEFAULT && comTeam.roleIds.length < 3 && comTeam.roleIds.indexOf(roleId) === -1;
}

/**
 * @description 判断队伍是否处于可满员状态
 * @export
 * @param {MemComBtlTeam} comTeam
 * @returns
 */
export function teamIsFullToStart(comTeam: MemComBtlTeam) {
    return comTeam && comTeam.roleIds && comTeam.status === COM_TEAM_STATUS.DEFAULT && comTeam.roleIds.length === 3;
}

/**
 * @description 添加指定数量的机器人到队伍
 * @export
 * @param {MemComBtlTeam} comTeam
 * @param {number} roleCe 真实玩家战力，用来做机器人战力基准
 * @param {number} roleLv 真实玩家等级，用来做机器人等级基准
 * @param {number} [count=1]
 */
export async function addRobotsToTeam(comTeam: MemComBtlTeam, roleId: string, roleCe: number, roleLv: number, teamMap: Map<string, MemComBtlTeam>, teamDisTimer: Map<string, NodeJS.Timer>, count = 1) {
    const { teamCode, roleStatus } = comTeam;
    let hasCap = roleStatus.findIndex(cur => cur.isCap) != -1;
    const { robotStArr, robotIdArr } = getRandComBtlRobots(roleCe, comTeam.ceLimit, roleLv, count);
    for (let st of robotStArr) {
        if(!hasCap) {
            st.isCap = true;
            hasCap = true;
        }
        addRoleStToTeam(comTeam, st);
        await ComBattleTeamModel.addRole(teamCode, st);
    }
    sendMessageToTeam(teamCode, PUSH_ROUTE.TEAM_JOIN, { teamInfo: comTeam })
    setDismissTimer(comTeam, teamMap, roleId, teamDisTimer);
}

/**
 * @description 在不同的时间加入机器人
 * @export
 * @param {MemComBtlTeam} comTeam
 * @param {RoleType} roleInfo
 * @param {Map<string, MemComBtlTeam>} teamMap
 * @param {Map<string, NodeJS.Timer>} teamDisTimer
 */
export async function addRobotsLater(comTeam: MemComBtlTeam, roleInfo: RoleType, teamMap: Map<string, MemComBtlTeam>, teamDisTimer: Map<string, NodeJS.Timer>) {
    const teamStatus = comTeam;
    const { teamCode, lv: blueprtLv } = teamStatus;
    const { roleId, lv } = roleInfo;
    let { topLineupCe = 1000 } = roleInfo;

    if (validToJoin(teamStatus)) { // 如果可以匹配
        await setCreatedTeamToRedis(teamCode, blueprtLv);

        const robotCnt = 3 - teamStatus.roleIds.length;
        for (let robotIdx = 0; robotIdx < robotCnt; robotIdx++) {
            const joinTime = getRandValueByMinMax(COM_BTL_CONST.MIN_CAP_TIME, COM_BTL_CONST.MAX_CAP_TIME, 0);
            setTimeout(async () => {
                const curTeamStatus = teamMap.get(teamCode);
                if (validToJoin(curTeamStatus)) {
                    await addRobotsToTeam(curTeamStatus, roleId, topLineupCe, lv, teamMap, teamDisTimer, 1);
                }
            }, joinTime);
        }
    }
}

/**
 * @description 从数组里找出第一个不在黑名单的队伍
 * @export
 * @param {ComBattleTeamType[]} teams 队伍数组
 * @param {string} roleId 要加入的玩家 id
 * @returns
 */
export async function oneTeamNotInBlack(teams: ComBattleTeamType[], roleId: string) {
    for (let team of teams) {
        let { roleIds } = team;
        const inBlackList = await teammateInBlackList(roleId, roleIds);
        if (!inBlackList) {
            return team;
        }
    }
    return null;
}

// export async function setComBtlOnUserLeave(roleId: string, teamCode: string) {
//     let res = dispatch(teamCode, pinus.app.getServersByType('battle'), 'battle');
//     await pinus.app.rpc.battle.comBattleRemote.leaveFromBattle.toServer(res.id, roleId, teamCode);
// }

export async function checkHasMyTeam(roleId: string) {
    return await ComBattleTeamModel.checkHasTeamByRoleId(roleId);
}

export async function checkTeamStatusAndSend(teamCode: string, roleId: string, sid: string) {
    let team = await ComBattleTeamModel.getTeamByCode(teamCode);
    if(team && (team.status == 2|| team.status == 3)) {
        await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.TEAM_COMPLETE, { teamCode, result: team.status == 2? true: false, timeout: team.timeout }, sid);
    }
}