import { ACTIVITY_TYPE, getRedisKeyByRankType, GUILD_ACTIVITY_TYPE } from './../consts';
import * as Redis from 'redis';
import {REDIS_KEY} from '../consts'
import { pinus, ServerInfo } from 'pinus';
import { GuildRankParam, GuildLeader, RankParam, LineupParam, LeagueLeader } from '../domain/rank';
import { comBtlRanges } from '../pubUtils/data';
import { Rank, setRankRedisFromDb } from './rankService';
import { ServerlistModel } from '../db/Serverlist';
import moment = require('moment');
import { getRedisSubChannel } from '../pubUtils/sdkUtil';
import { getRandSingleEelm, parseNumberList } from '../pubUtils/util';
import { ActivityModel } from '../db/Activity';
import { TimeLimitRankData } from '../domain/activityField/timeLimitRankField';
import { ActivityTimeLimitRankModel } from '../db/ActivityTimeLimitRank';
import { RoleModel, RoleType } from '../db/Role';
import { GuildType } from '../db/Guild';
import { ActivityGroupModel } from '../db/ActivityGroup';
import { LadderMatchModel, LadderMatchType } from '../db/LadderMatch';
import { isDevelopEnv } from './utilService';

/**
 * 在服务重新启动时，将信息存入redis
 */
export async function initAllRank() {
    console.log('******* initAllRank ******')
    const serverList = await ServerlistModel.findByEnv(pinus.app.get('env'));
    await delKeys(REDIS_KEY.ONLINE_USERS);
    await delKeys(REDIS_KEY.ONLINE_CNT);
    await delKeys(REDIS_KEY.USER_INFO);
    await delKeys(REDIS_KEY.GUILD_INFO);
    await delKeys(REDIS_KEY.TOP_LINEUP_INFO);
    await delKeys(REDIS_KEY.HERO_INFO);
    await delKeys(REDIS_KEY.TOWER_RANK);
    await delKeys(REDIS_KEY.GUILD_LV_RANK);
    await delKeys(REDIS_KEY.GUILD_ACTIVE_RANK);
    await delKeys(REDIS_KEY.TOP_LINEUP_RANK);
    await delKeys(REDIS_KEY.TOP_HERO_RANK);
    await delKeys(REDIS_KEY.HERO_NUM_RANK);
    await delKeys(REDIS_KEY.USER_LV);
    await delKeys(REDIS_KEY.SUM_CE_RANK);
    // await delKeys(REDIS_KEY.DUNGEON_RANK);
    await delKeys(REDIS_KEY.DUNGEON_LINEUP);
    await delKeys(REDIS_KEY.MAIN_RANK);
    await delKeys(REDIS_KEY.MAIN_ELITE_RANK);
    await delKeys(REDIS_KEY.HERO_RANK);
    await delKeys(REDIS_KEY.SHOW_LINEUP);
    // await delKeys(REDIS_KEY.PVP_RANK);
    await delKeys(REDIS_KEY.GUILD_FUND);
    await delKeys(REDIS_KEY.SUM_CE_SNAPSHOT);
    await delKeys(REDIS_KEY.TOP_LINE_SNAPSHOT);
    await delKeys(REDIS_KEY.LADDER);
    await delKeys(REDIS_KEY.GVG_VESTIGE_MEMBER_ALL);
    await delKeys(REDIS_KEY.GVG_VESTIGE_LEAGUE);
    // 测试服特殊处理，由于重启较频繁且联军数据较少，数据先不删，正式服激战期间不会重启
    if(!isDevelopEnv()) await delKeys(REDIS_KEY.LEAGUE_INFO);

    await setRankRedisFromDb(REDIS_KEY.PVP_RANK, {});
    await setRankRedisFromDb(REDIS_KEY.GVG_VESTIGE_MEMBER_ALL, {});
    await setRankRedisFromDb(REDIS_KEY.GVG_VESTIGE_LEAGUE, {});
    
    for(let {id} of serverList) {
        await initRankByServerId(id);
        await initActivitiesRank(id)
    }
}

