import { random } from 'mathjs';
import { wangzherongyao_fight_group } from '../../shared/protocols/wzry/PtlOpen';
import { PublicShared } from '../../shared/public/public';
import { ChatFun } from '../chat';
import { EmailFun } from '../email';
import { FightFun } from '../fight';
import { Rank } from '../rank/rank';
import { WangZheRongYaofun } from '../wzry';
import { Scheduler, schedulerType } from './scheduler';
import { getRankList } from '../../api_cross/wzry/ApiRank';



export class SchedulerWzryAutoBaoMing extends Scheduler {
    id: schedulerType = 'wzry_autobaoming';
    time = 0 ;//G.gc.wangzherongyao.wangzhe.eventtime.autobaomingtime;
    name = '王者荣耀自动报名（周一0:00）';     // 本服定时器
    type = 'week';

    async read() {
        await this.ctorStartTime();
        this.isReady = false;
    }

    async start() {
        let _user = await G.mongodb.collection('playerInfo', 'wzry').find({ type: 'wzry', isauto: 1, isbm: 0 }).toArray();
        let zkey = PublicShared.getToWeek()
        let prize = G.gc.wangzherongyao.wangzhe.bmprize
        for (let index = 0; index < _user.length; index++) {
            const element = _user[index];
            let toFight = await FightFun.getPlayerFightData(element.uid)
            let resCallWzry = await G.clientCross.callApi('wzry/BaoMing', { data: toFight, zkey: zkey });
            if (!resCallWzry.isSucc) {
                // 重复报名
                continue
            }
            prize.length > 0 && EmailFun.addEmail({
                uid: element.uid,
                type: 'system',
                title: G.gc.wangzherongyao.wangzhe.email.dldbaoming.title,
                content: G.gc.wangzherongyao.wangzhe.email.dldbaoming.content,
                prize: PublicShared.mergePrize(prize),
                contentInsertArr: []
            });
        }
        await G.mongodb.collection('playerInfo', 'wzry').updateMany({ type: 'wzry', isauto: 1 }, { $set: { isbm: 1 } })
        await this.record();
    }
}

export class SchedulerWzryDlDstart extends SchedulerWzryAutoBaoMing {
    id: schedulerType = 'wzry_dldstart';
    time = 86400 ;//G.gc.wangzherongyao.wangzhe.eventtime.dldstart;
    name = '王者荣耀大乱斗开启（周二0:00）';           //  跨服定时器
    type = 'week';

    async start() {
        let _u = await G.mongodb.collection('wzry_fight').findOne({ zkey: await PublicShared.getToWeek() })
        if (_u) {
            console.log("内网调时间导致重复执行,此次不执行")
            await this.record()
            return
        }
        let _fightUser = await G.mongodb.collection('wzry_user_cross').find({ zkey: await PublicShared.getToWeek() }).toArray()
        if (!_fightUser || _fightUser.length <= 0) {
            console.log("无玩家报名,此次不执行")
            await this.record()
            return
        }
        //先将所有真实玩家插入
        await G.mongodb.collection('wzry_fight').insertMany(_fightUser)
        for (let index = 0; index < _fightUser.length; index++) {
            const element = _fightUser[index];
            let data = {
                valArr: [element.jifen],
                ...element.data
            }
            Rank.list.wzryCross.addNew(data);
        }
        if (_fightUser.length < 256 && _fightUser.length > 0) {
            //如果玩家不够时，插入npc
            let npcFight = await WangZheRongYaofun.addNpc(256 - _fightUser.length)
            await G.mongodb.collection('wzry_fight').insertMany(npcFight)
            npcFight.forEach(npc => Rank.list.wzryCross.addNew({ valArr: [0], ...npc.data }))
        }
        await this.record();
    }
}

export class SchedulerWzryDlDjinji extends SchedulerWzryAutoBaoMing {
    id: schedulerType = 'wzry_dldjinji';
    //周二23:50
    time = 172200;//G.gc.wangzherongyao.wangzhe.eventtime.start256;
    name = '王者荣耀大乱斗晋级256分组(周二23:50)';
    type = 'week';

