/********** 37sdk **********/

import { RoleModel, RoleType } from "../db/Role";
import { Chat37Params, CheckGuild37Params, CheckName37Params, GetWordParam } from "../domain/sdk";
import { sendMailByContent, sendMailToGuildByContent } from './mailService';
import { NAMEPLATE } from '../pubUtils/dicParam';
import { CHANNEL_PREFIX, FILENAME, getSdkChannelId, MAIL_TYPE, PUSH_ROUTE, REDIS_KEY, SDK_37_ADDR, SDK_37_CONST, SDK_TA_CONST, STATUS, TA_EVENT, TA_USERSET_TYPE, THINKING_DATA_MODE, THINKING_DATA_MODE_LIST } from "../consts";
import { UserModel } from "../db/User";
import { request37CheckChat, request37GetWord, request37Post } from "../pubUtils/httpUtil";
import { GuildModel } from "../db/Guild";
import { getRoleOnlineInfo, updateUserInfo } from "./redisService";
import { Application, pinus } from "pinus";
import { getRandSingleEelm, parseGoodStr, readWordTxt, resResult, writeWordTxt } from "../pubUtils/util";
const ThinkingAnalytics = require("thinkingdata-node");
import Trie from '../pubUtils/trie';
import _ = require("underscore");
import { getGoldObject } from "./role/rewardService";
import { SurveyRecModel } from "../db/SurveyRec";
import { SurveyModel } from "../db/Survery";
import { pushGuildInfoUpdate } from "./guildService";
import { sendMessageToUserWithSuc } from "./pushService";
import { GuildLeader } from "../domain/rank";
import { initTaLoggingMode } from "./sdk/ta";

// 检查私聊是否合法

export async function checkPrivateChat(roleId: string, targetRoleId: string, message: string) {
    let body = new Chat37Params(message, getSdkChannelId('private'));
    let myRole = await RoleModel.findByRoleId(roleId);
    let myUser = await UserModel.findUserByUid(myRole.userInfo.uid);
    if(myUser.channelInfo) {
        body.setByMyRole(myRole, myUser);
        let targetRole = await RoleModel.findByRoleId(targetRoleId);
        let targetUser = await UserModel.findUserByUid(targetRole.userInfo.uid);
        body.setByTargetRole(targetRole, targetUser);
        return await request37CheckChat(SDK_37_ADDR.CHECK_CHAT, body, SDK_37_CONST.CHAT_KEY);
    }
    return true;
}

export async function checkGuildChat(roleId: string, guildCode: string, message: string) {
    let body = new Chat37Params(message, getSdkChannelId(CHANNEL_PREFIX.GUILD));
    let myRole = await RoleModel.findByRoleId(roleId);
    let myUser = await UserModel.findUserByUid(myRole.userInfo.uid);
    if(myUser.channelInfo) {
        body.setByMyRole(myRole, myUser);
        body.setByGuild(guildCode);
        return await request37CheckChat(SDK_37_ADDR.CHECK_CHAT, body, SDK_37_CONST.CHAT_KEY);
    }
    return true;
}

export async function checkOtherChat(roleId: string, channelPrefix: string, message: string) {
    let body = new Chat37Params(message, getSdkChannelId(channelPrefix));
    let myRole = await RoleModel.findByRoleId(roleId);
    let myUser = await UserModel.findUserByUid(myRole.userInfo.uid);
    if(!!myUser.channelInfo) {
        body.setByMyRole(myRole, myUser);
        return await request37CheckChat(SDK_37_ADDR.CHECK_CHAT, body, SDK_37_CONST.CHAT_KEY);
    }
    return true;
}

export async function checkRoleName(roleId: string, roleName: string, myRole?: RoleType) {
    if(!myRole) {
        myRole = await RoleModel.findByRoleId(roleId);
    }
    let myUser = await UserModel.findUserByUid(myRole.userInfo.uid);
    if(!!myUser.channelInfo) {
        let body = new CheckName37Params(myRole, roleName, myUser);
        let result = await request37Post(SDK_37_ADDR.CHECK_NAME, body, SDK_37_CONST.CHAT_KEY);
        if(result == STATUS.REQUEST_TIME_OUT.code) { // 超时
            return await checkFilterWords(roleName);
        } else if (result == 0) {
            return false;
        }
    }
    return true;
}