/**
 * 分服内初始redis排行榜 
 * 
 * @param serverId 服务器
 */
export async function initRankByServerId(serverId: number) {
    // console.log('*****', 'initRank')
    await setRankRedisFromDb(REDIS_KEY.TOWER_RANK, { serverId });
    await setRankRedisFromDb(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId });
    await setRankRedisFromDb(REDIS_KEY.GUILD_LV_RANK, { serverId });
    await setRankRedisFromDb(REDIS_KEY.TOP_LINEUP_RANK, { serverId });
    await setRankRedisFromDb(REDIS_KEY.TOP_HERO_RANK, { serverId });
    await setRankRedisFromDb(REDIS_KEY.HERO_NUM_RANK, { serverId });
    await setRankRedisFromDb(REDIS_KEY.USER_LV, { serverId });
    await setRankRedisFromDb(REDIS_KEY.SUM_CE_RANK, { serverId });
    // await setRankRedisFromDb(REDIS_KEY.DUNGEON_RANK, { serverId });
    await setRankRedisFromDb(REDIS_KEY.MAIN_RANK, { serverId });
    await setRankRedisFromDb(REDIS_KEY.MAIN_ELITE_RANK, { serverId });
    await setRankRedisFromDb(REDIS_KEY.HERO_RANK, { serverId });
    await setRankRedisFromDb(REDIS_KEY.LADDER, { serverId });
}

export async function initActivitiesRank(serverId: number) {
    let serverTime = await getServerCreateTime(serverId);
    let activityGroup = await ActivityGroupModel.findByServerId(serverId);
    let activityGroupId = activityGroup.map(cur => cur.groupId);
    let activities = await ActivityModel.findOpenActivityByType(activityGroupId, ACTIVITY_TYPE.TIME_LIMIT_RANK);
    for(let activity of activities) {
        let data = new TimeLimitRankData(activity, 0, serverTime);
        if(data.beginTime <= Date.now() && data.endTime >= Date.now()) {
            let redisKey = getRedisKeyByRankType(data.rankType, true);

            let ranks = await ActivityTimeLimitRankModel.getRank(serverId, data.activityId);
            let r = new Rank(redisKey, { serverId, activityId: data.activityId });
            r.setIsInit(true);
            for (let rank of ranks) {
                if(r.infoKey == REDIS_KEY.USER_INFO) {
                    await r.setRankWithRoleInfo(rank.roleId, rank.score, rank.time||0, <RoleType>rank.role);
                } else if(r.infoKey == REDIS_KEY.GUILD_INFO) {
                    await r.setRankWithGuildInfo(rank.guildCode, rank.score, rank.time||0, <GuildType>rank.guild);
                }
            }
        }
    }    
}

/**
 * 初始化某一个排行榜，如定时器内
 * @param key redis内的key
 */
export async function initSingleRank(key: string) {

    await delKeys(key);

    if(key == REDIS_KEY.PVP_RANK) {
        await setRankRedisFromDb(key, {});
    } else {
        const serverList = await ServerlistModel.findByEnv(pinus.app.get('env'));
        for(let { id } of serverList) {
            await setRankRedisFromDb(key, { serverId: id });
        }
    }
}

/** 
 * debug接口使用，直接删除排行榜数据
 * @param params serverId => guildCodes
 */
export async function delGuildActivityRank(aid: number) {
    if(aid == GUILD_ACTIVITY_TYPE.GATE_ACTIVITY) {
        await delKeys(REDIS_KEY.USER_GATE_ACTIVITY);
        await delKeys(REDIS_KEY.GATE_ACTIVITY);
    } else if (aid == GUILD_ACTIVITY_TYPE.CITY_ACTIVITY) {
        await delKeys(REDIS_KEY.USER_CITY_ACTIVITY);
        await delKeys(REDIS_KEY.CITY_ACTIVITY);
    } else if (aid == GUILD_ACTIVITY_TYPE.RACE_ACTIVITY) {
        await delKeys(REDIS_KEY.RACE_ACTIVITY);
    }
}