    async start() {
        let _u = await G.mongodb.collection('wzry_fight').findOne({ zkey: await PublicShared.getToWeek(), deep: { $exists: true } })
        if (_u) {
            console.log("内网调时间导致重复执行,此次不执行")
            await this.record()
            return
        }

        let _zuanshiUser = await getRankList(256,{
            'data.player.uid':1
        },{'data.player.isNpc':{$exists:false}});

        if (_zuanshiUser.length < 256) {
            console.log("本期无玩家,此次不执行")
            await this.record()
            return
        }
        let _userList = []
        //0号位 -1的这一条，表示晋级奖励
        let prize = G.gc.wangzherongyao.wangzhe.jiangli.dld[0]?.p || []

        for (let index = 0; index < _zuanshiUser.length; index++) {
            const element = _zuanshiUser[index];
            _userList.push(element.player.uid)
            // if (element.player.uid.indexOf('npc_') != -1) {
            //     if (_userList.length >= 256) break
            //     continue
            // }
            // 发送晋级钻石赛奖励
            prize.length > 0 && EmailFun.addEmail({
                uid: element.player.uid,
                type: 'system',
                title: G.gc.wangzherongyao.wangzhe.email.dldjinji.title,
                content: G.gc.wangzherongyao.wangzhe.email.dldjinji.content,
                prize: PublicShared.mergePrize(prize),
                contentInsertArr: []
            }, true)
            if (_userList.length >= 256) break
        }
        await G.mongodb.collection('wzry_fight').updateMany({ uid: { $in: _userList } }, { $set: { deep: 1 } })
        await wzrygroup(_userList)
        await this.record();
    }
}

export class SchedulerWzryZuanshiOne extends SchedulerWzryAutoBaoMing {
    id: schedulerType = 'wzry_zuanshione';
    //周三11:55分
    time = 2*24*3600 + 11*3600 + 55*60; //  G.gc.wangzherongyao.wangzhe.eventtime.start256 + 60 * 1;
    name = '王者荣耀256进128 (周三11:55)';
    type = 'week';
    deep = 1
    max = 256

    order(userlist) {
        userlist.sort((a, b) => a.groupinfo.groupid - b.groupinfo.groupid || a.groupinfo.orderid - b.groupinfo.orderid)
        return userlist
    }

    async start() {
        let deep = this.deep
        let _u = await G.mongodb.collection('wzry_fight').find({ deep: deep }).toArray()
        if (!_u || _u.length != this.max) {
            console.log("内网调时间导致重复执行,此次不执行")
            await this.record()
            return
        }
        _u = this.order(_u)
        let _pkNum = deep > 3 ? 5 : 3
        let [_tmpGroup, _order] = [[], deep * 16]
        for (let index = 0; index < _u.length; index++) {
            const element = _u[index];
            _tmpGroup.push(element)
            if (_tmpGroup.length <= 1) continue
            // 先记录所有的战斗结果后记录数据库
            let [_signlog, winArr] = [[], [0, 0]]
            // 战斗双方uid
            let [_uid1, _uid2, _winUid] = [_tmpGroup[0]['uid'], _tmpGroup[1]['uid'], _tmpGroup[0]['uid']]
            for (let idx = 0; idx < _pkNum; idx++) {
                let _tmpGroupCopy = JSON.parse(JSON.stringify(_tmpGroup))
                const result = FightFun.fight([_tmpGroupCopy[0]['data'], _tmpGroupCopy[1]['data']])
                let _fid = await G.mongodb.collection('wzry_fight_log').insertOne(result)
                winArr[result.winSide] += 1
                // 每场胜利数据
                let _tmp = {
                    showtime: G.time + 300,
                    winuid: result.winSide == 0 ? _uid1 : _uid2,
                    winArr: winArr,
                    pkuser: [_uid1, _uid2],
                    fid: _fid.insertedId.toString()
                }
                _signlog.push(_tmp)
            }

            // 胜场数确定输赢
            if (winArr[1] > winArr[0]) _winUid = _uid2

            for (let index = 0; index < [_uid1, _uid2].length; index++) {
                const element = [_uid1, _uid2][index];
                let _matchlog = _tmpGroup[index]?.matchlog || {}
                // 胜场日志
                let _tmpData = {}
                _tmpData[deep.toString()] = _signlog
                Object.assign(_matchlog, _tmpData)
                // let _setData = { matchlog: _matchlog, 'groupinfo.order': _order }
                let _setData = { matchlog: _matchlog }
                if (element == _winUid) _setData['deep'] = _tmpGroup[index].deep + 1

                await G.mongodb.collection('wzry_fight').updateOne({ uid: element }, { $set: _setData })
                // _order += 1
            }
            _tmpGroup = []
        }
        await this.record();
    }
}

