/**
 * entry触发后引起的下发
 */
import { getMails } from './mailService';
import { recentGuildMsgs, recentPrivateChatInfos, recentSysMsgs, recentWorldMsgs } from './chatService';
import { getCurTask, getPvpTask } from './taskService';

import { RoleType } from '../db/Role';
import { Application, FrontendOrBackendSession, pinus, RpcClient } from 'pinus';
import { resResult } from '../pubUtils/util';
import { STATUS, PUSH_BATCH, PUSH_INTERVAL, CONSUME_TYPE } from '../consts';
import { getAllShopList } from './shopService';
import { getGeneralRank, getRankFirstReward } from './rankService';
import { getFriendList, getApplyList } from './friendService';
import { getDailyBattleList } from './dailyBattleService';
import { getExpeditionStatus } from './expeditionService';
import { getTowerStatus, getHungupRewards, getTasks } from './battleService';
import { getAllAssistCnt } from './comBattleService';
import { getDungeonData } from './dungeonService';
import { PvpSeasonResultModel } from '../db/PvpSeasonResult';
import { nowSeconds, getZeroPoint } from '../pubUtils/timeUtil';
import { getGachaList, getVisitedHeroList } from './activity/gachaService';
import { getSchoolList } from './roleService';
import { addRoleToGuildChannel } from './chatChannelService';
import { getMyGuildInfo, getGuildWithRefActive, getUserGuildWithRefActive, getWishPool, getInvitationList } from './guildService';
import { getAuction } from './auctionService';
import { getGuildTrainInstance, getTrainBoxRewardsResult } from './guildTrainService';
import { BossInstanceModel } from '../db/BossInstance';
import { getBossInstanceInfo } from './guildBossService';
import { getEvent } from './eventSercive';
import { getBattleListOfMain } from './normalBattleService';
import { GuildType } from '../db/Guild';
import UserGuild, { UserGuildType } from '../db/UserGuild';
import { setMedianCe, getAllGuildActivityStatus } from './guildActivityService';
import { getAllOnlineRoles } from './redisService';
import Item from '../db/Item';
import { PvpDefenseModel } from '../db/PvpDefense';
import { getDonation } from './donateService';
import { refChallengeCnt } from './pvpService';

export async function pushData(hasInit: boolean, role: RoleType, session: FrontendOrBackendSession, pushType: 'entry' | 'refresh' = 'entry') {
    try {
        const { roleId } = role;
        const sid = session.get('sid');

        pushEntryStart(roleId, sid);
        // 军团
        const guildData = await getGuildEntryData(role, sid, session);
        let modules = [];
        if(!hasInit) {
            modules.push('lv', 'battle');
        } else {
            modules.push('lv', 'battle', 'rank', 'mail', 'friend', 'daily', 'expedition', 'tower', 'comBattle', 'dungeon', 'pvp', 'gacha', 'school', 'task', 'chat', 'event', 'guild');
            if (guildData.hasGuild) {
                modules.push('auction', 'train', 'boss', 'wishPool', 'guildActivity', 'donate');
            }
            modules.push('shop')
        }
        let notIncludeModule: string[] = [];
        if (pushType == 'refresh') { // 每天5点刷新的时候不推送
            notIncludeModule = ['rank', 'mail', 'school', 'auction', 'train', 'chat', 'battle'];
        }

        for (let type of modules) {
            if (notIncludeModule.indexOf(type) == -1) {
                let data = await getModuleData(type, { role, session }, guildData);
                if (data) {
                    pushEntryData(type, roleId, sid, data);
                }
            }
        }
        pushEntryEnd(roleId, sid);
    } catch (e) {
        console.error(e.stack);
    }
}

async function getModuleData(type: string, data: { role: RoleType, session: FrontendOrBackendSession }, guildData: { hasGuild: boolean, guild?: GuildType, userGuild?: UserGuildType, guildResult?: any } = { hasGuild: false }) {
    let { role, session } = data;
    const { roleId, serverId, roleName, guildCode } = role;
    let { hasGuild, guild, userGuild, guildResult } = guildData;
    switch (type) {
        case 'lv': 
            return role.lv;
        case 'shop': // 商店
            return await getAllShopList(roleId);
        case 'rank': // 排名
            const rewards = await getRankFirstReward(role, serverId);
            return { rewards }
        case 'mail': // 邮件
            return await getMails(roleId, serverId);
        case 'friend': // 好友
            const friendList = await getFriendList(role);
            const applyList = await getApplyList(roleId);
            return { friendList, applyList }
        case 'daily': // 每日
            return await getDailyBattleList(role);
        case 'expedition': // 远征
            return await getExpeditionStatus(roleId, roleName);
        case 'tower': // 镇念塔
            return await getTowerEntryData(role);
        case 'comBattle': // 寻宝
            const assistCnt = await getAllAssistCnt(roleId);
            const blueprts = await Item.findByRoleAndType(roleId, CONSUME_TYPE.BLUEPRT);
            return { assistCnt, blueprts }
        case 'dungeon': // 秘境
            return await getDungeonData(role);
        case 'pvp': // pvp
            return await getPvpEntryData(roleId);
        case 'gacha':
            const { gachaHasGuide } = role;
            const gachalist = await getGachaList(roleId);
            const visitList = await getVisitedHeroList(roleId);
            return { hasInit: !!gachaHasGuide, gachalist, visitList }
        case 'school':
            return await getSchoolList(roleId);
        case 'guild':
            let invitation = await getInvitationList(roleId, '');
            return { ...guildResult, invitation };
        case 'auction':
            return hasGuild ? await getAuction(guildCode, session) : null;
        case 'train':
            if (hasGuild) {
                let trainInstance = await getGuildTrainInstance(roleId, guild, userGuild);
                let trainBoxRewards = await getTrainBoxRewardsResult(guildCode);
                return { trainInstance, trainBoxRewards }
            }
        case 'boss':
            if (hasGuild) {
                return await getBossInstanceInfo(userGuild, guild);
            }
            return null;
        case 'wishPool':
            return hasGuild ? await getWishPool(userGuild) : null;
        case 'donate':
            if (hasGuild) {
                const { guildCode: code, donateCnt, receiveBoxs } = userGuild;
                let { donateFund, reports, donationLv } = await getDonation(code, serverId);
                return { receiveBoxs, donateFund, reports, donateCnt: donateCnt || 0, donationLv };
            }
        case 'task':
            let tasks = await getCurTask(role.roleId, session);
            let pvpTask = await getPvpTask(role.roleId);
            return {...tasks, pvpTask}
        case 'chat':
            const worldMsgs = await recentWorldMsgs(serverId);
            const sysMsgs = await recentSysMsgs(serverId);
            const guildMsgs = await recentGuildMsgs(guildCode);
            const recentPrivateChats = await recentPrivateChatInfos(roleId, roleName);
            return { worldMsgs, sysMsgs, guildMsgs, recentPrivateChats };
        case 'event':
            return await getEvent(role.eventStatus, roleId, roleName);
        case 'battle':
            return await getBattleListOfMain(role);
        case 'guildActivity':
            return getAllGuildActivityStatus();

        default:
            return null;
    }
}