export async function delKeys(key: string) {
    let keys = await redisClient().keysAsync(`${key}*`);
    for(let key of keys) {
        await redisClient().delAsync(key);
    }
    return keys
}

export async function setUserInfo(key: string, roleId: string, params: RankParam|GuildRankParam|LineupParam[]) {
    let value = JSON.stringify(params);
    return await redisClient().hsetAsync(key, roleId, value);
}

export async function updateUserInfo(key: string, roleId: string, arr: Array<{field: string, value:(string|number|GuildLeader|LeagueLeader)}>) {
    let params = await redisClient().hgetAsync(key, roleId);
    if(params) {
        let obj = JSON.parse(params);
        for(let {field, value} of arr) {
            obj[field] = value;
        }
        return await redisClient().hsetAsync(key, roleId, JSON.stringify(obj));
    }
}

export async function findKeys(key: string) {
    let keys = await redisClient().keysAsync(`${key}*`);
    return keys
}

/********排行榜结束 */


/**************** 寻宝相关 start */

/**
 * @description 拼接匹配分组的 key
 * @param {number} lv 藏宝图品阶
 */
function getComTeamKey(lv: number) {
    return `${REDIS_KEY.COM_TEAM_SEARCH_PRE}:${lv}`;
}

/**
 * @description 拼接匹配分组中 member 的值
 * @param {string} roleId
 * @param {string} sid connector serverId
 * @returns
 */
function getComTeamValue(roleId: string, sid: string) {
    return `${roleId}:${sid}`;
}

/**
 * @description 把寻宝的玩家信息存入 redis
 * @export
 * @param {string} roleId
 * @param {string} sid
 * @param {Array<number>} qualityArr
 * @param {number} lvRange
 * @returns
 */
export async function setTeamSearchReq(roleId: string, sid: string, lvs: number[]) {
    let cmds = [];
    lvs.forEach(lv => {
        if (lv) {
            cmds.push(['sadd', getComTeamKey(lv), getComTeamValue(roleId, sid)]);
        }
    });
    const res = await redisClient().multi(cmds).execAsync();

    return res;
}

/**
 * @description 从匹配队列中删除某个用户
 * @export
 * @param {string} roleId
 * @param {string} sid
 * @param {number} lv 如果不填表示所有品阶
 */
export async function rmRoleFromQueue(roleId: string, sid: string, lvs?: number[]) {

    let cmds = [];
    if (lvs) {
        for(let lv of lvs) {
            cmds.push(['srem', getComTeamKey(lv), getComTeamValue(roleId, sid)]);
        }
    } else {
        for (let range of comBtlRanges()) {
            cmds.push(['srem', getComTeamKey(range), getComTeamValue(roleId, sid)]);
        }
    }
    await redisClient().multi(cmds).execAsync();
}

function getComCreateTeamKey(lv: number) {
    return `${REDIS_KEY.COM_TEAM_CREATED_TEAM}:${lv}`;
}

export async function setCreatedTeamToRedis(teamCode: string, lv: number) {
    let sid = pinus.app.getCurServer().id;
    await redisClient().hsetAsync(getComCreateTeamKey(lv), teamCode, sid);
}

export async function rmCreatedTeamFromRedis(teamCode: string, lv: number) {
    await redisClient().hdelAsync(getComCreateTeamKey(lv), teamCode);
}

/**
 * @description 在寻宝匹配队列中随机两个玩家
 * @export
 * @param {number} quality 队伍品质
 * @param {number} lvRange 等级范围
 * @returns
 */
