
import { scheduleJob, Job, } from 'node-schedule';
import { PVPConfigModel, PVPConfigType } from '../db/SystemConfig';
import { nowSeconds, getTimeFun } from '../pubUtils/timeUtil';
import { getTodayGuildActivity, gameData } from '../pubUtils/data';
import { pvpSeasonEnd } from './pvpService';
import { getAllOnlineRoles, getAllServers, delGuildActivityRank } from './redisService';
import { GUILD_ACTIVITY_TYPE, REFRESH_TIME, SEND_NAME, SERVER_OPEN_TIME, COUNTER, AUCTION_TIME } from '../consts';
import { RoleModel } from '../db/Role';
import { pinus } from 'pinus';
import { indexOf } from 'underscore';
import { PvpSeasonResultModel } from '../db/PvpSeasonResult';
import { settleGuildWeekly } from './guildService';
import { sendMailByContent } from './mailService';
import { getGuildActivityByDic, sendEndMsgToAll, autoDeclare, sendGuildActivityStatus } from './guildActivityService';
import { sendUngotDividendJob, startGuildAuction, startWorldAuction, stopAuction } from './auctionService';
import { DicGuildActivity } from '../pubUtils/dictionary/DicGuildActivity';
import { dispatch } from '../pubUtils/dispatcher';
import { Rank } from './rankService';
import { checkTask } from './taskService';
import { everydayRefresh } from './connectorService';
import { initMarquee, initMaintenance } from './gmService';
import moment = require('moment');
import { CounterModel } from '../db/Counter';
import { reportOneOnline } from './authenticateService';

const PER_SECOND = 1 * 1000;
const PER_DAY = 24 * 60 * 60;
const SETTLE_DIFF_SECONDS = 29 * 60;
const PER_MINUTE = 1 * 60;
var seasonMakeRewardTimJobId: Job;
var warJobId: Job;
var seasonRefreshTimeJobId: Job;
let guildWeeklyJobId: Job;
let guildActStartJobId: Job; // 军团活动开启后每10(or 1)秒循环的定时任务，到结束活动清除
let guildActSecondsJobId: Job; // 军团活动开启后每10(or 1)秒循环的定时任务，到结束活动清除
let guildActEndJobId: Job; // 军团活动开启后每10(or 1)秒循环的定时任务，到结束活动清除
let pvpMakeRewardInterval = null;
let pvpRefreshInterval = null;

/**
 * 服务器启动即开启定时任务，结算时常是23-24点，实际结算的时间点是23：31分钟
 */
export async function init() {

    // pvp赛季
    await setPvpSeason();

    // 周功勋结算任务
    guildWeeklyJobId = scheduleJob('settleGuildWeekly', '0 0 0 * * 1', settleGuildWeekly);

    // 每5分钟汇报在线玩家在线情况
    scheduleJob('reportOnline', '0 0/5 * * * *', reportOnlineSchedule);

    // 军团活动排行榜
    guildActivitySchedule();

    // 拍卖行刷新：拍卖阶段刷新，分红发放
    auctionSchedule();

    // 每天5点推送刷新时间消息
    // 顺便每天0点计算前一天活跃玩家中位数战力
    scheduleJob('everyDayRefresh', `0 0 ${REFRESH_TIME} * * ?`, everydayRefresh);

    // 跑马灯
    await initMarquee();

    // 维护信息
    await initMaintenance();
}

function getSeasonContinueDay(seasonNum: number) {
    const pvpSeasonDuring = [{seasonNum: 1, day: 7},{seasonNum: 2, day: 15},{seasonNum: 3, day: 30},];

    let maxDay = 0;
    for(let {seasonNum: dicSeasonNum, day } of pvpSeasonDuring) {
        if(seasonNum == dicSeasonNum) return day;
        if(maxDay < day) maxDay = day;
    }
    return maxDay;
}

async function setPvpSeason() {
    let pvpConfig = await PVPConfigModel.findCurPVPConfig();
    if(!pvpConfig || pvpConfig.seasonEndTime <= nowSeconds() ) {
        if(pvpConfig && !pvpConfig.hasSettleReward) {
            await pvpSeasonEnd(pvpConfig);
        }

        let lastSeasonNum = pvpConfig? pvpConfig.seasonNum: 0;
        let lastSeasonEndTime = pvpConfig? pvpConfig.seasonEndTime: 0;

        let newSeasonStartTime = lastSeasonEndTime;
        let during = getSeasonContinueDay(lastSeasonNum + 1) * PER_DAY;
        let rewardTime = SETTLE_DIFF_SECONDS;
        if(nowSeconds() - lastSeasonEndTime > during) {
            newSeasonStartTime = <number>getTimeFun().getDayZeroPoint(0);
        }
        let newSeasonNum = await CounterModel.getNewCounter(COUNTER.PVP_SEASON_NUM);
        pvpConfig = await PVPConfigModel.createPVPConfig(newSeasonNum, newSeasonStartTime, newSeasonStartTime + during - rewardTime, newSeasonStartTime + during - PER_MINUTE);
    }
    await setPvpSeasonMakeRewardJob(pvpConfig);
    await setNextSeasonJob(pvpConfig);
}

