import { getRandEelm, } from '../pubUtils/util';
import { EPlace, Stone } from "../db/Hero";
import { gameData, getArtifactWithQuality, getDicArtifactLvByPlanId, getDicArtifactQualityByStage, getJewelConditionByLvAndSeId, getNextArtifact, getNextArtifactQuality, getRandEffectByGroupAndLevel } from "../pubUtils/data";
import { JewelType, RandSe } from '../db/Jewel';
import { DicRandomEffectPool } from '../pubUtils/dictionary/DicRandomEffectPool';
import { getJewelRandSe } from './role/rewardService';
import { ArtifactModelType } from '../db/Artifact';
import { STATUS } from '../consts';
import { ItemInter } from '../pubUtils/interface';
import { combineItems } from './role/util';

export function getRandSeResult(id: number, randSe: RandSe[], originSe: RandSe[] = [], originId?: number) {
    let { randomEffect, effectCount, lv } = gameData.jewel.get(id);

    let chosen = randSe.filter(cur => cur.locked).map(cur => cur.seid); // 上一轮随机出来的

    let newRandSe: RandSe[] = []; // 随机结果
    let startId = 0;
    for(let { id, seid } of originSe) {
        let { lv: oldLv } = gameData.jewel.get(originId);
        // 替换成高阶
        let dicRandomEffect = gameData.randomEffectPool.get(seid);
        let nextRandEffect: DicRandomEffectPool;
        let targetRandLv = dicRandomEffect.level + lv - oldLv;
        while(!nextRandEffect) {
            nextRandEffect = getRandEffectByGroupAndLevel(dicRandomEffect.group, targetRandLv);
            targetRandLv--;
            if(targetRandLv < 0) break;
        }
        let newSeid = nextRandEffect? nextRandEffect.id: seid;
        newRandSe.push(getJewelRandSe(id, newSeid));
        chosen.push(newSeid);
        startId++;
    }

    let randomResult: number[] = getRandEelm(randomEffect.filter(cur => !chosen.includes(cur)), effectCount); // 随机出的结果
    if(randomResult.length < effectCount) { // 去上轮之后不够，把上轮加入
        let chosenRandom = getRandEelm(chosen, effectCount - randomResult.length);
        randomResult.push(...chosenRandom);
    }
    if(randomResult.length < effectCount) { // 还是不够
        let allRandom = getRandEelm(randomEffect, effectCount - randomResult.length);
        randomResult.push(...allRandom);
    }

    // console.log('##### getRandSeResult', startId, effectCount)

    for (let i = startId; i < effectCount; i++) {
        if(randSe[i]) {
            if(randSe[i] && randSe[i].locked) {
                newRandSe.push(randSe[i]);
            } else {
                newRandSe.push(getJewelRandSe(randSe[i].id, randomResult[i]));
            }
        } else {
            newRandSe.push(getJewelRandSe(i + 1, randomResult[i]));
        }
    }
    if(newRandSe.length < randSe.length) {
        newRandSe.push(...randSe.splice(newRandSe.length));
    }

    return newRandSe
}

export function updateStone(origin: Stone[], id: number, target: number) {
    let newStones: Stone[] = [];
    let hasTarget = false;
    for(let stone of origin) {
        if(stone.id == id) {
            newStones.push({ id, stone: target });
            hasTarget = true;
        } else {
            newStones.push(stone);
        }
    }
    if(!hasTarget) {
        newStones.push({ id, stone: target });
    }
    return newStones;
}

export function updateEplace(eplace: EPlace[], eplaceId: number, update: Partial<EPlace>) {
    let newEplace: EPlace[] = [];
    let newEquip: EPlace;
    let updatedEplace: Partial<EPlace>[] = [];
    for(let equip of eplace) {
        if(equip.id == eplaceId) {
            newEplace.push({ ...equip, ...update });
            newEquip = { ...equip, ...update };
            updatedEplace.push({ id: equip.id, equipId: equip.equipId, ...update });
        } else {
            newEplace.push(equip);
        }
    }
    return {newEplace, updatedEplace, newEquip };
}

export function updateEplaces(eplace: EPlace[], update: Map<number, Partial<EPlace>>) {
    let newEplace: EPlace[] = [];
    let updatedEplace: Partial<EPlace>[] = [];
    for(let equip of eplace) {
        if(update.has(equip.id)) {
            newEplace.push({ ...equip, ...update.get(equip.id) });
            updatedEplace.push({ id: equip.id, equipId: equip.equipId, ...update.get(equip.id) });
        } else {
            newEplace.push(equip);
        }
    }
    return {newEplace, updatedEplace};
}

/**
 * 检查天晶石能否装备上这个装备
 * @param equip 
 * @param jewel 
 */
export function checkJewelCanPutOnEquip(equip: EPlace, jewel: JewelType) {
    // 位置是否满足
    let dicJewel = gameData.jewel.get(jewel.id);
    if(!dicJewel || dicJewel.eplaceId != equip.id) return false;
    // 品质是否满足
    let dicEquipQualityExtra = gameData.equipQualityExtra.get(equip.quality);
    if(!dicEquipQualityExtra || dicEquipQualityExtra.jewelCnt == 0) return false;
    return true
}

