// 和gvg组建期相关的方法

import { pinus } from "pinus";
import { GUILD_AUTH, GVG_APPLY_TYPE, GVG_PERIOD, GVG_SERVER_TYPE, LEAGUE_AUTH, LEAGUE_MANAGE_TYPE, PUSH_ROUTE, REDIS_KEY, STATUS } from "../../consts";
import { GuildModel, GuildType } from "../../db/Guild";
import { GVGCityModel } from "../../db/GVGCity";
import { GVGCityAreaPointModel } from "../../db/GVGCityAreaPoint";
import { GVGLeagueModel, GVGLeagueType, GVGLeagueUpdate } from "../../db/GVGLeague";
import { GVGLeagueApplyModel, GVGLeagueApplyType } from "../../db/GVGLeagueApply";
import { GVGLeaguePrepareModel, GVGLeaguePrepareType } from "../../db/GVGLeaguePrepare";
import { GVGTeamModel } from "../../db/GVGTeam";
import { RoleType } from "../../db/Role";
import { UserGuildModel } from "../../db/UserGuild";
import { LeagueGuildInfo, LeagueListInfo } from "../../domain/gvgField/returnData";
import { LeagueLeader } from "../../domain/rank";
import { GVG } from "../../pubUtils/dicParam";
import { getZeroPointD } from "../../pubUtils/timeUtil";
import { resResult } from "../../pubUtils/util";
import { sendMessageToUserWithSuc } from "../pushService";
import { updateUserInfo } from "../redisService";
import { getGVGBattleData } from "./gvgBattleMemory";
import { guildJoinLeagueRecord } from "./gvgRecService";
import { calLeagueCe, getCurPeriod, getGroupKey, getGVGConfig, getGVGPeriodData, getGVGServerType } from "./gvgService";

/**
 * 自动创建联军
 * @param guildCode 创建联军的那个军团
 * @returns GVGLeagueType
 */
export async function autoCreateLeague(guildCode: string) {
    let guild = await GuildModel.findByCode(guildCode, null, '+members +serverId');
    if(!guild || guild.lv < GVG.GVG_ARMY_LEAGUE_TIME) return;

    let { configId, period } = getGVGPeriodData();
    if(period == GVG_PERIOD.PREPARE) {
        let league = await createLeague(guild, {});
        let groupKey = await getGroupKey(guild.serverId);
        await GVGLeaguePrepareModel.initData(configId, groupKey, league.leagueCode, guild.memberCnt);
        return league;
    }
}

/**
 * 创建联军
 * @param guild 创建联军的那个军团
 * @param params 联军的一些初始数据
 * @returns 
 */
export async function createLeague(guild: GuildType, params: GVGLeagueUpdate) {
    let serverType = await getGVGServerType(guild.serverId);
    params.type = serverType;
    params.serverId = guild.serverId; 
    const league = await GVGLeagueModel.createLeague(guild, params);
    await GuildModel.joinLeague(guild.code, league.leagueCode);
    return league;
}

/**
 * 获取在联军中的职位
 * @param league 
 * @param roleId 
 * @returns 
 */
export function getMyAuth(league: GVGLeagueType, roleId: string) {
    let members = league.members;
    let member = members.find(cur => cur.roleId == roleId);
    return member?.auth?? LEAGUE_AUTH.MEMBER;
}

/**
 * 加入联军的当天如果是在准备期，这天不能去参加内政
 * @param roleId 
 * @returns 
 */
export async function checkCanPrepare(roleId: string) {
    let userGuild = await UserGuildModel.getMyGuild(roleId, 'createdAt');
    let today = getZeroPointD();
    return userGuild.createdAt < today;
}

/**
 * 是否可以选择职能，如果选择的人数超过了就不可以选
 * @param myJob 
 * @param league 
 * @returns 
 */
export function checkCanChooseJob(myJob: number, league: GVGLeaguePrepareType) {
    if(myJob > 0) return false;
    if(!league) return false;
    let { producerCnt, fighterCnt, maxMemberCnt } = league;
    return producerCnt + fighterCnt <= maxMemberCnt;
}

/**
 * 获取申请数据
 * @param apply 本条申请原数据
 * @param serverNames 全服务器的名字from redis
 * @param invitations 本联军向其他军团发出的邀请
 * @returns 
 */
