

import { HeroModel, HeroType, } from '../db/Hero';
import { ItemModel } from '../db/Item';
import { EquipModel, RandSe, Holes, RandMain, equipUpdate } from './../db/Equip';
import { gameData, getQuenchByQualityAndGrade, getQuenchGradeByValue } from './data';
import { RANDOM_SE_COUNT, ITID, CURRENCY_BY_TYPE, CURRENCY_TYPE, ROLE_SELECT, FIGURE_UNLOCK_CONDITION, CONSUME_TYPE, HERO_SYSTEM_TYPE, TASK_TYPE } from '../consts';
import { getRandValueByMinMax, getRandEelm } from './util';

import { findWhere } from 'underscore';
import { RoleModel, RoleType, } from '../db/Role';
import { Figure } from '../domain/dbGeneral';
import { getTimeFun } from './timeUtil';
import { reCalAllHeroCe } from './playerCe';
import { checkTaskWithEquip } from './taskUtil';
// import { checkTask, checkTaskWithHeroes, checkTaskWithEquip, accomplishTask } from './taskUtil';
import { SkinModel, } from '../db/Skin';
import { TaskListReturn } from '../domain/roleField/task';

/**
 * 只插入皮肤，不管那么多的
 * @param roleId 
 * @param roleName 
 * @param skinId 
 * @returns 
 */
export async function increaseSkin(roleId:string, roleName: string, skinId: number) {
    let dicSkin = gameData.fashion.get(skinId);
    if (!dicSkin) return false;

    let skin = await SkinModel.increaseSkin(roleId, skinId, { roleId, roleName, id: skinId, skinName: dicSkin.name, hid: dicSkin.actorId, skinId: dicSkin.heroId });
    if(!skin) return false; // 插入失败
    return skin
}

/**
 * 添加皮肤
 * @param roleId 玩家id 
 * @param roleName 玩家名
 * @param id 皮肤id
 * @param hero 武将，如果已经查询过这个武将就不用再查询一次，主意要select skins字段
 * @returns {{ hero, figureInfo, calAllHeroResult }} hero：添加皮肤后的武将 figureInfo: 触发头像添加信息 calAllHeroResult：全局战力加成后结果
 */
export async function addSkin(roleId: string, roleName: string, skinId: number, enable: boolean, hero?: HeroType) {
    let skin = await increaseSkin(roleId, roleName, skinId);
    if(!skin) return false;

    if(skin.hid && !hero) hero = await HeroModel.findByHidAndRole(skin.hid, roleId);
    let condition = { type: FIGURE_UNLOCK_CONDITION.GET_SKIN, paramSkinId: skinId };
    let figureInfo = await unlockFigure(roleId, [condition]); // 解锁头像
    let calAllHeroResult = await reCalAllHeroCe(HERO_SYSTEM_TYPE.ADD_SKIN, roleId, {}, [skinId]); // 全局加成

    if (hero) { // 有武将的，将皮肤链接到武将上
        if (!findWhere(hero.skins, { id: skinId })) {
            hero.skins.push({ id: skinId, skin: skin._id, enable, skinId: skin.skinId });
            await HeroModel.updateHeroInfo(roleId, hero.hid, hero);
        }
        return { hero, figureInfo, calAllHeroResult };
    } else {
        return { hero: null, figureInfo, calAllHeroResult }
    }
}

export async function addBags(roleId: string, roleName: string, datas: { id: number, count: number }[]) {
    let items: { id: number, count: number }[] = [];
    for(let data of datas) {
        let item = await addBag(roleId, roleName, data);
        items.push(item)
    }
    return { items }
}

export async function addBag(roleId: string, roleName: string, data: { id: number, count: number }) {
    let { id, count } = data;
    let { name: itemName, itid, hid } = gameData.goods.get(id);
    let { type } = ITID.get(itid);

    let item = await ItemModel.increaseItem(roleId, id, count, { roleId, roleName, itemName, id, type, hid });
    return { id: item.id, count: item.count };
}


export async function addEquips(roleId: string, roleName: string, weapons: { id: number, hid?: number }[]) {
    let equipInfos: equipUpdate[] = [];
    for(let weapon of weapons) {
        let info = await getAddEquipInfo(roleId, roleName, weapon);
        equipInfos.push(info);
    }

    const equips = await EquipModel.createEquips(roleId, equipInfos);
    let pushMessages: TaskListReturn[] = [];
    // 任务
    for(let equip of equips) {
        let pushMessage = await checkTaskWithEquip(roleId, TASK_TYPE.EQUIP_SUIT, equip);
        pushMessages = [...pushMessages, ...pushMessage];
    }

    return { equips, pushMessages }
}