export class SchedulerWzryZuanshiTwo extends SchedulerWzryZuanshiOne {
    id: schedulerType = 'wzry_zuanshitwo';
    //time = G.gc.wangzherongyao.wangzhe.eventtime.start256 + 2 * 60;
    //周三19:55分
    time = 2*24*3600 + 19*3600 + 55*60;
    name = '王者荣耀128进64 (周三19:55)';
    type = 'week';
    deep = 2
    max = 128

    order(userlist) {
        userlist.sort((a, b) => a.groupinfo.order - b.groupinfo.order)
        return userlist
    }
}

export class SchedulerWzryZuanshiThree extends SchedulerWzryZuanshiOne {
    id: schedulerType = 'wzry_zuanshithree';
    time = 3*24*3600 + 11*3600 + 55*60;  //G.gc.wangzherongyao.wangzhe.eventtime.start64; 原来的：周四11:50
    name = '王者荣耀64进32 (周四11:55)';
    type = 'week';
    deep = 3
    max = 64

    order(userlist) {
        userlist.sort((a, b) => a.groupinfo.order - b.groupinfo.order)
        return userlist
    }
}

export class SchedulerWzryZuanshifour extends SchedulerWzryZuanshiOne {
    id: schedulerType = 'wzry_zuanshifour';
    time = 3*24*3600 + 17*3600 + 55*60; //G.gc.wangzherongyao.wangzhe.eventtime.start64 + 1 * 60;
    name = '王者荣耀32进16 (周四17:55)';
    type = 'week';
    deep = 4
    max = 32

    order(userlist) {
        userlist.sort((a, b) => a.groupinfo.order - b.groupinfo.order)
        return userlist
    }
}

export class SchedulerWzryZuanshi16to8 extends SchedulerWzryZuanshiOne {
    id: schedulerType = 'wzry_zuanshi16to8';
    time = 3*24*3600 + 19*3600 + 55*60; //G.gc.wangzherongyao.wangzhe.eventtime.start64 + 1 * 60;
    name = '王者荣耀16进8 (周四19:55)';
    type = 'week';
    deep = 5
    max = 16

    order(userlist) {
        userlist.sort((a, b) => a.groupinfo.order - b.groupinfo.order)
        return userlist
    }
}

export class SchedulerWzryZuanshiSendPrize extends SchedulerWzryAutoBaoMing {
    id: schedulerType = 'wzry_zuanshisendprize';
    //time = G.gc.wangzherongyao.wangzhe.eventtime.zuanshisaisendprize;
    time = 3*24*3600 + 20*3600 + 10*60;
    name = '王者荣耀钻石赛结束发奖（周四20:10）';
    type = 'week';
    deep = 3        // 可以获奖的deep
    maxdeep = 6     // 此时最大的deep 避免重复执行
    max = 64   // 此时发奖人数
    typeprzie = 'zuanshi'
    // deep对应奖励下标
    idx = {
        6: 0,
        5: 1,
        4: 2,
        3: 3,

        9: 0,
        8: 1,
        7: 2
    }

