import { Service } from 'egg';
import { REDIS_KEY, STATUS } from '@consts';
import { ServerlistModel } from '@db/Serverlist';
import { gameData } from '@pubUtils/data';
import { DicHero } from '@pubUtils/dictionary/DicHero';
import { DicRMB } from '@pubUtils/dictionary/DicRMB';
import { DicActivityType } from '@pubUtils/dictionary/DicActivityType';
import { DicTaskType } from '@pubUtils/dictionary/DicTaskType';
import { NoticeModel, NoticeTypeParam } from '@db/Notice';
import Marquee, { MarqueeModel } from '@db/Marquee';
import { AccuseRecModel } from '@db/AccuseRec';
import { RegionModel } from '@db/Region';
import { ActivityGroupModel } from '@db/ActivityGroup';
import { nowSeconds } from '@pubUtils/timeUtil';
import { WhiteListModel } from '@db/RegionWhiteList';
import { SearchMarqueeParam, SearchOrderParam, SearchSurveyParam } from '@domain/backEndField/search';
import { DicServerName } from '@pubUtils/dictionary/DicServerName';
import { CreateRegionParam, UpdateChannelParam } from '@domain/backEndField/params';
import { UserOrderModel } from '@db/UserOrder';
import { SurveyModel } from '@db/Survery';
import { RedisClient } from 'redis';
import { ChannelInfoModel } from '@db/ChannelInfo';
import { PVPConfigModel } from '@db/PvpConfig';
import { HiddenDataByIdModel } from '@db/HiddenDataById';
import { isNumber } from 'util';
import { GVGServerGroupModel } from '@db/GVGServerGroup';
import { GVGConfigModel } from '@db/GVGConfig';

/**
 * Test Service
 */
export default class Game extends Service {

    public async getRegions() {
        const { ctx } = this;
        let user = ctx.user;
        let list = [];
        if(user.envs.indexOf('all') != -1) {
            list = await RegionModel.getAllRegion();
        } else {
            list = await RegionModel.findRegionByEnvs(user.envs||[]);
        }
        return ctx.service.utils.resResult(STATUS.SUCCESS, {
            list
        });
    }

    public async createRegion(values: CreateRegionParam) {
        const { ctx } = this;
        let param = new CreateRegionParam(values);

        if(!param.checkParams()) return this.ctx.service.utils.resResult(STATUS.WRONG_PARMS);
        let region = await RegionModel.createNewRegion(param, ctx.user?.uid)
        return ctx.service.utils.resResult(STATUS.SUCCESS, {
            region
        });
    }

    public async getServers() {
        const { ctx } = this;

        const list = await ServerlistModel.getAllServerList();
        console.log('******', list)
        return ctx.service.utils.resResult(STATUS.SUCCESS, {
            list
        });
    }

    public async getChannelInfo() {
        const { ctx } = this;

        const list = await ChannelInfoModel.findAll();
        return ctx.service.utils.resResult(STATUS.SUCCESS, {
            list
        });
    }

    public async updateChannel(param: UpdateChannelParam) {
        const { ctx } = this;
        if(!param.checkParams()) return ctx.service.utils.resResult(STATUS.WRONG_PARMS);
     
        await ChannelInfoModel.updateChannel(param.code, param);
        return ctx.service.utils.resResult(STATUS.SUCCESS);
    }
    

    public async getOnlineUsersByServer() {
        const { ctx } = this;
        let redisClient: RedisClient = ctx.app.context.redisClient;
        let allRoles = await redisClient.hgetallAsync(REDIS_KEY.ONLINE_USERS);
        let result: { serverId: number, count: number }[] = [];
        for(let roleId in allRoles) {
            try{ 
                let param = allRoles[roleId].split('|');
                let [,,,_serverId] = param;
                let serverId = parseInt(_serverId);
                let index = result.findIndex(cur => cur.serverId == serverId);
                if(index == -1) {
                    result.push({ serverId, count: 1 });
                } else {
                    result[index].count++;
                }
            } catch(e) {
                continue;
            }
        }
        return ctx.service.utils.resResult(STATUS.SUCCESS, {
            result
        });
    }

    public async stopServerRegister(id: number) {
        const { ctx } = this;
        const server = await ServerlistModel.updateByServerId(id, { stopRegisterTime: nowSeconds() - 1 });
        if(!server) return ctx.service.utils.resResult(STATUS.WRONG_PARMS);
        return ctx.service.utils.resResult(STATUS.SUCCESS);
    }

    public async switchServerStatus(id: number, status: number) {
        const { ctx } = this;
        const server = await ServerlistModel.updateByServerId(id, { serverStatus: status });
        if(!server) return ctx.service.utils.resResult(STATUS.WRONG_PARMS);
        return ctx.service.utils.resResult(STATUS.SUCCESS);
    }

