import Marquee, { MarqueeType, MarqueeModel } from "../db/Marquee";
import { GM_MAIL_STATUS, GM_MAIL_TYPE, MAIL_TIME_TYPE, MARQUEE_SHOW_TYPE, MARQUEE_TIME_TYPE, REF_CIRCLE_MAIL_TIME, SERVER_STATUS } from "../consts";
import { scheduleJob, scheduledJobs, Job } from 'node-schedule';
import { createMarqueeMsg as sysCreateMarqueeMsg, pushMarqueeMsg as sysPushMarqueeMsg } from './sysChatService';
import { GroupMessageType } from "../db/GroupMessage";
import { pinus } from "pinus";
import { getWorldChannelSid } from "./chatChannelService";
import { ServerlistModel, ServerlistType } from "../db/Serverlist";
import { NoticeModel, NoticeType } from "../db/Notice";
import { SendMailFun } from "./mailService";
import GMMail, { GMMailModel, GMMailType } from '../db/GMMail';
import moment = require("moment");
import { getSeconds, nowSeconds } from "../pubUtils/timeUtil";
import { CreateServerParam } from "../domain/backEndField/params";
import { RegionModel, RegionType } from "../db/Region";
import { GMMail as StategyMail } from "../db/ServerStategy";
import { uniq } from "underscore";

// —————————————— 跑马灯 —————————————— //
// 初始
export async function initMarquee() {
    const marquees = await MarqueeModel.findEffectiveMarque(pinus.app.get('env'));
    for(let marquee of marquees) {
        await generateMarqueeSchedule(marquee);
    }
}

export async function setMarquee(marquee: MarqueeType) {
    console.log('******', marquee.timeType, marquee)
    if(marquee.timeType == MARQUEE_TIME_TYPE.INSTANT) {
        await startMarquee(marquee);
        return true;
    } else {
        return await generateMarqueeSchedule(marquee);
    }
}

async function generateMarqueeSchedule(marquee: MarqueeType) {
    // 定时发送
    let setSecondsMarquee = scheduledJobs[`setSeconds${marquee.code}`];
    if(setSecondsMarquee) return false; // 已经在运行中了

    if(marquee.timeType != MARQUEE_TIME_TYPE.SCHEDULE) return false;
    if(marquee.endTime && marquee.endTime < nowSeconds()) return false;
    if(marquee.startTime > nowSeconds()) {
        let startJob = scheduleJob(`start${marquee.code}`, marquee.startTime * 1000, async () => {
            await startMarquee(marquee, startJob)
        });
    } else {
        await startMarquee(marquee)
    }
    return true;
}

async function startMarquee(marquee: MarqueeType, startJob?: Job) {
    console.log('************', `跑马灯定时器 ${marquee.code}开始`, '************');
    let msgDatas = await createMarqueeMsg(marquee);
    if(marquee.showType == MARQUEE_SHOW_TYPE.ONCE) { // 一次性发送
        await pushMarqueeMsg(msgDatas);
        if(startJob) {
            startJob.cancel();
            startJob = undefined;
        }
    } else {
        await pushMarqueeMsg(msgDatas);
        console.log('***', marquee.interval)
        let secondsJob = scheduleJob(`setSeconds${marquee.code}`, `*/${marquee.interval} * * * * *`, async () => {
            console.log(`*****setSeconds${marquee.code}****`)
            await pushMarqueeMsg(msgDatas);
        });
        let endJob = scheduleJob(`end${marquee.code}`, marquee.endTime * 1000, async () => {
            if(startJob) {
                startJob.cancel();
                startJob = undefined;
            }
            if(secondsJob) {
                secondsJob.cancel();
                secondsJob = undefined;
            }
            if(endJob) {
                endJob.cancel();
                endJob = undefined;
            }
        });
    }
}

async function createMarqueeMsg(marquee: MarqueeType) {
    let { receivers, content } = marquee;
    let msgDatas: GroupMessageType[] = [];
    let serverIds: number[] = [];
    for(let { env, serverId } of receivers) {
        if(serverId == 0) {
            let servers = await ServerlistModel.findByEnv(env);
            for(let { serverId } of servers) {
                serverIds.push(serverId);
            }
        } else {
            serverIds.push(serverId);
        }
    }
    for(let serverId of uniq(serverIds)) {
        let msgData = await sysCreateMarqueeMsg('', '系统', serverId, content);
        msgDatas.push(msgData);
    }

    return msgDatas;
}

async function pushMarqueeMsg(msgDatas: GroupMessageType[]) {
    for(let msgData of msgDatas) {
        await sysPushMarqueeMsg(msgData);
    }
}

export async function cancelMarquee(code: string) {
    let startMarquee = scheduledJobs[`start${code}`];
    let setSecondsMarquee = scheduledJobs[`setSeconds${code}`];
    let endMarquee = scheduledJobs[`end${code}`];
    if(startMarquee) startMarquee.cancel();
    if(setSecondsMarquee) setSecondsMarquee.cancel();
    if(endMarquee) endMarquee.cancel();
    return true
}

export async function sendOpenServerMail(type: 'openMail'|'circleMail', mail: StategyMail, newServer: ServerlistType, uid: number) {
     let addParam = new GMMail();
     addParam.setByRegionStategy(type, mail, newServer, uid);
    let gmmail = await GMMailModel.addMail(addParam, uid);
    let needSend = false;
    if(mail.timeType == MAIL_TIME_TYPE.CIRCLE) {
        let refTimeStr = REF_CIRCLE_MAIL_TIME >= 10? `${REF_CIRCLE_MAIL_TIME}`: `0${REF_CIRCLE_MAIL_TIME}`;
        let refTime = moment(moment().format(`YYYY-MM-DD ${refTimeStr}:00:00`)).unix();
        let sendTime = moment(moment().format('YYYY-MM-DD '+ mail.circleHour)).unix();
        if(sendTime < refTime) sendTime += 86400;
        let now = nowSeconds();
        if(refTime < now && sendTime > now) {
            needSend = true;
        }
    } else {
        needSend = true;
    }
    if(needSend) {
        let f = new SendMailFun();
        await f.setWithGmMail(gmmail);
        await f.sendToServer([newServer.id]);
    }
    return true;
}

export function setServerMainten(serverIds: number[], startTime: number, endTime: number) {
    let maintenServers = pinus.app.get('maintenServers')||new Map();
    for(let id of serverIds) {
        if(!maintenServers.has(id)) {
            maintenServers.set(id, { startTime, endTime });
        } else {
            maintenServers.get(id).startTime = startTime;
            maintenServers.get(id).endTime = endTime;
        }
    }
    pinus.app.set('maintenServers', maintenServers);
}

export function stopServerMainten(serverIds: number[]) {
    let maintenServers = pinus.app.get('maintenServers')||new Map();
    for(let id of serverIds) {
        if(maintenServers.has(id)) {
            maintenServers.delete(id);
        }
    }
    pinus.app.set('maintenServers', maintenServers);
}

export function getServerMainten(serverId: number) {
    let maintenServers = pinus.app.get('maintenServers')||new Map();
    return maintenServers.get(serverId);
}

export async function createNewServer(region: RegionType ,serverId: number, params: CreateServerParam, uid?: number) {
    let newServer = await ServerlistModel.newServer(params, region, serverId, uid);
    if(params.openMail) await sendOpenServerMail('openMail', params.openMail, newServer, uid);
    if(params.circleMail) await sendOpenServerMail('circleMail', params.circleMail, newServer, uid);
    await RegionModel.newServer(region.id, newServer);
}