    async start() {
        let deep = this.deep
        let _user = await G.mongodb.collection('wzry_fight').find({ deep: { $gte: deep, $lte: this.maxdeep } }).toArray()
        if (_user.length != this.max) {
            console.log("内网调时间导致重复执行,此次不执行")
            await this.record()
            return
        }
        let _prizeCon = this.typeprzie=='zhuanshi'?G.gc.wangzherongyao.wangzhe.jiangli.zuanshi:G.gc.wangzherongyao.wangzhe.jiangli.wangzhe;
        let _u = []
        for (let index = 0; index < _user.length; index++) {
            const element = _user[index];
            _u.push(element.uid)
            if (element.data.player.uid.indexOf('npc_') != -1) continue
            if (element?.isprize?.[this.typeprzie]) continue
            let prize = _prizeCon[this.idx[element.deep]]?.p || [];

            //注意：这里的调用addEmail时，cross参数用的是true
            //因为这个定时器是在跨服上执行的，邮件先临时放到跨服
            //在下方有个每天20:15运行的定时器：SchedulerWzrycrossEmail，负责从跨服里拿本地的邮件
            prize.length > 0 && EmailFun.addEmail({
                uid: element.uid,
                type: 'system',
                title: G.gc.wangzherongyao.wangzhe.email[this.typeprzie].title,
                content: G.gc.wangzherongyao.wangzhe.email[this.typeprzie].content,
                prize: PublicShared.mergePrize(prize),
                // 八强  ["冠军","亚军","四强","八强"]
                contentInsertArr: [this.idx[element.deep]]
            }, true)
        }
        await G.mongodb.collection('wzry_fight').updateMany(
            { uid: { $in: _u } },
            { $set: G.mongodb.createTreeObj({ key: `isprize.${this.typeprzie}`, val: 1 }) }
        )
        await this.record();
    }
}

export class SchedulerWzryWangZheone extends SchedulerWzryZuanshiOne {
    id: schedulerType = 'wzry_wangzheone';
    //time = G.gc.wangzherongyao.wangzhe.eventtime.start64 + 2 * 60;
    time = 3*24*3600 + 20*3600 + 10*60;
    name = '发八强竞猜通知邮件(周四20:10)';
    type = 'week';
    deep = 5
    max = 16

    order(userlist) {
        userlist.sort((a, b) => a.groupinfo.order - b.groupinfo.order)
        return userlist
    }

    async start() {
        super.start()
        // 全区邮件  竞猜王者开启
        EmailFun.addQuanFuEmail({
            uid: "system",
            type: 'system',
            title: G.gc.wangzherongyao.wangzhe.email.jingcaikaiqi.title,
            content: G.gc.wangzherongyao.wangzhe.email.jingcaikaiqi.content,
            prize: [],
            contentInsertArr: []
        })
    }
}

export class SchedulerWzryWangZhetwo extends SchedulerWzryZuanshiOne {
    id: schedulerType = 'wzry_wangzhetwo';
    //time = G.gc.wangzherongyao.wangzhe.eventtime.start8;
    time = 5*24*3600 + 11*3600 + 55*60;
    name = '王者荣耀八进四(周六11:55)';
    type = 'week';
    deep = 6
    max = 8

    order(userlist) {
        userlist.sort((a, b) => a.groupinfo.order - b.groupinfo.order)
        return userlist
    }
}

export class SchedulerWzryWangZhethree extends SchedulerWzryZuanshiOne {
    id: schedulerType = 'wzry_wangzhethree';
    //time = G.gc.wangzherongyao.wangzhe.eventtime.start8 + 1 * 60;
    time = 5*24*3600 + 17*3600 + 55*60;
    name = '王者荣耀四进二(周六17:55)';
    type = 'week';
    deep = 7
    max = 4