export function getLeagueApplyData(apply: GVGLeagueApplyType, serverNames: any, invitations: GVGLeagueApplyType[] ) {
    let data = new LeagueGuildInfo(<GuildType>apply.guild, serverNames);
    let hasInvited = !!invitations.find(cur => cur.guildCode == apply.guildCode);
    data.setHasInvited(hasInvited);
    return data;
}

/**
 * 获取邀请数据
 * @param invite 本条邀请原数据
 * @param serverNames 全服务器的名字from redis
 * @param applies 本军团向其他联军发出的申请
 * @returns 
 */
export async function getLeagueInviteData(invite: GVGLeagueApplyType, serverNames: any, applies: GVGLeagueApplyType[]) {
    let data = new LeagueListInfo(<GVGLeagueType>invite.league, serverNames);
    let hasApply = !!applies.find(cur => cur.leagueCode == invite.guildCode);
    data.setHasApply(hasApply);
    data.setLeagueCe(await calLeagueCe(<GVGLeagueType>invite.league))
    return data;
}

/**
 * 联军加入军团
 * @param myLeague 
 * @param targetGuildCode 
 * @returns 
 */
export async function joinGuildToLeague(league: GVGLeagueType, targetGuildCode: string) {
    const hasApply = await GVGLeagueApplyModel.checkApply(league.leagueCode, targetGuildCode, GVG_APPLY_TYPE.ALL);
    if(!hasApply) {
        return resResult(STATUS.GUILD_NOT_APPLY);
    }
    if(league.guildCnt >= GVG.GVG_LEAGUE_COMPOSE) {
        return resResult(STATUS.LEAGUE_IS_GUILD_MAX);
    }
    let hisLeague = await GVGLeagueModel.findLeagueByGuild(targetGuildCode);
    if(hisLeague) {
        await GVGLeagueApplyModel.deleteApply(targetGuildCode, league.leagueCode);
        return resResult(STATUS.TARGET_GUILD_HAS_LEAGUE);
    }

    const targetGuild = await GuildModel.findByCode(targetGuildCode, null, '+members');
    if(!targetGuild) return resResult(STATUS.TARGET_GUILD_NOT_FOUND);
    if(targetGuild.lv < GVG.GVG_ARMY_LEAGUE_TIME) return resResult(STATUS.GUILD_LV_NOT_ENOUGH);

    league = await GVGLeagueModel.joinGuild(league.leagueCode, targetGuild);

    await GuildModel.joinLeague(targetGuildCode, league.leagueCode);
    guildJoinLeagueRecord(league.leagueCode, targetGuild.name);

    return resResult(STATUS.SUCCESS, league);
}

/**
 * 检查是否可以进行组建联军等操作
 * @param serverId 
 * @param serverType 
 * @returns 
 */
export async function checkCanManage(serverId: number, serverType?: number) {
    if(!serverType) serverType = await getGVGServerType(serverId);
    if(serverType != GVG_SERVER_TYPE.MULTI) return resResult(STATUS.GVG_TEAM_SERVER_TYPE_ERR);
    let { period } = getGVGPeriodData();
    if(period != GVG_PERIOD.TEAM) return resResult(STATUS.GVG_NOT_TEAM_PERIOD);
    return resResult(STATUS.SUCCESS);
}

/**
 * 一些操作只能由军团的团长才能操作
 * @param guildCode 
 * @param roleId 
 * @param guild 
 * @returns 
 */
export async function checkGuildLeader(guildCode: string, roleId: string, guild?: GuildType) {
    if(!guild) guild = await GuildModel.findByCode(guildCode, null, '+members +serverId');
    if(!guild) return resResult(STATUS.GVG_HAS_NO_AUTH);
    if(guild.lv < GVG.GVG_ARMY_LEAGUE_TIME) return resResult(STATUS.GUILD_LV_NOT_ENOUGH);

    const userGuild = await UserGuildModel.getMyGuild(roleId, 'auth');
    if(!userGuild || userGuild.auth != GUILD_AUTH.LEADER) return resResult(STATUS.GVG_HAS_NO_AUTH);
    return resResult(STATUS.SUCCESS);
}

/**
 * 检查联军的操作
 * @param roleId 
 * @param myLeague 
 * @param type 
 * @returns 
 */
