import { MarqueeType, MarqueeModel } from "../db/Marquee";
import { MARQUEE_TYPE, 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 { MaintenanceModel, MaintenanceType } from '../db/Maintenance';
import { pinus } from "pinus";
import { getWorldChannelSid } from "./chatChannelService";
import { ServerlistModel } from "../db/Serverlist";
import { NoticeModel, NoticeType } from "../db/Notice";
import { SendMailFun } from "./mailService";
import { GMMailType } from '../db/GMMail';

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

export async function setMarquee(code: string) {
    let marquee = await MarqueeModel.findByCode(code);
    if(marquee.type == MARQUEE_TYPE.INSTANT) {
        let msgDatas = await createMarqueeMsg(marquee);
        await pushMarqueeMsg(msgDatas);
        return true;
    } else {
        return await generateMarqueeSchedule(marquee);
    }
}

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

    if(marquee.type != MARQUEE_TYPE.SCHEDULE) return false;
    if(marquee.startTime.getTime() >= marquee.endTime.getTime()) return false;
    if(marquee.endTime.getTime() < Date.now()) return false;
    if(marquee.startTime.getTime() > Date.now()) {
        let startJob = scheduleJob(`start${marquee.code}`, marquee.startTime.getTime(), async () => {
            await startMarquee(marquee, startJob)
        });
    } else {
        await startMarquee(marquee)
    }
    return true;
}

async function startMarquee(marquee: MarqueeType, startJob?: Job) {
    console.log('************', `跑马灯定时器 ${marquee.code}开始`, '************');
    await MarqueeModel.updateData(marquee.code, { isRunning: true });
    let msgDatas = await createMarqueeMsg(marquee);
    await pushMarqueeMsg(msgDatas);
    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.getTime(), async () => {
        if(startJob) {
            startJob.cancel();
            startJob = undefined;
        }
        if(secondsJob) {
            secondsJob.cancel();
            secondsJob = undefined;
        }
        if(endJob) {
            endJob.cancel();
            endJob = undefined;
        }
        await MarqueeModel.updateData(marquee.code, { isRunning: false });
    });
}

async function createMarqueeMsg(marquee: MarqueeType) {
    let { serverIds, content } = marquee;
    let msgDatas: GroupMessageType[] = [];
    for(let serverId of 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();
    await MarqueeModel.updateData(code, { isRunning: false });
    return true
}

// —————————————— 停服维护 —————————————— //
// 维护信息
export async function initMaintenance(maintenance?: MaintenanceType) {
    if(!maintenance) 
        maintenance = await MaintenanceModel.findOpenMaintenance();
    if(maintenance) {
        let { startTime, marquee } = maintenance;
        if(marquee) {
            let result = await generateMarqueeSchedule(<MarqueeType>marquee);
            // console.log(result);
        }
        if(Date.now() > startTime.getTime()) {
            await startMaintenance(maintenance);
        } else {
            let startJob = scheduleJob(`startMainten${maintenance.code}`, startTime.getTime(), async () => {
                await startMaintenance(maintenance, startJob);
            });
        }
    }
}

// 开启维护
async function startMaintenance(maintenance: MaintenanceType, startJob?: Job) {
    // 向全服发送
    let { serverIds, notice } = maintenance;
    for(let serverId of serverIds) {
        let chatSid = await getWorldChannelSid(serverId);
        await pinus.app.rpc.chat.chatRemote.sendServerMaintenance.toServer(chatSid, serverId);
    }

    // 更新serverlist上的status
    await ServerlistModel.updateByServerIds(serverIds, { serverStatus: SERVER_STATUS.MAINTENANCE });
    // 更新notice的isEnable
    if(notice) {
        await NoticeModel.updateNotice((<NoticeType>notice).id, { isEnable: true });
    }
    
    // 更新connectorRemote里面的维护服务器
    await pinus.app.rpc.connector.connectorRemote.setServerMainten.broadcast(serverIds);
}

// 停止维护
export async function stopMaintenance(maintenance: MaintenanceType, uid: number) {
    let { serverIds, notice, marquee, mail } = maintenance;
    // 更新serverlist上的status
    await ServerlistModel.updateByServerIds(serverIds, { serverStatus: SERVER_STATUS.HOT });
    // 更新notice的isEnable
    if(notice) {
        await NoticeModel.updateNotice((<NoticeType>notice).id, { isEnable: false });
    }

    // 更新connectorRemote里面的维护服务器
    let connectorServers = pinus.app.getServersByType('connector');
    for(let { id } of connectorServers) {
        await pinus.app.rpc.connector.connectorRemote.setServerMainten.toServer(id, []);
    }

    if(marquee) {
        await cancelMarquee((<MarqueeType>marquee).code);
    }
    console.log('*****', JSON.stringify(mail));
    if(mail) {
        let f = new SendMailFun();
        await f.setWithGmMail((<GMMailType>mail)._id);
        await f.sendToServer(serverIds);
        await f.saveRecord(uid);
    }
}