    order(userlist) {
        userlist.sort((a, b) => a.groupinfo.order - b.groupinfo.order)
        return userlist
    }
}

export class SchedulerWzryWangZhefour extends SchedulerWzryZuanshiOne {
    id: schedulerType = 'wzry_wangzhefour';
    //time = G.gc.wangzherongyao.wangzhe.eventtime.start8 + 2 * 60;
    time = 5*24*3600 + 19*3600 + 55*60;
    name = '王者荣耀决赛(周六19:55)';
    type = 'week';
    deep = 8
    max = 2

    order(userlist) {
        userlist.sort((a, b) => a.groupinfo.order - b.groupinfo.order)
        return userlist
    }
}

export class SchedulerWzryWangzheSendPrize extends SchedulerWzryZuanshiSendPrize {
    id: schedulerType = 'wzry_wangzhesendprize';
    //time = G.gc.wangzherongyao.wangzhe.eventtime.wanzhesaisendprize;
    time = 5*24*3600 + 20*3600 + 10*60;
    name = '王者荣耀王者赛结束发奖(周六20:10)';
    type = 'week';
    deep = 7        // 可以获奖的deep
    maxdeep = 9     // 此时最大的deep 避免重复执行
    max = 4   // 此时发奖人数
    typeprzie = 'wangzhe'
}

export class SchedulerWzryWangzheWZZD extends SchedulerWzryAutoBaoMing {
    id: schedulerType = 'wzry_wangzheWZZD';
    //time = G.gc.wangzherongyao.wangzhe.eventtime.start8 + 4 * 60;
    time = 5*24*3600 + 20*3600 + 5*60;
    name = '王者荣耀王者之巅保存四强数据（周六20:05）';
    type = 'week';

    async start() {
        let zkey = PublicShared.getToWeek()
        let _r = await G.mongodb.collection('wzrywiner').findOne({ zkey: zkey })
        if (_r) {
            console.log("本期数据已经保存,此次不执行")
            await this.record()
            return
        }

        let _user = await G.mongodb.collection('wzry_fight').find({ deep: { $gte: 7 }, zkey: zkey }).toArray();
        if (_user.length != 4) {
            console.log("王者赛4强还未决出,此次不执行")
            await this.record()
            return
        }
        let _rankList = []
        _user.sort((b, a) => a.deep - b.deep)
        for (let index = 0; index < _user.length; index++) {
            const element = _user[index];
            if (element.matchlog) delete element.matchlog
            delete element._id
            _rankList.push(element)
        }

        let _setData = {
            ranklist: _rankList,
            ctime: G.time,
            round: (await G.mongodb.collection('wzrywiner').countDocuments({}) || 0) + 1,
            zkey: zkey
        }
        await G.mongodb.collection('wzrywiner').insertOne(_setData)
        await this.record();
    }

}

export class SchedulerWzryjingcaiSendPrize extends SchedulerWzryAutoBaoMing {
    id: schedulerType = 'wzry_jingcaiprize';
    //time = G.gc.wangzherongyao.wangzhe.eventtime.wanzhesaisendprize;
    time = 5*24*3600 + 20*3600 + 10*60;
    name = '王者荣耀发送竞猜奖励（周六20:10）';     // 本服定时器
    type = 'week';