export async function checkGuildName(guildCode: string, serverId: number, name: string, notice: string) {
    let nameResult = true, noticeResult = true;
    if(name != undefined) {
        let body = new CheckGuild37Params(guildCode, serverId, 1, name);
        let result = await request37Post(SDK_37_ADDR.CHECK_UNION, body, SDK_37_CONST.CHAT_KEY);
        if(result == STATUS.REQUEST_TIME_OUT.code) { // 超时
            nameResult = await checkFilterWords(name);
        } else if (result == 0) {
            nameResult = false;
        }
    }
    if(notice != undefined) {
        if(notice == '') notice = ' ';
        let body = new CheckGuild37Params(guildCode, serverId, 2, notice);
        let result = await request37Post(SDK_37_ADDR.CHECK_UNION, body, SDK_37_CONST.CHAT_KEY);
        if(result == STATUS.REQUEST_TIME_OUT.code) { // 超时
            noticeResult = await checkFilterWords(name);
        } else if (result == 0) {
            noticeResult = false;
        }
    }
    return nameResult && noticeResult
}


// 根据37sdk处理违规玩家名
export async function treatRoleName(roleId: string, isDebug?: boolean) {
    let role = await RoleModel.findByRoleId(roleId);
    if((role && role.sdkMark) || isDebug) { // 有设置标记的情况下
        let newName = "默认玩家名";
        // 新名字上传
        await checkRoleName(roleId, newName, role);
        // 改名字
        await RoleModel.updateRoleInfo(roleId, { roleName: newName, sdkMark: false });
        // 通知处理
        await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'roleName', value: newName }]); // redis缓存
        if(role.isGuildLeader) {
            await updateUserInfo(REDIS_KEY.GUILD_INFO, role.guildCode, [{ field: 'leader', value: new GuildLeader(role) }]);
        }
        const { sid } = await getRoleOnlineInfo(roleId);
        if(!!sid) {
            await pinus.app.rpc.connector.connectorRemote.setOtherUserSession.toServer(sid,[{ roleId, roleName: newName }]); // 改session
            sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAYER_DATA_CHANGE, { roleName: newName }, sid);
        }
        // 补偿
        let gold = getGoldObject(NAMEPLATE.NAMEPLATE_FEECOST)
        await sendMailByContent(MAIL_TYPE.TREAT_ROLE_NAME, role.roleId, { goods: [gold] });
    }
}

// 根据37sdk处理违规军团数据
export async function treatGuildName(content: string) {
    let params: { code: string, serverId: number, type: number };
    try {
        params = JSON.parse(content);
    } catch(e) {
        return false;
    }

    let guild = await GuildModel.findByCode(params.code, params.serverId, '+members');
    if(guild && guild.sdkMark) { // 有设置标记的情况下
        if(params.type == 1) { // 公会名
            let newName = "默认公会名";
            // 新名字上传
            await checkGuildName(params.code, params.serverId, newName, undefined);
            await GuildModel.updateInfo(params.code, { name: newName, sdkMark: false });
            // 通知处理
            await sendMailToGuildByContent(MAIL_TYPE.TREAT_GUILD_INFO, params.code, {}); // 邮件
            await pushGuildInfoUpdate(params.code, { name: newName });
            await updateUserInfo(REDIS_KEY.GUILD_INFO, params.code, [{ field: 'name', value: newName }]); // redis缓存信息
            for(let roleId of guild.members) {
                await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'guildName', value: newName }]);
            }
            await RoleModel.updateGuildName(params.code, newName);

        } else if (params.type == 2) { // 公会公告
            await checkGuildName(params.code, params.serverId, undefined, ' ');
            await GuildModel.updateInfo(params.code, { notice: ' ', sdkMark: false });
            // 通知处理
            await sendMailToGuildByContent(MAIL_TYPE.TREAT_GUILD_INFO, params.code, {}); // 邮件
            await pushGuildInfoUpdate(params.code, { notice: '' });
        }
    }
}

export function connectThinkingData(app: Application) {
    let ta;
    if(app.get('env') != 'development') {
        if(THINKING_DATA_MODE == THINKING_DATA_MODE_LIST.DEBUG) {
            ta = ThinkingAnalytics.initWithDebugMode(SDK_TA_CONST.APPID, SDK_TA_CONST.SERVER_URL);
        } else if (THINKING_DATA_MODE == THINKING_DATA_MODE_LIST.BATCH) {
            ta = ThinkingAnalytics.initWithBatchMode(SDK_TA_CONST.APPID, SDK_TA_CONST.SERVER_URL);
        } else if (THINKING_DATA_MODE == THINKING_DATA_MODE_LIST.LOGGING) {
            ta = initTaLoggingMode();
        }
        ta.setDynamicSuperProperties(() => {
            return {
                env: app.get('env'),
                sid: app.getServerId()
            };
          });
        app.set('ta', ta);
    }
}