    public async switchServerReview(id: number, isReview: boolean) {
        const { ctx } = this;
        const server = await ServerlistModel.updateByServerId(id, { isReview });
        if(!server) return ctx.service.utils.resResult(STATUS.WRONG_PARMS);
        return ctx.service.utils.resResult(STATUS.SUCCESS);
    }

    public async getRegionStategy(id: number) {
        const { ctx } = this;
        let region = await RegionModel.findRegionById(id);
        if(!region) return ctx.service.utils.resResult(STATUS.WRONG_PARMS);

        let activityGroups = await ActivityGroupModel.findAllActivityGroup();

        return ctx.service.utils.resResult(STATUS.SUCCESS, {
            region, activityGroups
        });
    }

    public async getWhiteList(id: number) {
        const { ctx } = this;
        let region = await RegionModel.findRegionById(id);
        if(!region) return ctx.service.utils.resResult(STATUS.WRONG_PARMS);

        let whitelist = await WhiteListModel.findByRegionId(id);

        return ctx.service.utils.resResult(STATUS.SUCCESS, {
            whitelist
        });
    }

    public async updateWhiteList(id: number, code: string, type: number, content: string) {
        const { ctx } = this;
        let region = await RegionModel.findRegionById(id);
        if(!region) return ctx.service.utils.resResult(STATUS.WRONG_PARMS);
        if(type == 1) {
            let whitelist = await WhiteListModel.updateWhiteList(code, { type, regionId: region.id, env: region.env, ip: content });
            return ctx.service.utils.resResult(STATUS.SUCCESS, { whitelist });
        } else if(type == 2) {
            if(!isNumber(content)) return ctx.service.utils.resResult(STATUS.WRONG_PARMS);
            let whitelist = await WhiteListModel.updateWhiteList(code, { type, regionId: region.id, env: region.env, uid: parseInt(content) });
            return ctx.service.utils.resResult(STATUS.SUCCESS, { whitelist });
        } else {
            return ctx.service.utils.resResult(STATUS.WRONG_PARMS);
        }
    }

    public async deleteWhiteList(id: number, code: string) {
        const { ctx } = this;
        let region = await RegionModel.findRegionById(id);
        if(!region) return ctx.service.utils.resResult(STATUS.WRONG_PARMS);
        let whitelist = await WhiteListModel.deleteWhiteList(code);
        return ctx.service.utils.resResult(STATUS.SUCCESS, { whitelist });
    }

    public async getDicHero() {
        let list: DicHero[] = [];
        for(let [heroId, hero] of gameData.hero) {
            if(heroId <= 300) {
                list.push(hero)
            }
        }
        return this.ctx.service.utils.resResult(STATUS.SUCCESS, {
            list
        })
    }

    public async getDicGoods() {
        let list = [];
        for(let [_, { good_id, name, quality, itid, image_id }] of gameData.goods) {
            list.push({
                good_id, name, quality, itid, image_id
            })
        }
        return this.ctx.service.utils.resResult(STATUS.SUCCESS, {
            list
        })
    }

    public async getDicRmb() {
        let list: DicRMB[] = [];
        for(let [_, dicRmb] of gameData.rmb) {
            list.push(dicRmb);
        }
        return this.ctx.service.utils.resResult(STATUS.SUCCESS, {
            list
        })
    }

    public async getDicActivityType() {
        let list: DicActivityType[] = gameData.activityType;
        return this.ctx.service.utils.resResult(STATUS.SUCCESS, {
            list
        })
    }

    public async getDicTaskType() {
        let list: DicTaskType[] = gameData.taskTypeDesc;
        return this.ctx.service.utils.resResult(STATUS.SUCCESS, {
            list
        })
    }

    public async getServerName() {
        let list: DicServerName[] = [];
        for(let [_, serverName] of gameData.serverNames) {
            list.push(serverName);
        }
        return this.ctx.service.utils.resResult(STATUS.SUCCESS, {
            list
        })
    }

    public async getOrderlist(page: number, pageSize: number, sortField: string, sortOrder: string, form: SearchOrderParam) {
        const { ctx } = this;
        const list = await UserOrderModel.findByCondition(page, pageSize, sortField, sortOrder, form);
        const total = await UserOrderModel.countByCondition( form )
        return ctx.service.utils.resResult(STATUS.SUCCESS, {
            list: list.map(cur => {
                return { ...cur, createdAt: cur.createdAt.getTime(), updatedAt: cur.updatedAt.getTime(), env: this.app.config.realEnv }
            }), total
        });
    }

    public async getNoticeList(page: number, pageSize: number, sortField: string, sortOrder: string, form: { content?: string }) {
        const { ctx } = this;
        const list = await NoticeModel.findByCondition(page, pageSize, sortField, sortOrder, form);
        const total = await NoticeModel.countByCondition( form )
        return ctx.service.utils.resResult(STATUS.SUCCESS, {
            list: list.map(cur => {
                return { ...cur, showEndTime: cur.showEndTime.getTime(), showStartTime: cur.showStartTime.getTime(), env: this.app.config.realEnv }
            }), total
        });
    }

