import { FIGURE_UNLOCK_CONDITION, ITEM_CHANGE_REASON, REDIS_KEY, STATUS, TASK_TYPE, HERO_SYSTEM_TYPE, LINEUP_NUM, COUNTER, PUSH_ROUTE } from "../../consts";
import { SkinModel } from "../../db/Skin";
import { HeroModel, HeroSkin, HeroType, HeroUpdate } from "../../db/Hero";
import { SkinUpdate } from "../../db/Skin";
import { nowSeconds } from "../../pubUtils/timeUtil";
import { resResult } from "../../pubUtils/util";
import { CreateHeroParam, HeroParam, HeroShowParam } from "../../domain/roleField/hero";
import { pinus } from "pinus";
import { ItemInter, RewardInter } from "../../pubUtils/interface";
import { transPiece } from "./util";
import { addItems, unlockFigure, } from "./rewardService";
import { CounterModel } from "../../db/Counter";
import { calculateCes } from "../playerCeService";
import { RoleModel, RoleType, RoleUpdate } from "../../db/Role";
import { sendMessageToUserWithSuc } from "../pushService";
import { checkTaskInCreateHero } from "../task/taskService";
import { filterHeroes } from "../dataService";
import { pushGetHero } from "../sysChatService";

/**
 * 创建多个武将
 * @param roleId 
 * @param sid 
 * @param serverId 
 * @param heroInfo 
 */
 export async function createHeroes(roleId: string, roleName: string, sid: string, serverId: number, heroInfo: CreateHeroParam[], initRoleInfos?: RoleUpdate) {
    heroInfo = filterHeroes(heroInfo, obj => obj.hid, roleId);
    let hids = heroInfo.map(cur => cur.hid);
    let userHeroesMap = await HeroModel.findMapByHidRange(hids, roleId);

    let createHeroeInfos: CreateHeroParam[] = [], pieces: ItemInter[] = [];
    for (let h of heroInfo) {
        let heroCount = h.count || 1;
        if (userHeroesMap.has(h.hid)) {
            let { pieceId, count } = transPiece(h.hid);
            pieces.push({ id: pieceId, count: count * heroCount });
        } else {
            createHeroeInfos.push(h);
            userHeroesMap.set(h.hid, null);
            if (heroCount > 1) {
                let { pieceId, count } = transPiece(h.hid);
                pieces.push({ id: pieceId, count: count * (heroCount - 1) });
            }
        }
    }

    let resultHeroes: HeroType[] = [], resultItems: RewardInter[] = [], showHeroes: HeroShowParam[] = [];
    let figureConditions: { type: FIGURE_UNLOCK_CONDITION, paramHid: number }[] = [];
    let incHeroNum = 0;
    let skins: SkinUpdate[] = [];
    if (createHeroeInfos.length > 0) {
        let heroInfos = new Map<number, HeroUpdate>();
        for(let {hid, ...info} of createHeroeInfos) {
            let originSkins = await SkinModel.findbyRoleAndHid(roleId, hid);
            let initSkin = SkinModel.getInitInfo(hid);
            skins.push(initSkin); // 初始皮肤
            let seqId = await CounterModel.getNewCounter(COUNTER.HID) || -1;
            let initHeroSkins = [initSkin, ...originSkins].map((skin, index) => new HeroSkin(skin, index == 0));
            let initHero = HeroModel.getInitInfo(hid, { ...info, seqId, serverId, roleId, roleName, skins: initHeroSkins });
            heroInfos.set(hid, initHero);
            figureConditions.push({ type: FIGURE_UNLOCK_CONDITION.GET_HERO, paramHid: hid });
            incHeroNum ++;
        }
        await unlockFigure(sid, roleId, figureConditions);

        let roleUpdata: RoleUpdate = { heroNumUpdatedAt: nowSeconds() };
        if(initRoleInfos) {
            roleUpdata = { ...initRoleInfos, ...roleUpdata }
        }
        let { heroes } = await calculateCes(HERO_SYSTEM_TYPE.INIT, roleId, serverId, sid, heroInfos, roleUpdata, { heroNum: incHeroNum }, { isInitRole: !!initRoleInfos });
        for(let hero of heroes) {
            showHeroes.push(new HeroShowParam(hero));
            resultHeroes.push(hero);
            pushGetHero(roleId, roleName, serverId, hero);
        }

        await SkinModel.insertSkins(roleId, roleName, skins);
        sendMessageToUserWithSuc(roleId, PUSH_ROUTE.HERO_SKIN_CHANGE, getSkinPushMsg(resultHeroes, skins), sid);
        sendMessageToUserWithSuc(roleId, PUSH_ROUTE.HERO_UPDATE, { heroes: heroes.map(hero => new HeroParam(hero)) }, sid);
    }

    if (pieces.length > 0) {
        let goods = await addItems(roleId, roleName, sid, pieces, ITEM_CHANGE_REASON.HERO_TRANSFER_PIECE);
        resultItems = goods;
    }
    await checkTaskInCreateHero(serverId, roleId, sid, resultHeroes.length, resultHeroes);
    return { heroes: showHeroes, resultHeroes, goods: resultItems }
}

export async function createHero(roleId: string, roleName: string, sid: string, serverId: number, heroInfo: CreateHeroParam) {
    let result = await createHeroes(roleId, roleName, sid, serverId, [heroInfo]);
    return result;
}

function getSkinPushMsg(resultHeroes: HeroType[], skins: SkinUpdate[]) {
    let skinPushMessages: {heros: {skins: HeroSkin[], hid: number}[], skins: {id: number, hid: number, inc: number, reason: number }[]} = { heros: [], skins:[] }; // 皮肤推送信息
    for(let { hid, skins } of resultHeroes) {
        skinPushMessages.heros.push({ hid, skins });
    }
    for(let { id, hid } of skins) {
        skinPushMessages.skins.push({ id, hid, inc: 1, reason: ITEM_CHANGE_REASON.GET_HERO_UNLOCK_SKIN })
    }
    return skinPushMessages;
}