import { Application, BackendSession, pinus } from 'pinus';
import { getRandSingleEelm, isTimestamp, resResult } from '../../../pubUtils/util';
import { STATUS } from '../../../consts/statusCode';
import { GMMailModel, GMMailType } from '../../../db/GMMail';
import { ACTIVITY_TYPE, GM_MAIL_STATUS, GM_MAIL_TYPE, MAIL_TIME_TYPE, MEMORY_LOG_TYPE, PUSH_ROUTE, SURVEY_SELECT } from '../../../consts';
import { ActivityModel } from '../../../db/Activity';
import { ActivityGroupModel } from '../../../db/ActivityGroup';
import { ActivityGroupTypeModel } from '../../../db/ActivityGroupType';
import { getTimeFunM, nowSeconds } from '../../../pubUtils/timeUtil';
import moment = require('moment');
import { sendUngotDividend } from '../../../services/auctionService';
import { taflush } from '../../../services/sdkService';
import { ActivityInRemote } from '../../../domain/activityField/activityField';
import { pushCurrentTime } from '../../../services/auctionService';
import { SurveyModel, SurveyUpdate } from '../../../db/Survery';
import { getSurvey } from '../../../services/gmService';
import { sendMessageToAllWithSuc } from '../../../services/pushService';
import { sendMailByContent, sendMailsByGmMail } from '../../../services/mailService';
import { saveMemory } from '../../../services/log/memoryLogService';
import { getGVGConfigFromRemote } from '../../../services/gvg/gvgService';
import { GVGServerGroupModel } from '../../../db/GVGServerGroup';
import { isNumber } from 'underscore';
import { group } from 'console';
import { GVGConfigModel } from '../../../db/GVGConfig';
import { ServerlistModel } from '../../../db/Serverlist';

let timer: NodeJS.Timer;
export default function (app: Application) {
    return new GmHandler(app);
}

export class GmHandler {
    constructor(private app: Application) {
    }

    async sendSingleMail(msg: { id: string, isPass: boolean }, session: BackendSession) {
        const uid: number = session.get('uid')
        let { id, isPass } = msg;
        let gmmail = await GMMailModel.getGmMailByIdAndType(id, GM_MAIL_TYPE.SINGLE, true);
        if(!gmmail) return resResult(STATUS.GM_MAIL_NOT_FOUND);
        return await this.sendMail(gmmail, isPass, uid);
    }

    async sendSingleMailTxt(msg: { id: string, isPass: boolean }, session: BackendSession) {
        const uid: number = session.get('uid')
        let { id, isPass } = msg;
        let gmmail = await GMMailModel.getGmMailByIdAndType(id, GM_MAIL_TYPE.SINGLE, false);
        if(!gmmail) return resResult(STATUS.GM_MAIL_NOT_FOUND);
        return await this.sendMail(gmmail, isPass, uid);
    }

    async sendServerMail(msg: { id: string, isPass: boolean }, session: BackendSession) {
        const uid: number = session.get('uid')
        let { id, isPass } = msg;
        let gmmail = await GMMailModel.getGmMailByIdAndType(id, GM_MAIL_TYPE.SERVER, true);
        if(!gmmail) return resResult(STATUS.GM_MAIL_NOT_FOUND);
        return await this.sendMail(gmmail, isPass, uid);
    }

    async sendServerMailTxt(msg: { id: string, isPass: boolean }, session: BackendSession) {
        const uid: number = session.get('uid')
        let { id, isPass } = msg;
        let gmmail = await GMMailModel.getGmMailByIdAndType(id, GM_MAIL_TYPE.SERVER, false);
        if(!gmmail) return resResult(STATUS.GM_MAIL_NOT_FOUND);
        return await this.sendMail(gmmail, isPass, uid);
    }

    //对接gm后台，下发邮件
    async sendMail(gmmail: GMMailType, isPass: boolean, uid: number) {
        let id = gmmail._id;
        let { receivers, mailType, status, timeType, startTime, circleHour, circleDay } = gmmail;
        if(status != GM_MAIL_STATUS.CREATE) {
            return resResult(STATUS.GM_MAIL_HAS_SENT);
        }

        if(isPass) {
            await sendMailsByGmMail([gmmail]);
        }
        await GMMailModel.updateMailById(id, { status: isPass? GM_MAIL_STATUS.PASS: GM_MAIL_STATUS.NOT_PASS, viewAt: new Date(), viewBy: uid }, uid);
        return resResult(STATUS.SUCCESS);
    }

