
import { HeroModel } from '../db/Hero';
import Role, { RoleModel, RoleType } from '../db/Role'
import { getLvByExp, getExpByLv, gameData, getDicApByLv } from '../pubUtils/data';
import { updateUserInfo } from './redisService';
import { switchOnFunc } from './funcSwitchService';
import { FUNC_OPT_TYPE, TASK_TYPE, WAR_TYPE } from '../consts';
import { BackendSession } from 'pinus';
import { REDIS_KEY } from '../consts';
import { Rank } from './rankService';
import { checkActivityTask, checkTask } from './taskService';
import { accomplishTask } from '../pubUtils/taskUtil';
import { RScriptRecordModel } from '../db/RScriptRecord';
import { setAp } from './actionPointService';

export async function roleLevelup(roleId: string, kingExp: number, session: BackendSession) {
    const serverId = session.get('serverId');
    const sid = session.get('sid');
    const funcs = session.get('funcs');
    let role = await RoleModel.findByRoleId(roleId);
    let { lv = 1, exp = 0 } = role;
    let canGetExp = lv < gameData.maxPlayerLv.max; // 当主公超过最大级后，挑战结算不再获得经验值
    let newExp = canGetExp ? exp + kingExp : exp;
    let newLv = getLvByExp(newExp);
    // 等级超过最高级之后，经验依然可以稍微溢出一些，以备下一次提升等级
    // let nextExpObj = getExpByLv(newLv + 1);
    // let curExpObj = getExpByLv(newLv);
    // if(curExpObj && !nextExpObj && newExp > curExpObj.sum) {
    //     newExp = curExpObj.sum;
    // }

    role = await RoleModel.levelup(roleId, newLv, newExp);
    if (newLv > lv) { // 升级
        await switchOnFunc(roleId, FUNC_OPT_TYPE.LEVEL_UP, newLv, session);
        await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'lv', value: newLv }]);

        let r = new Rank(REDIS_KEY.USER_LV, { serverId: role.serverId });
        await r.setRankWithRoleInfo(roleId, newLv, Date.now(), role);

        // 任务
        await checkTask(roleId, session.get('sid'), session.get('funcs'), TASK_TYPE.ROLE_LV, newLv, false, {});
        //成长任务
        await checkActivityTask(serverId, session.get('sid'), session.get('funcs'), roleId, TASK_TYPE.ROLE_LV, newLv);

    }
    let actordata: { lv: number, exp: number, getExp: number, mostExp: number }[] = [];
    for (let i = lv; i <= newLv; i++) {
        let lvObj = getExpByLv(i);

        if (!lvObj) break;
        let { sum, cur } = lvObj;
        let lastSum = sum - cur;
        // console.log(sum, cur, lastSum, exp, newExp);

        let startExp = exp > lastSum ? exp - lastSum : 0;
        let getExp = newExp > sum ? cur - startExp : newExp - lastSum - startExp;
        actordata.push({
            lv: i,
            exp: startExp, // 升级前经验
            getExp: getExp > 0 ? getExp : 0, // 获得的经验
            mostExp: cur
        });
        if(i != lv) { // 升级加体力
            let dicAp = getDicApByLv(i);
            await setAp(roleId, i, dicAp.restoreAp, sid, funcs);
        }
    }

    return { actordata, lv: newLv, exp: newExp, kingExp: newExp - exp };
}


export async function checkBattleHeroes(roleId: string, seqIds: Array<number> = []) {
    let heroes: number[] = [];
    let flag = true;
    // if (seqIds.length <= 0) flag = false;

    const findHeroes = await HeroModel.findBySeqIdRange(seqIds, roleId);
    if (findHeroes.length != seqIds.length) flag = false;
    for (let seqId of seqIds) {
        let hero = findHeroes.find(cur => cur.seqId == seqId);
        if (!hero) {
            flag = false; break;
        }
        heroes.push(hero.hid);
    }
    return { isOK: flag, heroes };
}

export async function checkBattleHeroesByHid(roleId: string, heroes: Array<number> = []) {
    let flag = true;
    // if (heroes.length <= 0) flag = false;

    const findHeroes = await HeroModel.findByHidRange(heroes, roleId);
    if (findHeroes.length != heroes.length) flag = false;
    for (let hid of heroes) {
        let hero = findHeroes.find(cur => cur.hid == hid);
        if (!hero) flag = false;
    }
    return { isOK: flag, heroes: findHeroes };
}

export async function updateWarStar(roleId: string, battleId: number, warType: number, star: number) {
    let role = await RoleModel.findByRoleId(roleId);
    let { warStar = new Array<{ id: number, warType: number, star: number }>() } = role;
    let curStar = warStar.find(cur => cur.id == battleId);
    let result: Role;
    if (curStar) {
        if (star > curStar.star) {
            result = await Role.updateWarStar(roleId, battleId, star);
        }
    } else {
        result = await RoleModel.pushWarStar(roleId, battleId, warType, star);
    }
    return result
}

export async function getBattleListOfMain(role: RoleType) {
    let types = [ WAR_TYPE.NORMAL, WAR_TYPE.VESTIGE, WAR_TYPE.MAIN_ELITE ];
    let result = [];
    for(let type of types) {
        let list = await getBattleList(role, type);
        result.push({ type, list });
    }
    return result
}

export async function getBattleList(role: RoleType, type: number) {
    let { roleId, warStar } = role;

    let scripts = await RScriptRecordModel.findbyRole(roleId, type);

    let result = []; // 去重
    for (let { battleId, scriptBefore = '', scriptAfter = '' } of scripts) {

        result.push({
            battleId,
            status: 0,
            star: 0,
            scriptBefore,
            scriptAfter
        });
    }
    for (let { id, star, warType } of warStar) {
        if (warType == type) {
            let curResult = result.find(cur => cur.battleId == id);
            if (curResult) {
                curResult.status = 1;
                curResult.star = star;
            } else {
                result.push({
                    battleId: id,
                    status: 1,
                    star,
                    scriptBefore: '',
                    scriptAfter: ''
                });
            }
        }
    }
    result = result.sort((a, b) => { return a.battleId - b.battleId });
    return result;
}