    async start() {
        let wzzdres = await WangZheRongYaofun.getWzzd('')
        if (!wzzdres.isSucc) {
            console.log("王者赛4强还未决出,此次不执行")
            await this.record()
            return
        }
        let wzzd = wzzdres.res.wzzd
        if (!wzzd || !wzzd.ranklist) return    // 增加无数据容错
        let _rank = []
        for (let index = 0; index < wzzd.ranklist.length; index++) {
            const element = wzzd.ranklist[index];
            _rank.push(element.uid)
            // 全区跑马灯  本服定时器执行pmd // todo
            // 对npc名字做一个处理
            // if (element.data.player.isNpc) element.data.player.name = element.data.player.nmae
            let playName = index + 1
            ChatFun.newMsg({
                type: 'local',
                //第1、2名可以区分，但是34都是4强，无法区分，所以单独用一句特别的语言包
                msg: playName<=2?G.gc.pmd.tlsd_pmd:"intr_pmd_tlsd_34",
                time: G.time,
                sender: 'system',
                otherData: {
                    pmd: true,
                    args: [element.data.player.name, playName]
                }
            })
        }
        let _jcAllNum = await (await G.clientCross.callApi('wzry/getJingCai', {})).res.num
        let _users = await G.mongodb.collection('playerInfo', 'wzry').find({ type: 'wzry', 'isjingcai.totalmoney': { $gt: 0 } }).toArray()
        let _chknum = await G.mongodb.collection('playerInfo', 'wzry').countDocuments({ type: 'wzry', 'isjingcai.guessuid': { $in: _rank } })
        for (let index = 0; index < _users.length; index++) {
            const element = _users[index];
            if (!element.isjingcai || !element.isjingcai.guessuid) continue    // 增加容错
            let idx = _rank.indexOf(element.isjingcai.guessuid)
            if (idx != -1 && _chknum != 0) {

                //某个玩家投注的钻石数量
                let totalmoney = element.isjingcai.totalmoney;
                //冠军给2倍返回，其他的1.5倍
                let xs = idx != 0 ? 1.5 : 2
                // @ts-ignore
                let _n = parseInt(totalmoney * xs); //parseInt(_jcAllNum * xs / _chknum) > _jcAllNum * 10 ? _jcAllNum * 10 : parseInt(_jcAllNum * xs / _chknum)
                let prize = [{ "a": "attr", "t": "rmbmoney", "n": _n }]
                prize.length > 0 && EmailFun.addEmail({
                    uid: element.uid,
                    type: 'system',
                    title: G.gc.wangzherongyao.wangzhe.email.jingcai.title,
                    content: G.gc.wangzherongyao.wangzhe.email.jingcai.content,
                    prize: PublicShared.mergePrize(prize),
                    contentInsertArr: [wzzd.ranklist[idx].data.player.name, idx]
                });
            } else {
                let prize = G.gc.wangzherongyao.wangzhe.email.jingcaifail.prize
                prize.length > 0 && EmailFun.addEmail({
                    uid: element.uid,
                    type: 'system',
                    title: G.gc.wangzherongyao.wangzhe.email.jingcaifail.title,
                    content: G.gc.wangzherongyao.wangzhe.email.jingcaifail.content,
                    prize: PublicShared.mergePrize(prize),
                    contentInsertArr: []
                })
            }
        }
        await this.record();
    }
}

export class SchedulerWzryendDel extends SchedulerWzryAutoBaoMing {
    id: schedulerType = 'wzry_end';
    time = 604500 + 4*60; // 周天23.59   本服执行
    name = '王者荣耀结束清除数据（周日23:59）';
    type = 'week';

    async start() {
        await WangZheRongYaofun.delGroup()
        await this.record();
    }
}

// 分组
export async function wzrygroup(userList) {
    let _u = shuffle(userList)
    let [_group, _orderid, order] = [1, 1, 1]
    for (let index = 0; index < _u.length; index++) {
        const element = _u[index];
        let _tmp: wangzherongyao_fight_group['groupinfo'] = {
            groupid: _group,
            orderid: _orderid,
            order: order
        }
        _orderid += 1
        order += 1
        if (_orderid > 8) {
            _orderid = 1
            _group += 1
        }
        await G.mongodb.collection('wzry_fight').updateOne({ uid: element }, { $set: { groupinfo: _tmp } })
    }
    return _u;
}

export function shuffle(array: []) {
    let copy = [],
        n = array.length,
        i;
    // 如果还剩有元素。。
    while (n) {
        // 随机选取一个元素
        i = Math.floor(Math.random() * n--);
        // 移动到新数组中
        copy.push(array.splice(i, 1)[0]);
    }
    return copy;
}