async function setPvpSeasonMakeRewardJob(pvpConfig: PVPConfigType) {
    if (!!seasonMakeRewardTimJobId) {
        seasonMakeRewardTimJobId.cancel();
    }
    if(pvpConfig.seasonRewardTime < nowSeconds() && !pvpConfig.hasSettleReward) { // 未发奖励
        await pvpSeasonEnd(pvpConfig);
    } else {
        seasonMakeRewardTimJobId = scheduleJob('seasonMakeRewardTimJobId', pvpConfig.seasonRewardTime, async () => {
            await pvpSeasonEnd(pvpConfig);
        });
    }
}

async function setNextSeasonJob(pvpConfig: PVPConfigType) {
    if (!!seasonRefreshTimeJobId) {
        seasonRefreshTimeJobId.cancel();
    }
    //定时开启新赛季，比seasonEndTime多定一分钟，保证定时器时间没错
    seasonRefreshTimeJobId = scheduleJob('seasonRefreshTimeJobId', pvpConfig.seasonEndTime + PER_MINUTE, setPvpSeason);
}

/**
 * debug接口
 * @param hour 
 */
export async function resetPvpSeasonTime(hour: number) {
    await PVPConfigModel.setCurPvpConfig({ seasonEndTime: <number>getTimeFun().getDayZeroPoint(0) });
    return await setPvpSeason();
}

export async function reportOnlineSchedule() {
    let allRoles = await getAllOnlineRoles();
    console.log('reportOnlineSchedule all roles count: ', allRoles.length)
    for (let { roleId, userCode, sid } of allRoles) {
        let result = reportOneOnline(roleId, userCode, sid, false);
        if (!result) continue;
    }
}


/**
 * 军团活动，每晚8点开启
 */
export async function guildActivitySchedule() {
    /***********guildActivitySchedule***********/
    if (guildActStartJobId) {
        guildActStartJobId.cancel();
    }
    if (guildActSecondsJobId) {
        guildActSecondsJobId.cancel();
        guildActSecondsJobId = undefined;
    }
    if (guildActEndJobId) {
        guildActEndJobId.cancel();
        guildActEndJobId = undefined;
    }

    let dicGuildActivity = getTodayGuildActivity();
    await delGuildActivityRank(dicGuildActivity.id);

    console.log(dicGuildActivity)

    guildActStartJobId = scheduleJob('guildActivityStart', `${dicGuildActivity.startSeconds} ${dicGuildActivity.startMinute} ${dicGuildActivity.startTime} * * ?`, guildActivityStartSchedule);
}

// 军团晚间活动，每天8点开始
async function guildActivityStartSchedule() {
    await guildActivityStart();
}

export async function guildActivityStart(dicGuildActivity?: DicGuildActivity) {
    console.log('*******开始军团晚间活动****')
    if (!dicGuildActivity) dicGuildActivity = getTodayGuildActivity();
    if (!dicGuildActivity) return;

    console.log('********', dicGuildActivity.id, Date.now() + dicGuildActivity.duringTime * 1000)
    let servers = await getAllServers(); // 玩家serverId列表
    if (dicGuildActivity.id == GUILD_ACTIVITY_TYPE.GATE_ACTIVITY) {
        guildActSecondsJobId = scheduleJob('guildActivitySeconds', '*/10 * * * * *', gateActivitySeconds);
        // 结束时间
        guildActEndJobId = scheduleJob('guildActivityEnd', Date.now() + dicGuildActivity.duringTime * 1000, gateActivityEnd);
    } else if (dicGuildActivity.id == GUILD_ACTIVITY_TYPE.CITY_ACTIVITY) {
        guildActSecondsJobId = scheduleJob('guildActivitySeconds', '*/10 * * * * *', cityActivitySeconds);
        // 结束时间
        guildActEndJobId = scheduleJob('guildActivityEnd', Date.now() + dicGuildActivity.duringTime * 1000, cityActivityEnd);
    } else if (dicGuildActivity.id == GUILD_ACTIVITY_TYPE.RACE_ACTIVITY) {

        // 开始活动
        let guildServers = pinus.app.getServersByType('guild');
        for (let serverId of servers) {
            let sid = dispatch(serverId.toString(), guildServers, 'guild');
            await pinus.app.rpc.guild.guildActivityRemote.raceActivityStart.toServer(sid.id, serverId);
        }

        guildActSecondsJobId = scheduleJob('guildActivitySeconds', '*/1 * * * * *', raceActivitySeconds);
        // 结束时间
        guildActEndJobId = scheduleJob('guildActivityEnd', Date.now() + dicGuildActivity.duringTime * 1000, raceActivityEnd);
    }

    for (let serverId of servers) {
        await sendGuildActivityStatus(serverId);
    }
    return true;
}