export async function getTeamSearchByLv(lv: number) {
    // TODO: 操作不具有原子性
    const userInfos = await redisClient().srandmemberAsync(getComTeamKey(lv), 2);
    console.log('getTeamSearchByLv: ' + userInfos);
    if (!userInfos || !userInfos.length) return null;

    let res = [];
    for (let userInfo of userInfos) {
        const decodeData = `${userInfo}`.split(':');
        if (decodeData.length !== 2) return null;
        res.push({roleId: decodeData[0], sid: decodeData[1]});
    }
    console.log('getTeamSearchByLv res: ', res);
    return res;
}

export async function getCreatedTeamByLv(lvs: number[]) {
    let team: {lv: number, teamCode: string}[] = [];
    for(let lv of lvs) {
        let teams = await redisClient().hkeysAsync(getComCreateTeamKey(lv));
        team.push(...teams.map(teamCode => ({ lv, teamCode })));
    }
    return team;
}

export async function getComTeamSidByCode(lv: number, teamCode: string) {
    let sid = await redisClient().hgetAsync(getComCreateTeamKey(lv), teamCode);
    return sid
}

/**
 * @description 检查玩家是否在某个队列中等待寻宝匹配
 * @export
 * @param {string} roleId
 * @param {string} sid
 * @param {number} lv
 * @returns
 */
export async function checkRoleInQueue(roleId: string, sid: string, lvs: number[]) {
    for (let lv of lvs) {
        let res = await redisClient().sismemberAsync(getComTeamKey(lv), `${roleId}:${sid}`);
        if (res) {
            return true;
        }
    };

    return false;
}

/**
 * @description 清除所有的寻宝匹配队列
 * @export
 */
export async function clearComBtlQueue() {
    await delKeys(REDIS_KEY.COM_TEAM_SEARCH_PRE);
    await delKeys(REDIS_KEY.COM_TEAM_CREATED_TEAM);
}

export function setRedis(key: string, data: string) {
    redisClient().setAsync(key, data);
}

export async function getRedis(key: string) {
    const str =  await redisClient().getAsync(key);
    return str;
}

export async function delRedis(key: string) {
    await redisClient().delAsync(key);
}

export function redisSidKey(roleId: string) {
    return `login_roleId_${roleId}`;
}

export async function redisChannelServer(roomId: string) {
    const sid = await redisClient().hgetAsync(REDIS_KEY.CHANNEL_SERVERS, roomId);
    return sid;
}

export async function addRedisChannel(roomId: string, sid: string) {
    const result = await redisClient().hsetAsync(REDIS_KEY.CHANNEL_SERVERS, roomId, sid);
    return result;
}

export async function clearChannelServers() {
    const result = await redisClient().delAsync(REDIS_KEY.CHANNEL_SERVERS);
    return result;
}

/**
 * 玩家上线
 * @param roleId role表id
 * @param userCode user表唯一字符串标识
 * @param sid connector服的那个sid
 */
export async function roleLogin(roleId: string, userCode: string, sid: string, createTime: number, serverId: number, lv: number, topLineupCe: number) {
    await redisClient().hincrbyAsync(REDIS_KEY.ONLINE_CNT, roleId, 1);
    await redisClient().hsetAsync(REDIS_KEY.USER_CODE, userCode, roleId);
    return await redisClient().hsetAsync(REDIS_KEY.ONLINE_USERS, roleId, `${userCode}|${sid}|${createTime}|${serverId}|${lv}|${topLineupCe}`);
}

export async function updateRoleOnlineInfo(roleId: string, updateData: {lv?: number, topLineupCe?: number}) {
    let info = await getRoleOnlineInfo(roleId);
    if(info.isOnline) {
        return await redisClient().hsetAsync(REDIS_KEY.ONLINE_USERS, roleId, `${info.userCode}|${info.sid}|${info.createtime}|${info.serverId}|${updateData?.lv??info.lv}|${updateData?.topLineupCe??info.topLineupCe}`);
    }
}