export function reportTAEvent(roleId: string, eventName: string, properties: any, ip?: string, distinctId?: string) {
    let ta = pinus.app.get('ta');
    if(!ta) return
    let event = {
        // 账号 ID （可选)
        accountId: `${roleId}`,
        // 访客 ID （可选)，账号 ID 和访客 ID 不可以都为空
        distinctId: (distinctId && distinctId != 'weikaiqishushu')? `${distinctId}`:"",
        // 事件名称 （必填)
        event: eventName,
        // 事件时间 (可选) 如果不填，将以调用接口时的时间作为事件时间
        time: new Date(),
        // 事件 IP (可选) 当传入 IP 地址时，后台可以解析所在地
        ip: ip,
        // 事件属性 (可选)
        properties,
        callback(err) {
            console.log('*****测试接入事件', err)
        }

    };
    ta.track(event);
}

export function reportTAUserSet(type: TA_USERSET_TYPE, roleId: string, properties: any) {
    let ta = pinus.app.get('ta');
    if(!ta) return
    let userData = {
        // 账号 ID （可选)
        accountId: `${roleId}`,
        // 访客 ID （可选)，账号 ID 和访客 ID 不可以都为空
        distinctId: "",
        // 用户属性
        properties,
        // 出错时回调 (可选)
        callback(e) {
            if (e) {
                console.log(e);
            }
        }
    };
    if(type == TA_USERSET_TYPE.SET) {
        ta.userSet(userData);
    } else if (type == TA_USERSET_TYPE.SET_ONCE) {
        ta.userSetOnce(userData);
    } else if (type == TA_USERSET_TYPE.ADD) {
        ta.userAdd(userData);
    }
}

export async function reportCreateRoleEventToTa(role: RoleType, ip: string) {
    if(role.shushuMark) {
        reportTAEvent(role.roleId, TA_EVENT.CREATE_ROLE, null, ip, role.shushuMark);
        await RoleModel.updateRoleInfo(role.roleId, { shushuMark: '' });
    }
}

export function taflush() {
    let ta = pinus.app.get('ta');
    if(!ta) return;
    if(ta.flush) ta.flush();
    if(ta.close) ta.close();
}

export async function fetch37Words() {
    let params = new GetWordParam();
    let result = await request37GetWord(SDK_37_ADDR.GET_WORD, params, SDK_37_CONST.CHAT_KEY);

    writeWordTxt(FILENAME.FILTER_WORDS, result);
    return result;
}

export async function getTire() {
    console.log('**********getTire')
    let trie = pinus.app.get('tire');
    if(!trie) {
        let blockWords = readWordTxt(FILENAME.FILTER_WORDS);
        if(!blockWords) {
            blockWords = await fetch37Words();
        }
        trie = new Trie();
        let blockWordsArr = blockWords.split('\n');
        blockWordsArr.forEach(word => {
            let arr = word.split('||');
            trie.insertData(arr[0]);
        });
        pinus.app.set('tire', trie);
    }
    
    return trie
}

export async function _checkFilterWords(word: string) {
    let trie = await getTire();
    if (word.length > 30) return false;

    let cleanStr = word.trim().replace(/ /gi, '').replace('\n','').replace(/&/gi, '');
    let hitStr = trie.getHitStr(cleanStr);
    if (hitStr) {
        console.log(`命中屏蔽词: ${hitStr}`);
        return false;
    }
    return true;
}

export async function checkFilterWords(word: string) {
    if(pinus.app.getServerType() == 'chat') {
        return await _checkFilterWords(word);
    } else {
        let servers = pinus.app.getServersByType('chat');
        let server = getRandSingleEelm(servers);
        return await pinus.app.rpc.chat.chatRemote.checkFilterWords.toServer(server.id, word);
    }
}

export async function sendSurveyMail(code: string) {
    console.log('***** sendSurveyMail', code);
    let rec = await SurveyRecModel.findByCode(code);
    if(!rec || rec.hasSentMail) return false;
    console.log('***** sendSurveyMail hasSentMail', rec.hasSentMail);

    let survey = await SurveyModel.findBySurveyId(rec.surveyId);
    if(!survey) return false;
    console.log('***** sendSurveyMail survey', survey);

    await sendMailByContent(MAIL_TYPE.SEND_MAIL, rec.roleId, { goods: survey.reward, params: [survey.mailContent] });
    await sendMessageToUserWithSuc(rec.roleId, PUSH_ROUTE.DELETE_SURVEY, { code: survey.code });
    rec = await SurveyRecModel.send(rec.code);
}