// 蛮夷入侵
// 结束军团活动
export async function gateActivityEnd() {

    console.log('*****gateActivityEnd');
    await sendEndMsgToAll();
    await pinus.app.rpc.guild.guildActivityRemote.guildActivityEnd.broadcast(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY);

    if (guildActSecondsJobId) {
        guildActSecondsJobId.cancel();
        guildActSecondsJobId = undefined;
    }
    if (guildActEndJobId) {
        guildActEndJobId.cancel();
        guildActEndJobId = undefined;
    }
}

// 每10秒下发一次的任务
export async function gateActivitySeconds() {
    console.log('*****gateActivitySeconds')
    await pinus.app.rpc.guild.guildActivityRemote.sendRankToGuilds.broadcast(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY);
}

// 诸侯混战
// 结束军团活动
export async function cityActivityEnd() {
    console.log('*****cityActivityEnd');
    await sendEndMsgToAll();
    await pinus.app.rpc.guild.guildActivityRemote.guildActivityEnd.broadcast(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY);

    // 发完之后再做下周自动宣战
    let serverlists = await getAllServers();
    for (let serverId of serverlists) {
        await autoDeclare(serverId);
    }
    if (guildActSecondsJobId) {
        guildActSecondsJobId.cancel();
        guildActSecondsJobId = undefined;
    }
    if (guildActEndJobId) {
        guildActEndJobId.cancel();
        guildActEndJobId = undefined;
    }
}

// 每10秒下发一次的任务
export async function cityActivitySeconds() {
    console.log('*****cityActivitySeconds')
    await pinus.app.rpc.guild.guildActivityRemote.sendRankToGuilds.broadcast(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY);
}

// 粮草先行
// 结束军团活动
export async function raceActivityEnd() {
    console.log('*****raceActivityEnd');
    await sendEndMsgToAll();
    await pinus.app.rpc.guild.guildActivityRemote.guildActivityEnd.broadcast(GUILD_ACTIVITY_TYPE.RACE_ACTIVITY);

    if (guildActSecondsJobId) {
        guildActSecondsJobId.cancel();
        guildActSecondsJobId = undefined;
    }
    if (guildActEndJobId) {
        guildActEndJobId.cancel();
        guildActEndJobId = undefined;
    }
}

// 每10秒下发一次的任务
export async function raceActivitySeconds() {
    console.log('*****raveActivitySeconds')
    let servers = await getAllServers(); // 玩家serverId列表
    let guildServers = pinus.app.getServersByType('guild');
    for (let serverId of servers) {
        let sid = dispatch(serverId.toString(), guildServers, 'guild');
        await pinus.app.rpc.guild.guildActivityRemote.calWoodenHorseAndSend.toServer(sid.id, serverId);
    }
}

let startGuildAuctionJobId: Job;
let startWorldAuctionJobId: Job;
let stopAuctionJobId: Job;
let sendUngotDividendJobId: Job;

export function auctionSchedule() {
    clearAuctionSchedule();
    let guildOpen = gameData.auctionTime.get(AUCTION_TIME.GUILD_OPEN);
    let worldOpen = gameData.auctionTime.get(AUCTION_TIME.WORLD_OPEN);
    let worldClose = gameData.auctionTime.get(AUCTION_TIME.WORLD_CLOSE);

    console.log('***** auctionSchedule', guildOpen.hour, guildOpen.minute, guildOpen.seconds);
    console.log('***** auctionSchedule', worldOpen.hour, worldOpen.minute, worldOpen.seconds);
    console.log('***** auctionSchedule', worldClose.hour, worldClose.minute, worldClose.seconds);
    startGuildAuctionJobId = scheduleJob('startGuildAuction', `${guildOpen.seconds} ${guildOpen.minute} ${guildOpen.hour} * * ?`, startGuildAuction);
    startWorldAuctionJobId = scheduleJob('startWorldAuction', `${worldOpen.seconds} ${worldOpen.minute} ${worldOpen.hour} * * ?`, startWorldAuction);
    stopAuctionJobId = scheduleJob('stopAuction', `${worldClose.seconds} ${worldClose.minute} ${worldClose.hour} * * ?`, stopAuction);
    sendUngotDividendJobId = scheduleJob('sendUngotDividendJob', '0 0 5 00 * ?', sendUngotDividendJob);

}

function clearAuctionSchedule() {
    if (startGuildAuctionJobId) {
        startGuildAuctionJobId.cancel();
        startGuildAuctionJobId = undefined;
    }
    if (startWorldAuctionJobId) {
        startWorldAuctionJobId.cancel();
        startWorldAuctionJobId = undefined;
    }
    if (stopAuctionJobId) {
        stopAuctionJobId.cancel();
        stopAuctionJobId = undefined;
    }
    if (sendUngotDividendJobId) {
        sendUngotDividendJobId.cancel();
        sendUngotDividendJobId = undefined;
    }
}