/**
 * 玩家下线
 * @param roleId role表id
 */
export async function roleLeave(roleId: string) {
    let role = await getRoleOnlineInfo(roleId);
    let count = await redisClient().hincrbyAsync(REDIS_KEY.ONLINE_CNT, roleId, -1);
    if(count <= 0) {
        await redisClient().hdelAsync(REDIS_KEY.ONLINE_CNT, roleId);
        await redisClient().hdelAsync(REDIS_KEY.ONLINE_USERS, roleId);
        if(role) await redisClient().hdelAsync(REDIS_KEY.USER_CODE, role.userCode);
        await redisClient().hdelAsync(REDIS_KEY.ONLINE_CNT, roleId);
    }
    return role;
}

/**
 * 判断玩家是否在线
 * @param roleId role表id
 */
export async function isRoleOnline(roleId: string) {
    let result = await redisClient().hexistsAsync(REDIS_KEY.ONLINE_USERS, roleId);
    return !!result;
}

export async function getOnlineRoleByUserCode(userCode: string) {
    let roleId = await redisClient().hgetAsync(REDIS_KEY.USER_CODE, userCode);
    return roleId;
}

/**
 * 获得在线玩家userCode和sid
 * @param roleId 
 */
export async function getRoleOnlineInfo(roleId: string) {
    let str = await redisClient().hgetAsync(REDIS_KEY.ONLINE_USERS, roleId);
    if(str) {
        try {
            let result = str.split('|');
            let [userCode, sid, createTime, serverId, lv, topLineupCe] = result;

            return {
                isOnline: true, userCode, sid,
                createtime: parseInt(createTime),
                serverId: parseInt(serverId),
                lv: parseInt(lv),
                topLineupCe: parseInt(topLineupCe)
            }
        } catch(e) {
            return { isOnline: false }
        }
    } else {
        return { isOnline: false }
    }
}

export async function getRoleCreateTime(roleId: string, role?: RoleType) {
    if(role && role.createTime) return role.createTime;

    let onlineInfo = await getRoleOnlineInfo(roleId);
    if(onlineInfo.isOnline) {
        return onlineInfo.createtime;
    } else {
        let role = await RoleModel.findByRoleId(roleId);
        return role?.createTime||0;
    }
}

/**
 * 获得所有在线的玩家
 */
export async function getAllOnlineRoles() {
    let allRoles = await redisClient().hgetallAsync(REDIS_KEY.ONLINE_USERS);
    let result = new Array<{roleId: string, userCode: string, sid: string, serverId: number, lv: number, topLineupCe: number}>();
    for(let roleId in allRoles) {
        try{ 
            let param = allRoles[roleId].split('|');
            let [userCode, sid, _createTime, serverId, lv, topLineupCe] = param;

            result.push({ roleId, userCode, sid, serverId: parseInt(serverId), lv: parseInt(lv), topLineupCe: parseInt(topLineupCe) });
                
        } catch(e) {
            continue;
        }
    }
    return result;
}

/**
 * 将玩家登录时间记录到
 * @param userCode 玩家user表里的userCode 
 * @param isToday 累计记录还是当日记录
 * @returns 分钟
 */
export async function incOnlineTime(userCode: string, isToday: boolean, incTime: number) {
    moment.locale('zh-cn');
    let today = moment().format('YYYYMMDD');
    let key = isToday? `${REDIS_KEY.ONLINE_TIME}:${today}`: REDIS_KEY.ONLINE_TIME;
    if(isToday) {
        let tomorrow = moment().add(1, 'days').hours(0).minutes(0).seconds(0).unix();
        let result = await redisClient().hincrbyAsync(key, userCode, incTime);
        let result2 = await redisClient().expireatAsync(key, tomorrow);
        // console.log(result2)
        return result;
    } else {
        return await redisClient().hincrbyAsync(key, userCode, incTime);
    }
}