export async function getAddEquipInfo(roleId: string, roleName: string, weapon: { id: number, hid?: number }) {
    let { id, hid = 0 } = weapon;
    let { name, quality, suitId, hole, randomEffect, itid, goodsAbility } = gameData.goods.get(id);
    let { type } = ITID.get(itid);

    // 随机属性
    let randomNum = RANDOM_SE_COUNT.get(quality);
    let randomResult: number[] = getRandEelm(randomEffect, randomNum);

    let randSe: Array<RandSe> = randomResult.map((id: number, i: number) => {
        let random = gameData.randomEffectPool.get(id)
        let rand = 0;
        if (random.id > 0) rand = getRandValueByMinMax(random.Min, random.Max, 0);
        return {
            id: i + 1,
            seid: random.id,
            rand,
            locked: false
        };
    });

    let randRange = 0;

    // 淬火品相
    let randMain: RandMain[] = [];
    let grade = 0;
    for(let [ attrId, attrValue ] of goodsAbility) {
        if(attrValue > 0) {
            let { randMin, randMax } = getQuenchByQualityAndGrade(quality, grade);
            let rand = getRandValueByMinMax(randMin, randMax, 0);
            // console.log(quality, grade, rand)
            grade = getQuenchGradeByValue(quality, rand);
            randMain.push({
                id: attrId,
                rand
            });
        }
    }


    let holes = new Array<Holes>();
    for (let i = 0; i < hole; i++) {
        holes.push({ id: i + 1, isOpen: false, jewel: 0 });
    }

    return { roleId, roleName, id, name, quality, suitId, randRange, ePlaceId: type, randSe, holes, hid, grade, randMain };
}

/**
 * @description 获取元宝物品 { id, count }
 * @param count 元宝数量
 */
export function getGoldObject(count: number) {
    return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD), count };
}

/**
 * @description 获取金币物品 { id, count }
 * @param count 元宝数量
 */
export function getCoinObject(count: number) {
    return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.COIN), count };
}

/**
 * @description 获取体力物品 { id, count }
 * @param count 体力数量
 */
 export function getApObject(count: number) {
    return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.ACTION_POINT), count };
}
/**
 * @description 获取友情点物品 { id, count }
 * @param count 友情点数量
 */
export function getFriendPointObject(count: number) {
    return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.FRIEND_POINT), count };
}

/**
 * @description 获取功勋物品 { id, count }
 * @param count 功勋数量
 */
export function getHonourObject(count: number) {
    return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.HONOUR), count };
}

/**
 * 返回 解锁头像/相框
 * @param conditions 解锁条件
 * @param role 如果已查询过role表就直接可以使用
 */
 export function unlockFigureWithoutSave(conditions: { type: number, paramHid?: number, paramFavourLv?: number, paramSkinId?: number }[], role: RoleType) {

    let { heads, frames, spines } = role;
    let figureInfo = { heads: new Array<Figure>(), frames: new Array<Figure>(), spines: new Array<Figure>() };
    for (let { type, paramHid, paramFavourLv, paramSkinId } of conditions) {
        let canUnLockList = gameData.figureCondition.get(type);
        if (canUnLockList) {
            for (let { id, params, gid } of canUnLockList) {
                let flag = false; // 是否达成条件
                if (type == FIGURE_UNLOCK_CONDITION.GET_HERO) {
                    let [hid] = params;
                    if (paramHid == hid) flag = true;
                } else if (type == FIGURE_UNLOCK_CONDITION.HERO_FAVOR) {
                    let [hid, favourLv] = params;
                    if (paramHid == hid && paramFavourLv >= favourLv) flag = true;
                } else if (type == FIGURE_UNLOCK_CONDITION.GET_SKIN) {
                    let [id] = params;
                    if (paramSkinId == id) flag = true;
                }
                if (!flag) continue;
                let dicGood = gameData.goods.get(gid);
                if (!dicGood) continue;
                let dicItid = ITID.get(dicGood.itid);
                if (!dicItid) continue;

                if (dicItid.type == CONSUME_TYPE.HEAD) {
                    let figure = unlockSingleFigure(heads, gid, false, id);
                    if (figure && figure.unlocked) figureInfo.heads.push(figure);
                } else if (dicItid.type == CONSUME_TYPE.FRAME) {
                    let figure = unlockSingleFigure(frames, gid, false, id);
                    if (figure && figure.unlocked) figureInfo.frames.push(figure);
                } else if (dicItid.type == CONSUME_TYPE.SPINE) {
                    let figure = unlockSingleFigure(spines, gid, false, id);
                    if (figure && figure.unlocked) figureInfo.spines.push(figure);
                } else {
                    continue;
                }

            }

        }
    }
    return { figureInfo, heads, frames, spines };
}