    async reloadResource(msg: {}, session: BackendSession) {
        try {
            let activityServers = this.app.getServersByType('activity');
            for (let { id } of activityServers) {
                await this.app.rpc.activity.activityRemote.reloadResources.toServer(id);
            }
            let battleServers = this.app.getServersByType('battle');
            for (let { id } of battleServers) {
                await this.app.rpc.battle.battleRemote.reloadResources.toServer(id);
            }
            let chatServers = this.app.getServersByType('chat');
            for (let { id } of chatServers) {
                await this.app.rpc.chat.chatRemote.reloadResources.toServer(id);
            }
            let connectServers = this.app.getServersByType('connector');
            for (let { id } of connectServers) {
                await this.app.rpc.connector.connectorRemote.reloadResources.toServer(id);
            }
            let guildServers = this.app.getServersByType('guild');
            for (let { id } of guildServers) {
                await this.app.rpc.guild.guildRemote.reloadResources.toServer(id);
            }
            let roleServers = this.app.getServersByType('role');
            for (let { id } of roleServers) {
                await this.app.rpc.role.roleRemote.reloadResources.toServer(id);
            }
            let systimerServers = this.app.getServersByType('systimer');
            for (let { id } of systimerServers) {
                await this.app.rpc.systimer.systimerRemote.reloadResources.toServer(id);
            }
            let orderServers = this.app.getServersByType('order');
            for (let { id } of orderServers) {
                await this.app.rpc.order.orderRemote.reloadResources.toServer(id);
            }
            return resResult(STATUS.SUCCESS, {
                isOK: true
            });
        } catch (e) {
            return resResult(STATUS.SUCCESS, {
                isOK: false,
                err: e.stack
            });
        }
    }

    async updateActivity(msg: { aids: number[] }, session: BackendSession) {
        let { aids }= msg;

        let activities = await ActivityModel.findActivityByIds(aids);
        let activityServers = pinus.app.getServersByType('activity');
        for(let server of activityServers) {
            pinus.app.rpc.activity.activityRemote.updateActivities.toServer(server.id, activities.map(activity => new ActivityInRemote(activity)));
        }
        let timeLimitRanks = activities.filter(cur => cur.type == ACTIVITY_TYPE.TIME_LIMIT_RANK);
        if(timeLimitRanks.length > 0) {
            pinus.app.rpc.systimer.systimerRemote.updateTimeLimitRank.broadcast(timeLimitRanks);
        }
        let groupShops = activities.filter(cur => cur.type == ACTIVITY_TYPE.GROUP_SHOP);
        if(groupShops.length > 0) {
            pinus.app.rpc.systimer.systimerRemote.initSumSchedule.broadcast();
        }

        return resResult(STATUS.SUCCESS, {
            activity: activities
        });
    }

    async deleteActivity(msg: { activityId: number}, session: BackendSession) {
        const { activityId } = msg;
        let activityServers = pinus.app.getServersByType('activity');
        for(let server of activityServers) {
            pinus.app.rpc.activity.activityRemote.deleteActivities.toServer(server.id, [activityId]);
        }

        return resResult(STATUS.SUCCESS);
    }

    async updateActivityGroup(msg: { groupId: number, serverIds: number[], activityIds: number[] }, session: BackendSession) {
        const uid = session.get('uid');
        let { groupId, serverIds, activityIds } = msg;
        pinus.app.rpc.activity.activityRemote.saveActivitiesToGroup.broadcast(groupId, activityIds);
        pinus.app.rpc.activity.activityRemote.saveGroupToServer.broadcast([groupId], serverIds);
        return resResult(STATUS.SUCCESS);
    }