export async function setOnlineTime(userCode: string, isToday: boolean, setTime: number) {
    moment.locale('zh-cn');
    let today = moment().format('YYYYMMDD');
    let key = isToday? REDIS_KEY.ONLINE_TIME: `${REDIS_KEY.ONLINE_TIME}:${today}`;
    if(isToday) {
        let tomorrow = moment().add(1, 'days').hours(0).minutes(0).seconds(0).format('x');
        await redisClient().expireatAsync(key, parseInt(tomorrow));
    }
    return await redisClient().hsetAsync(key, userCode, setTime);
}


// 排行榜是否存在
export async function smembersAsync(key: string) {
    const result = await redisClient().smembersAsync(key);
    return result;
}

export async function saddAsync(key: string, values: Array<string>) {
    const result = await redisClient().saddAsync(key, values);
    return result;
}

export async function sismemberAsync(key: string, value: string) {
    const result = await redisClient().sismemberAsync(key, value);
    return result;
}

export async function delAsync(key:string) {
    await redisClient().delAsync(key);
}

export async function sremAsync(key:string, member:string) {
    await redisClient().sremAsync(key, member);
}
/**************** 寻宝相关 end */

/**************** 数据库表存入缓存 */

export async function readDataBase() {
    await setServerList();
}

async function setServerList() {
    const serverList = await ServerlistModel.getAllServerList();
    await redisClient().delAsync(REDIS_KEY.SERVER);
    await redisClient().delAsync(REDIS_KEY.SERVER_OPEN_TIME);

    for(let { id, serverId, name, openTime, env } of serverList) {
        if(env == pinus.app.get('env')) {
            // console.log(roleId);
            await redisClient().hsetAsync(REDIS_KEY.SERVER, `${id}`, `${name}`);
            await redisClient().hsetAsync(REDIS_KEY.SERVER_OPEN_TIME, `${id}`, `${openTime}`);
        }
    }
}

export async function getAllServers() {
    let servers = await  redisClient().hgetallAsync(REDIS_KEY.SERVER);
    let serverlist = new Array<number>();
    for(let serverStr in servers) {
        let serverId = parseInt(serverStr);
        
        if(!isNaN(serverId) && !serverlist.includes(serverId)) {
            serverlist.push(serverId);
        }
    }
    return serverlist;
}

export async function getAllServerName(): Promise<{[serverId: string]: string}> {
    let servers = await redisClient().hgetallAsync(REDIS_KEY.SERVER);
    return servers;
}

export async function getServerName(serverId: number) {
    let name = await redisClient().hgetAsync(REDIS_KEY.SERVER, `${serverId}`);
    return name||'常山少年'
}

export async function getServerCreateTime(serverId: number) {
    let time = await redisClient().hgetAsync(REDIS_KEY.SERVER_OPEN_TIME, `${serverId}`);
    return parseInt(time);
}

export async function getAllServerCreateTime() {
    let servers = await  redisClient().hgetallAsync(REDIS_KEY.SERVER_OPEN_TIME);
    return servers;
}

export function redisClient() {
    const client: Redis.RedisClient = pinus.app.get('redis');
    return client;
}

export async function hasKey(key: string) {
    return await redisClient().existsAsync(key);
}

/**************** 数据库表end */

/**************** 名将擂台防守战力 */
export async function saveLadderDefCeByData(roleId: string, ladderMatch?: LadderMatchType) {
    if(!ladderMatch) {
        ladderMatch = await LadderMatchModel.findByRoleId(roleId);
        if(!ladderMatch) return;
    }
    let heroes = ladderMatch.defense?.heroes||[];
    let defCe = heroes.reduce((pre, cur) => pre + cur.ce, 0);
    await saveLadderDefCe(roleId, defCe);
}

export async function saveLadderDefCe(roleId: string, defCe: number) {
    await redisClient().hsetAsync(REDIS_KEY.LADDER_DEFCE, `${roleId}`, defCe);
}