function pushEntryData<T>(type: string, roleId: string, sid: string, param: T) {
    let uids = [{ uid: roleId, sid }];
    let data = { type };
    data[type] = param;
    pinus.app.channelService.pushMessageByUids('onEntryData', resResult(STATUS.SUCCESS, data), uids);//通知在线玩家练兵场重置，
}

function pushEntryStart(roleId: string, sid: string) {
    let uids = [{ uid: roleId, sid }];
    pinus.app.channelService.pushMessageByUids('onEntryDataStart', resResult(STATUS.SUCCESS), uids);//通知在线玩家练兵场重置，
}

function pushEntryEnd(roleId: string, sid: string) {
    let uids = [{ uid: roleId, sid }];
    pinus.app.channelService.pushMessageByUids('onEntryDataEnd', resResult(STATUS.SUCCESS), uids);//通知在线玩家练兵场重置，
}


/**
 * 镇念塔初始数据
 * @param role 
 */
async function getTowerEntryData(role: RoleType) {
    const { roleId } = role;
    const status = await getTowerStatus(role);
    const hungUp = await getHungupRewards(roleId);
    const tasks = await getTasks(role);
    if (hungUp.status == -1) {
        return { status, hungUp: {}, tasks }
    } else {
        return { status, hungUp: hungUp.data, tasks }
    }
}

/**
 * 获取是否存在pvp赛季奖励
 * @param roleId 
 */
async function getPvpEntryData(roleId: string) {
    let pvpDefense = await PvpDefenseModel.findByRoleId(roleId);
    if (pvpDefense) {
        let seasonEndTime = pinus.app.get('pvpSeasonEndTime');
        let refChallengeObj = refChallengeCnt(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime);
        let { challengeCnt } = refChallengeObj;
        let { receivedBox, score, hisScore } = pvpDefense;

        return { challengeCnt, score, hisScore, receivedBox }
    } else {
        return null
    }
}

/**
 * 获取军团信息，并加入军团频道
 * @param role 
 * @param sid 
 * @param session 
 */
async function getGuildEntryData(role: RoleType, sid: string, session: FrontendOrBackendSession) {

    if (role.hasGuild) {
        let userGuild = await getUserGuildWithRefActive(role.roleId);
        if (userGuild) {
            let guild = await getGuildWithRefActive(userGuild.guildCode, role.serverId);
            if (guild) {
                addRoleToGuildChannel(role.roleId, sid, userGuild.guildCode);

                let result = await getMyGuildInfo(role.roleId, sid, userGuild, guild, role.serverId, session);
                return { hasGuild: true, guild, userGuild, guildResult: result };
            }
        }
    }
    return { hasGuild: false }
}

export async function everydayRefresh() {
    let allOnlineUsers = await getAllOnlineRoles();
    let todayZeroPoint = getZeroPoint();
    let n = Math.ceil(allOnlineUsers.length / PUSH_BATCH); // 一共多少批
    // console.log(n)
    let i = -1;
    let interval = setInterval(() => {
        if (++i < n) {
            let users = allOnlineUsers.slice(i * PUSH_BATCH, (i + 1) * PUSH_BATCH - 1);
            for (let { roleId, sid } of users) {
                pinus.app.channelService.pushMessageByUids('onRefreshTime', resResult(STATUS.SUCCESS, {
                    todayZeroPoint
                }), [{ uid: roleId, sid: sid }]);
            }
        } else {
            clearInterval(interval);
        }
    }, PUSH_INTERVAL)
    setMedianCe();
}

export async function kickUser(app: Application, uid: string, message = STATUS.LOGIN_ERR) {
    let sessionService = app.get('sessionService');
    let sessions = sessionService.getByUid(uid);
    if (!!sessions) {
        sessions.forEach(session => {
            let roleId = session.get('roleId');
            let sid = session.get('sid');
            let uids = [{ uid: roleId, sid }];
            app.get('channelService').pushMessageByUids('onRemoteLogin', resResult(message), uids);
        });
    }
    await sessionService.akick(uid);
}