    public async updateNotice(id: string|number, params: NoticeTypeParam) {
        const { ctx } = this;
        if(params.showStartTime) params.showStartTime = new Date(params.showStartTime);
        if(params.showEndTime) params.showEndTime = new Date(params.showEndTime);
        let result = await NoticeModel.updateNotice(id, params);
        if(!result) return ctx.service.utils.resResult(STATUS.WRONG_PARMS);
        return ctx.service.utils.resResult(STATUS.SUCCESS);
    }

    public async delNotice(id: number) {
        const { ctx } = this;
        let result = await NoticeModel.delNotice(id);
        if(!result) return ctx.service.utils.resResult(STATUS.WRONG_PARMS);
        return ctx.service.utils.resResult(STATUS.SUCCESS);
    }


    public async getMarqueeList(page: number, pageSize: number, sortField: string, sortOrder: string, form: SearchMarqueeParam) {
        const { ctx } = this;
        const list = await MarqueeModel.findByCondition(page, pageSize, sortField, sortOrder, form);
        const total = await MarqueeModel.countByCondition( form )
        return ctx.service.utils.resResult(STATUS.SUCCESS, {
            list, total
        });
    }

    public async updateMarquee(code: string, values: any) {
        const { ctx } = this;
        let params = new Marquee();
        params.setByForm(values);

        let result;
        if(code == 'new') {
            result = await MarqueeModel.createData(params);
        } else {
            result = await MarqueeModel.updateData(code, params);
        }
        if(!result) return ctx.service.utils.resResult(STATUS.WRONG_PARMS);
        return ctx.service.utils.resResult(STATUS.SUCCESS, { code: result.code });
    }

    public async getAccuse(page: number, pageSize: number, sortField: string, sortOrder: string, form: {}) {
        const { ctx } = this;
        const list = await AccuseRecModel.findByCondition(page, pageSize, sortField, sortOrder, form);
        const total = await AccuseRecModel.countByCondition( form )
        return ctx.service.utils.resResult(STATUS.SUCCESS, {
            list, total
        });
    }

    public async getSurveylist(page: number, pageSize: number, sortField: string, sortOrder: string, form: SearchSurveyParam) {
        const { ctx } = this;
        const list = await SurveyModel.findByCondition(page, pageSize, sortField, sortOrder, form);
        const total = await SurveyModel.countByCondition( form )
        return ctx.service.utils.resResult(STATUS.SUCCESS, {
            list: list.map(cur => {
                return { ...cur, env: this.app.config.realEnv }
            }), total
        });
    }

    public async getPvpConfig(page: number, pageSize: number, sortField: string, sortOrder: string) {
        const { ctx } = this;
        const list = await PVPConfigModel.findByCondition(page, pageSize, sortField, sortOrder);
        const total = await PVPConfigModel.countByCondition()
        return ctx.service.utils.resResult(STATUS.SUCCESS, {
            list, total
        });
    }

    public async getHiddenData(page: number, pageSize: number, sortField: string, sortOrder: string, form: any) {
        const { ctx } = this;

        const list = await HiddenDataByIdModel.findByCondition(page, pageSize, sortField, sortOrder, form);
        const total = await HiddenDataByIdModel.countByCondition(form);
        return ctx.service.utils.resResult(STATUS.SUCCESS, {
            list: list.map(cur => {
                return { ...cur, env: this.app.config.realEnv }
            }), total
        });
    }

    public async getExistHiddenData(type: number) {
        const { ctx } = this;
        let datas = await HiddenDataByIdModel.findExistData(type);
        let existIds = datas.map(cur => cur.id);

        return ctx.service.utils.resResult(STATUS.SUCCESS, {
            ids: existIds
        });
    }

    public async getGVGServerGroup() {
        const { ctx } = this;
        const serverlists = await ServerlistModel.findByEnv(this.app.config.realEnv);
        const currentTypes = await GVGServerGroupModel.findByTime(nowSeconds());
        const nextTypes = await GVGServerGroupModel.findByTime(nowSeconds() + 7 * 86400);

        const servers = serverlists.map(server => {
            let current = currentTypes.find(obj => obj.serverId == server.id);
            let next = nextTypes.find(obj => obj.serverId == server.id);
            let dic = gameData.serverNames.get(server.serverId);
            return { id: server.id, serverId: server.serverId, name: server.name, current: current?.groupId|| dic.groupId, next: next?.groupId|| current?.groupId || dic.groupId, env: this.app.config.realEnv }
        });

        return ctx.service.utils.resResult(STATUS.SUCCESS, {
            list: servers
        });
    }

    public async getGVGConfig() {
        const { ctx } = this;
        const gvgconfig = await GVGConfigModel.findConfig();

        return ctx.service.utils.resResult(STATUS.SUCCESS, {
            list: gvgconfig?[{...gvgconfig, env: this.app.config.realEnv }]: []
        });
    }
}