/**
 * 解锁头像/相框
 * @param roleId 玩家id
 * @param conditions 解锁条件
 * @param role 如果已查询过role表就直接可以使用
 */
export async function unlockFigure(roleId: string, conditions: { type: number, paramHid?: number, paramFavourLv?: number, paramSkinId?: number }[], role?: RoleType) {
    if (!role || !role.heads || !role.frames) {
        role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.GET_HEADS);
    }
    let { figureInfo, heads, frames, spines } = unlockFigureWithoutSave(conditions, role);
    role = await RoleModel.updateRoleInfo(roleId, { heads, frames, spines });
    return figureInfo;
}


// 直接获得形象/相框
export async function addFigure(roleId: string, ids: number[]) {
    let role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.GET_HEADS);

    if (!role) return false;
    let { heads, frames, spines } = role;

    let figureInfo = { heads: [], frames: [], spines: [] };
    for (let gid of ids) {
        let dicGoods = gameData.goods.get(gid);
        if (!dicGoods) continue;
        let dicItid = ITID.get(dicGoods.itid);
        if (!dicItid) continue;

        if (dicItid.type == CONSUME_TYPE.HEAD) {
            let figure = unlockSingleFigure(heads, gid, true);
            if (figure && figure.unlocked) figureInfo.heads.push(figure);
        } else if (dicItid.type == CONSUME_TYPE.FRAME) {
            let figure = unlockSingleFigure(frames, gid, true);
            if (figure && figure.unlocked) figureInfo.frames.push(figure);
        } else if (dicItid.type == CONSUME_TYPE.SPINE) {
            let figure = unlockSingleFigure(spines, gid, true);
            if (figure && figure.unlocked) figureInfo.spines.push(figure);
        } else {
            continue;
        }
    }

    role = await RoleModel.updateRoleInfo(roleId, { heads, frames, spines });
    return figureInfo;
}

/**
 * 根据物品id解锁/获得玩家数据
 * @param dbFigures 数据库内字段
 * @param id 物品id
 * @param unlockDirect 是否不计算解锁条件直接解锁
 * @param conditionId 条件id
 */
function unlockSingleFigure(dbFigures: Figure[], id: number, unlockDirect = false, conditionId?: number) {
    let figure = dbFigures.find(cur => cur.id == id);
    if (!figure) {
        figure = new Figure(id, false);
        dbFigures.push(figure);
    }
    if (figure.unlocked) return; // 已解锁过
    if (!figure.unlockedId) figure.unlockedId = new Array<number>();

    let dicGoods = gameData.goods.get(id);

    let hasUnlockedAll = true;
    if (!unlockDirect) { // 不能直接获得，需要通过type解锁
        if (figure.unlockedId.includes(conditionId)) return;

        figure.unlockedId.push(conditionId);

        for (let { id: cid } of dicGoods.condition) {
            if (!figure.unlockedId.includes(cid)) {
                hasUnlockedAll = false; break;
            }
        }
    }
    if (hasUnlockedAll) {
        figure.unlocked = true;
        delete figure.unlockedId;

        if (dicGoods.timeLimit) {
            figure.time = <number>getTimeFun().getAfterDay(dicGoods.timeLimit); // timeLimit天以后 
        }
    }

    return figure
}

// async function getSkinsOfThisHero(roleId: string, roleName: string, hid: number, initialSkin: number, allSkins?: SkinType[]) {
//     if(!allSkins) allSkins = await SkinModel.findbyRoleAndHid(roleId, hid);
//     let skin = await increaseSkin(roleId, roleName, initialSkin);
//     if(skin) allSkins.push(skin);
//     let skins: { id: number, skin: string, enable: boolean }[] = [];
//     for(let skin of allSkins) {
//         skins.push({ id: skin.id, skin: skin._id, enable: skin.id == initialSkin });
//     }

//     return skins
// }

export function combineFigureInfo(figureInfos: { heads: Figure[], frames: Figure[], spines: Figure[] }[]) {
    let figureInfo = { heads: new Array<Figure>(), frames: new Array<Figure>(), spines: new Array<Figure>() };
    for(let {heads, frames, spines} of figureInfos) {
        for(let head of heads) {
            figureInfo.heads.push(head);
        }
        for(let frame of frames) {
            figureInfo.frames.push(frame);
        }
        for(let spine of spines) {
            figureInfo.spines.push(spine);
        }
    }
    return figureInfo;
}

export function transPiece(hid: number) {
    let dicHero = gameData.hero.get(hid);
    let count = gameData.heroTransPiece.get(dicHero.quality);
    return { pieceId: dicHero.pieceId, count }
}

// export class CreateHero {
//     roleId: string;
//     roleName: string;
//     serverId: number;

//     constructor(roleId: string, roleName: string, serverId: number) {

//     }
// }