export async function checkLeagueAuth(roleId: string, myLeague: GVGLeagueType, type: LEAGUE_MANAGE_TYPE) {
    const auth = getMyAuth(myLeague, roleId);
    const needAuth = getAuthFromManageType(type);
    return needAuth.indexOf(auth) > -1 
}

function getAuthFromManageType(type: LEAGUE_MANAGE_TYPE) {
    switch(type) {
        case LEAGUE_MANAGE_TYPE.HANDLE_APPLY:
        case LEAGUE_MANAGE_TYPE.INVITE:
        case LEAGUE_MANAGE_TYPE.KICK:
        case LEAGUE_MANAGE_TYPE.DISSMISS:
        case LEAGUE_MANAGE_TYPE.ABDICATE:
        case LEAGUE_MANAGE_TYPE.RERUIT:
            return [LEAGUE_AUTH.LEADER];
        case LEAGUE_MANAGE_TYPE.QUIT:
        case LEAGUE_MANAGE_TYPE.BE_ABDICATED:
            return [LEAGUE_AUTH.SUB_LEADER];
        case LEAGUE_MANAGE_TYPE.SET_INFO:
        case LEAGUE_MANAGE_TYPE.SEND_MAIL:
        case LEAGUE_MANAGE_TYPE.UNLOCK_TECH:
            return [LEAGUE_AUTH.LEADER, LEAGUE_AUTH.SUB_LEADER];
        case LEAGUE_MANAGE_TYPE.ACTIVATE_TECH:
            return [LEAGUE_AUTH.LEADER, LEAGUE_AUTH.SUB_LEADER, LEAGUE_AUTH.MEMBER];
    }
}

export async function memberJoinGuildToLeague(guild: GuildType, role: RoleType) {
    if(!guild.leagueCode) return;
    await GVGLeagueModel.joinMember(guild.leagueCode, role.roleId, guild.code);
}

export async function memberQuitGuildToLeague(guild: GuildType, role: RoleType) {
    if(!guild.leagueCode) return;
    await GVGLeagueModel.quitMember(guild.leagueCode, role.roleId);
}

export async function guildDismissToLeague(guild: GuildType) {
    if(!guild.leagueCode) return;
    await GVGLeagueModel.quitGuild(guild.leagueCode, guild);
}

export async function guildAbdicateToLeague(guild: GuildType, fromRoleId: string, toRole: RoleType) {
    if(!guild.leagueCode) return;
    await GVGLeagueModel.abdicateGuild(guild.leagueCode, fromRoleId, toRole.roleId, toRole._id);
    await updateUserInfo(REDIS_KEY.LEAGUE_INFO, guild.leagueCode, [{ field: 'leader', value: new LeagueLeader(toRole) }]);
}

export async function updateGVGBattleLeagueInfo(serverId: number, leagueCode: string, info: { leagueName?: string, icon?: number }) {
    await GVGTeamModel.updateLeagueName(leagueCode, info.leagueName);
    await GVGCityModel.updateLeagueInfo(leagueCode, info.leagueName, info.icon);
    await GVGCityAreaPointModel.updateLeagueName(leagueCode, info.leagueName)
    if(info.leagueName) await pinus.app.rpc.guild.guildRemote.updateLeagueNameMem.broadcast(serverId, leagueCode, info.leagueName);
}

export async function updateLeagueNameMem(serverId: number, leagueCode: string, leagueName: string ) {
    let groupKey = await getGroupKey(serverId);
    let teamObj = getGVGBattleData(groupKey);
    teamObj.updateLeagueInfo(leagueCode, leagueName);
}

export async function updateGVGBattleRoleInfo(serverId: number, roleId: string, info: { roleName?: string, lv?: number }) {
    await GVGTeamModel.updateRoleInfo(roleId, info);
    await pinus.app.rpc.guild.guildRemote.updateTeamRoleInfoMem.broadcast(serverId, roleId, info);
}

export async function updateTeamRoleInfoMem(serverId: number, roleId: string, info: { roleName?: string, lv?: number } ) {
    let groupKey = await getGroupKey(serverId);
    let teamObj = getGVGBattleData(groupKey);
    teamObj.updateRoleInfo(roleId, info);
}