export async function getLadderDefCe(roleId: string) {
    let defCe = await redisClient().hgetAsync(REDIS_KEY.LADDER_DEFCE, `${roleId}`);
    return defCe||0;
}

/**************** 名将擂台防守战力end */

/*************** 将connector服插入redis *******/

export async function setConnectors(servers: ServerInfo[]) {
    for(let server of servers) {
        if(server.serverType == 'connector' && server.id != 'connector-server-gm') {
            let { serverType, clientHost, clientPort, id } = server;
            await redisClient().hsetAsync(REDIS_KEY.SYS_SERVER, server.id, JSON.stringify({ serverType, clientHost, clientPort, id }));
        }
    }
}

export async function removeConnectors(servers: string[]) {
    for(let server of servers) {
        let hasServer = await redisClient().hgetAsync(REDIS_KEY.SYS_SERVER, server);
        if(!!hasServer) await redisClient().hdelAsync(REDIS_KEY.SYS_SERVER, server);
    }
}

export async function checkConnectors() {
    let servers = pinus.app.getServersByType('connector');
    let redisServers = await redisClient().hgetallAsync(REDIS_KEY.SYS_SERVER);
    for(let id in redisServers) {
        let server = servers.find(cur => cur.id == id);
        if(!server || server.id == 'connector-server-gm') {
            await redisClient().hdelAsync(REDIS_KEY.SYS_SERVER, id);
        }
    }
}

export async function incConnectorNum(sid: string, inc: number) {
    let server = await redisClient().hgetAsync(REDIS_KEY.SYS_SERVER, sid);
    let json = JSON.parse(server);
    let { id, serverType, clientHost, clientPort, num = 0 } = json;
    let newNum = num + inc;
    if(newNum < 0) newNum = 0;
    await redisClient().hsetAsync(REDIS_KEY.SYS_SERVER, id, JSON.stringify({ serverType, clientHost, clientPort, id, num: newNum }));
}

/*************** 将connector服插入redis *******/


/*************** 订阅短链接redis *******/

export function redisClientPub() {
    const client: Redis.RedisClient = pinus.app.get('redisPub');
    return client;
}

export async function redisSubScribe() {
    let env = pinus.app.get('env');
    if(env == 'development') env = 'local';  // 本地处理
    let payChannel = getRedisSubChannel(REDIS_KEY.PAY_CHANNEL, env);
    let refundChannel = getRedisSubChannel(REDIS_KEY.REFUND_CHANNEL, env);
    let treatRoleChannel = getRedisSubChannel(REDIS_KEY.TREAT_ROLE_CHANNEL, env);
    let treatGuildChannel = getRedisSubChannel(REDIS_KEY.TREAT_GUILD_CHANNEL, env);
    let surveyChannel = getRedisSubChannel(REDIS_KEY.SURVEY_CHANNEL, env);
    let userChannel = getRedisSubChannel(REDIS_KEY.USER_CHANNEL, env);
    await redisClientPub().subscribeAsync(payChannel, treatRoleChannel, treatGuildChannel, refundChannel, surveyChannel, userChannel);
    redisClientPub().on('message', (channel, message) => {
        console.log('**********redisSubScribe*******')
        console.log('channel: ', channel, payChannel);

        if(channel == payChannel) {
            let servers = pinus.app.getServersByType('order');
            let server = getRandSingleEelm(servers);
            pinus.app.rpc.order.orderRemote.settleOrderFromRedisPub.toServer(server.id, message);
        } else if (channel == treatRoleChannel) {
            let servers = pinus.app.getServersByType('role');
            let server = getRandSingleEelm(servers);
            pinus.app.rpc.role.roleRemote.treatRoleName.toServer(server.id, message);
        } else if (channel == treatGuildChannel) {
            let servers = pinus.app.getServersByType('guild');
            let server = getRandSingleEelm(servers);
            pinus.app.rpc.guild.guildRemote.treatGuildName.toServer(server.id, message);
        } else if (channel == refundChannel) {
            let servers = pinus.app.getServersByType('order');
            let server = getRandSingleEelm(servers);
            pinus.app.rpc.order.orderRemote.refundOrderFromRedisPub.toServer(server.id, message);
        } else if (channel == surveyChannel) {
            let servers = pinus.app.getServersByType('role');
            let server = getRandSingleEelm(servers);
            pinus.app.rpc.role.roleRemote.sendSurveyMail.toServer(server.id, message);
        } else if(channel == userChannel) {
            let [sid, roleId] = (message||'').split('|');
            if(!!sid && !!roleId) pinus.app.rpc.connector.connectorRemote.remoteLogin.toServer(sid, roleId);
        }
    });
} 
/*************** 订阅短链接redis *******/