    /**
     * 开启军团活动到拍卖行debug
     * @param msg 
     * @param session 
     */
    async setGuildActivityDebug(msg: { aid: number, day: number, startActivity: number, endActivity: number, startGuildAuction: number, endGuildAuction: number, startWorldAuction: number, endWorldAuction: number, startNextDay: number  }, session: BackendSession) {
        let { aid, day, startActivity = 0, endActivity = 0, startGuildAuction = 0, endGuildAuction = 0, startWorldAuction = 0, endWorldAuction = 0, startNextDay = 0 } = msg;
        if(timer) {
            clearTimeout(timer);
        }
        const uid = session.get('uid');
        if(aid == undefined || day == undefined ) {
            return resResult(STATUS.WRONG_PARMS);
        }
        if(aid == 0) {
            day = new Date().getDay();
        }
    
        // 设置字典
        let now = new Date();

        let startTimes = await pinus.app.rpc.guild.guildActivityRemote.setDicGuildActivity.broadcast(now.getTime(), aid, startActivity, endActivity);
        await pinus.app.rpc.systimer.systimerRemote.setDicGuildActivity.broadcast(now.getTime(), aid, startActivity, endActivity);
        await pinus.app.rpc.connector.connectorRemote.setDicGuildActivity.broadcast(now.getTime(), aid, startActivity, endActivity);
        await pinus.app.rpc.guild.guildActivityRemote.setDicAuctionTime.broadcast(startTimes[0], endActivity, startGuildAuction, endGuildAuction, startWorldAuction, endWorldAuction);
        await pinus.app.rpc.connector.connectorRemote.setDicAuctionTime.broadcast(startTimes[0], endActivity, startGuildAuction, endGuildAuction, startWorldAuction, endWorldAuction);
        await pinus.app.rpc.systimer.systimerRemote.setDicAuctionTime.broadcast(startTimes[0], endActivity, startGuildAuction, endGuildAuction, startWorldAuction, endWorldAuction);
        await pinus.app.rpc.guild.guildActivityRemote.setDay.broadcast(day);
        await pinus.app.rpc.systimer.systimerRemote.setDay.broadcast(day);
        await pinus.app.rpc.connector.connectorRemote.setDay.broadcast(day);
        await pinus.app.rpc.guild.guildActivityRemote.guildActivityEnd.broadcast(aid);
        await pinus.app.rpc.guild.guildActivityRemote.clearActivityObj.broadcast();

        // 开启定时器
        await pinus.app.rpc.systimer.systimerRemote.setAuctionSchedule.broadcast();
        await pinus.app.rpc.systimer.systimerRemote.setGuildActivitySchedule.broadcast();
        // 向客户端发送时间
        let time = <number>getTimeFunM().getTimeWithWeek(day, 20, 0, 0) - startActivity * 1000;
        pinus.app.rpc.guild.guildActivityRemote.setCurrentTime.broadcast(time);
        await pushCurrentTime(time);
        timer = setTimeout(async () => {
            let time = <number>getTimeFunM().getAfterDayWithHour(0);
            pinus.app.rpc.guild.guildActivityRemote.setCurrentTime.broadcast(time);
            await pushCurrentTime(time);
            let guilds = pinus.app.getServersByType('guild');
            let guild = getRandSingleEelm(guilds);
            await pinus.app.rpc.guild.guildActivityRemote.sendUngotDividend.toServer(guild.id);
        }, startActivity * 1000 + endActivity * 1000 + startGuildAuction * 1000 + endGuildAuction * 1000 + startWorldAuction * 1000 + endWorldAuction * 1000 + startNextDay * 1000)
        return resResult(STATUS.SUCCESS, {
            startActivity: startTimes[0],
            endActivity: startTimes[0] + endActivity * 1000,
            startGuildAuction: startTimes[0] + endActivity * 1000 + startGuildAuction * 1000,
            endGuildAuction: startTimes[0] + endActivity * 1000 + startGuildAuction * 1000 + endGuildAuction * 1000,
            startWorldAuction: startTimes[0] + endActivity * 1000 + startGuildAuction * 1000 + endGuildAuction * 1000 + startWorldAuction * 1000,
            endWorldAuction: startTimes[0] + endActivity * 1000 + startGuildAuction * 1000 + endGuildAuction * 1000 + startWorldAuction * 1000 + endWorldAuction * 1000,
            startNextDay: startTimes[0] + endActivity * 1000 + startGuildAuction * 1000 + endGuildAuction * 1000 + startWorldAuction * 1000 + endWorldAuction * 1000 + startNextDay * 1000,
        });
    }

    async cancelGuildActivityDebug(msg: {  }, session: BackendSession) {
        // 设置字典
        let now = new Date();
        if(timer) {
            clearTimeout(timer);
        }
        await pinus.app.rpc.guild.guildRemote.reloadResources.broadcast();
        await pinus.app.rpc.systimer.systimerRemote.reloadResources.broadcast();
        await pinus.app.rpc.guild.guildActivityRemote.setDay.broadcast(null);
        await pinus.app.rpc.systimer.systimerRemote.setDay.broadcast(null);
        await pinus.app.rpc.connector.connectorRemote.setDay.broadcast(null);

        // 开启定时器
        await pinus.app.rpc.systimer.systimerRemote.setAuctionSchedule.broadcast();
        await pinus.app.rpc.systimer.systimerRemote.setGuildActivitySchedule.broadcast();
        await pinus.app.rpc.guild.guildActivityRemote.clearActivityObj.broadcast();

        // 向客户端发送时间
        pinus.app.rpc.guild.guildActivityRemote.setCurrentTime.broadcast(now.getTime());
        await pushCurrentTime(now.getTime());
        return resResult(STATUS.SUCCESS);
    }