export function checkStoneCanPutOnEquip(equip: EPlace, id: number, stone: number) {
    if(stone == 0) return true; // 卸载
    // 位置是否满足
    let dicStone = gameData.stone.get(stone);
    if(!dicStone || dicStone.eplaceId != equip.id) return false;
    // 品质是否满足
    let dicEquipQualityExtra = gameData.equipQualityExtra.get(equip.quality);
    if(!dicEquipQualityExtra || dicEquipQualityExtra.stoneCnt < id) return false;
    return true;
}

export function isLocked(randSe: RandSe[]) {
    for(let { locked } of randSe) {
        if(locked) return true;
    }
    return false;
}

export function getEquipById(oldEplace: EPlace[], newEplace: EPlace[], eplaceId: number) {
    let oldEquip = oldEplace.find(cur => cur.id == eplaceId)||new EPlace(eplaceId, 0);
    let newEquip = newEplace.find(cur => cur.id == eplaceId)||new EPlace(eplaceId, 0);
    return { oldEquip, newEquip }
}

export function getJewelByEquip(equip: EPlace, jewels: JewelType[]) {
    if(!equip) return null
    let jewel = jewels.find(cur => cur && cur.seqId == equip.jewel);
    return jewel
}

export function isRandSeUnLock(jewelId: number, randSeId: number, stones: Stone[]) {
    let dicJewel = gameData.jewel.get(jewelId);
    let dicJewelCondition = getJewelConditionByLvAndSeId(dicJewel.lv, randSeId);
    let stoneCnt = 0, stoneLv = 0;
    for(let { stone } of stones) {
        let dicStone = gameData.stone.get(stone);
        if(dicStone) {
            stoneCnt++;
            stoneLv += dicStone.lv;
        }
    }
    return stoneCnt >= dicJewelCondition.stoneCnt && stoneLv >= dicJewelCondition.stoneLv;
}

export function checkArtifactCanCompose(originArtifactId: number, artifact: ArtifactModelType) {
    if(!artifact) return STATUS.ARTIFACT_IS_NOT_FIND;
    // 宝物表
    let dicArtifact = gameData.artifact.get(artifact.artifactId);
    if(!dicArtifact) return STATUS.ARTIFACT_IS_NOT_FIND;
    // 宝物品质表
    let dicArtifactQuality = getDicArtifactQualityByStage(dicArtifact.quality, dicArtifact.qualityStage);
    if(!dicArtifactQuality) return STATUS.DIC_DATA_NOT_FOUND;
    // 狗粮不可装备
    if(artifact.hid > 0) return STATUS.ARTIFACT_IS_EQUIPED;
    // 狗粮不可强化
    if(artifact.lv > 0) return STATUS.ARTIFACT_CAN_NOT_STRENGTHEN;

    // 合成目标
    let dicTargetArtifactQuality = getNextArtifact(originArtifactId);
    if(!dicTargetArtifactQuality) return STATUS.DIC_DATA_NOT_FOUND;
    
    // 检查狗粮品质
    if(dicTargetArtifactQuality.materialId != dicArtifactQuality.uniqId) return STATUS.ARTIFACT_MATERIAL_QUALITY_ERR;
    // 检查是否同名
    if(dicTargetArtifactQuality.materialGroup == 1 && dicTargetArtifactQuality.group != dicArtifact.group) return STATUS.ARTIFACT_MATERIAL_QUALITY_ERR;
    return STATUS.SUCCESS;
}

export function getRebuildConsume(artifacts: ArtifactModelType[]) {
    let usedConsumes: ItemInter[] = [];
    for(let artifact of artifacts) {
        let dicArtifact = getArtifactWithQuality(artifact.artifactId);
        if(!dicArtifact) continue;
        if(!hasArtifactStrength(artifact)) continue;
        
        for(let lv = 1; lv <= artifact.lv; lv++) {
            let dicArtifactLv = getDicArtifactLvByPlanId(dicArtifact.lvAttrPlan, lv);
            usedConsumes.push(...dicArtifactLv.consumes);
        }
        for(let stage = 0; stage < artifact.qualityStage; stage++) {
            let dicArtifactQuality = getDicArtifactQualityByStage(dicArtifact.quality, stage);
            let dicNextArtifactQuality = gameData.artifactQualityById.get(dicArtifactQuality?.nextId);
            if(!dicNextArtifactQuality) continue;
            let dicMaterialArtifactQuality = gameData.artifactQualityById.get(dicNextArtifactQuality.materialId);
            if(!dicMaterialArtifactQuality) continue;
            
            let consumes = dicMaterialArtifactQuality.generalItem.map(({id, count}) => ({ id, count: count * dicNextArtifactQuality.materialCnt}));
            usedConsumes.push(...consumes);
        }
    }
    return combineItems(usedConsumes);
}

// 宝物是否有养成
export function hasArtifactStrength(artifact: ArtifactModelType) {
    if(!artifact) return false;
    return artifact.lv >= 1 || artifact.qualityStage > 0;
}