/***诸侯混战 */
export async function getHistoryCity(roleId: string) {
    return await redisClient().hgetAsync(REDIS_KEY.GA_HISTORY_CITY, `${roleId}`);
}

export async function setHistoryCity(roleId: string, cityId: number) {
    await redisClient().hsetAsync(REDIS_KEY.GA_HISTORY_CITY, `${roleId}`, cityId);
}

// gvg激战期玩家之前所处的区域，用于退出的时候查询
export async function getGVGHistoryAreas(roleId: string) {
    let areaIds = await redisClient().hgetAsync(REDIS_KEY.GVG_HISTORY_AREA, roleId);
    if(!areaIds) return []
    return areaIds.split('&');
}

export async function addGVGHistoryAreas(roleId: string, groupKey: string, areaIds: number[]) {
    let key = areaIds.map(areaId => `${groupKey}_${areaId}`).join('&');
    const result = await redisClient().hsetAsync(REDIS_KEY.GVG_HISTORY_AREA, roleId, key);
    return result;
}

export async function delGVGHistoryAreas(roleId: string) {
    const result = await redisClient().hdelAsync(REDIS_KEY.GVG_HISTORY_AREA, roleId);
    return result;
}

export async function clearGVGHistoryAreas() {
    const result = await redisClient().delAsync(REDIS_KEY.GVG_HISTORY_AREA);
    return result;
}


export async function getGVGHistoryAreaTeam(roleId: string) {
    let channelName = await redisClient().hgetAsync(REDIS_KEY.GVG_HISTORY_AREA_TEAM, roleId);
    return channelName
}

export async function addGVGHistoryAreaTeam(roleId: string, groupKey: string, areaId: number) {
    const result = await redisClient().hsetAsync(REDIS_KEY.GVG_HISTORY_AREA_TEAM, roleId, `${groupKey}_${areaId}`);
    return result;
}

export async function delGVGHistoryAreaTeam(roleId: string) {
    const result = await redisClient().hdelAsync(REDIS_KEY.GVG_HISTORY_AREA_TEAM, roleId);
    return result;
}

export async function clearGVGHistoryAreaTeam() {
    const result = await redisClient().delAsync(REDIS_KEY.GVG_HISTORY_AREA_TEAM);
    return result;
}


export async function getGVGHistoryCityTeam(roleId: string) {
    let channelName = await redisClient().hgetAsync(REDIS_KEY.GVG_HISTORY_CITY, roleId);
    return channelName
}

export async function addGVGHistoryCityTeam(roleId: string, groupKey: string, cityId: number) {
    const result = await redisClient().hsetAsync(REDIS_KEY.GVG_HISTORY_CITY, roleId, `${groupKey}_${cityId}`);
    return result;
}

export async function delGVGHistoryCityTeam(roleId: string) {
    const result = await redisClient().hdelAsync(REDIS_KEY.GVG_HISTORY_CITY, roleId);
    return result;
}

export async function clearGVGHistoryCityTeam() {
    const result = await redisClient().delAsync(REDIS_KEY.GVG_HISTORY_CITY);
    return result;
}