    async taflus() {
        taflush();
        pinus.app.rpc.activity.activityRemote.taflush.broadcast();
        pinus.app.rpc.battle.battleRemote.taflush.broadcast();
        pinus.app.rpc.chat.chatRemote.taflush.broadcast();
        pinus.app.rpc.connector.connectorRemote.taflush.broadcast();
        pinus.app.rpc.guild.guildRemote.taflush.broadcast();
        pinus.app.rpc.order.orderRemote.taflush.broadcast();
        pinus.app.rpc.role.roleRemote.taflush.broadcast();
        pinus.app.rpc.systimer.systimerRemote.taflush.broadcast();
        return resResult(STATUS.SUCCESS);
    }

    async updateSurvey(msg: { code: string, surveyId: string, beginTim: number, endTime: number, isEnable: boolean, surveyLink: string, surveyName: string, roleIndex: number, goods: string, mailContent: string  }, session: BackendSession) {
        let update: SurveyUpdate = msg;
        if(msg.goods) {
            let reward = JSON.parse(msg.goods);
            update.reward = reward;
        }
        let origin = await SurveyModel.findByCode(msg.code);
        let result = await SurveyModel.updateSurvey(msg.code, update, SURVEY_SELECT.FIND);
        if(!result) return resResult(STATUS.WRONG_PARMS);

        if(origin && origin.isEnable != result.isEnable) {
            await sendMessageToAllWithSuc(PUSH_ROUTE.UPDATE_SURVEY, { survey: result });
        }

        return resResult(STATUS.SUCCESS);
    }

    async deleteSurvey(msg: { code: string }, session: BackendSession) {
        let { code } = msg;

        await SurveyModel.deleteSurvey(code);
        await sendMessageToAllWithSuc(PUSH_ROUTE.DELETE_SURVEY, { code });

        return resResult(STATUS.SUCCESS);
    }

    async saveMemoryLog(msg: { memoryLogType: MEMORY_LOG_TYPE }, session: BackendSession) {
        const { memoryLogType } = msg;
        await saveMemory(memoryLogType);
        return resResult(STATUS.SUCCESS);
    }

    async updateGVGServerGroup(msg: { serverId: number[], groupId: number }, session: BackendSession) {
        const { serverId: serverIds, groupId } = msg;
        if(!isNumber(groupId)) return resResult(STATUS.WRONG_PARMS);
        for(let serverId of serverIds) {
            if(!isNumber(serverId)) return resResult(STATUS.WRONG_PARMS);
        }
        let { scheduleTime } = await getGVGConfigFromRemote();
        for(let serverId of serverIds) {
            await GVGServerGroupModel.updateByServerId(serverId, groupId, scheduleTime);
        }
        try {
            await pinus.app.rpc.guild.guildRemote.setGVGServerGroup.broadcast();
            await pinus.app.rpc.chat.chatRemote.setGVGServerGroup.broadcast();
            await pinus.app.rpc.connector.connectorRemote.setGVGServerGroup.broadcast();
            await pinus.app.rpc.gm.gmRemote.setGVGServerGroup.broadcast();
            await pinus.app.rpc.systimer.systimerRemote.setGVGServerGroup.broadcast();
        } catch(e) {
            console.log('remote未初始完');
        }
        return resResult(STATUS.SUCCESS);
    }

    async updateGVGConfig(msg: { configId: number, teamTime: number, prepareTime: number, battleTime: number, scheduleTime: number }, session: BackendSession) {
        const { configId, teamTime, prepareTime, battleTime, scheduleTime } = msg;
        if(!isNumber(configId) || !isTimestamp(teamTime) || !isTimestamp(prepareTime) || !isTimestamp(battleTime) || !isTimestamp(scheduleTime)) {
            return resResult(STATUS.WRONG_PARMS);
        }
        if(teamTime > prepareTime || prepareTime > battleTime || battleTime > scheduleTime) {
            return resResult(STATUS.GM_GVG_TIME_ERR);
        }
        const config = await GVGConfigModel.updateConfig(configId, teamTime, prepareTime, battleTime, scheduleTime);
        await pinus.app.rpc.guild.guildRemote.setGVGConfig.broadcast(config);
        await pinus.app.rpc.systimer.systimerRemote.initGVGConfigSchedule.broadcast();
        return resResult(STATUS.SUCCESS);
    }
}