import { Application, ChannelService, HandlerService, } from 'pinus';
import { resResult } from '../../../pubUtils/util';
import { STATUS, CHANNEL_PREFIX } from '../../../consts';
import { GuildType } from '../../../db/Guild';
import { RoleType } from '../../../db/Role';
import { GuildRecType } from '../../../db/GuildRec';
import { leaveGuildChannel, groupRoomId } from '../../../services/chatService';
import { GuildRankParams, WoodenHorse, Event } from '../../../domain/battleField/guildActivity';
import { MailParam } from '../../../domain/roleField/mail';
import { pick } from 'underscore';

export default function (app: Application) {
    new HandlerService(app, {});
    return new GuildRemote(app);
}

export class GuildRemote {

    constructor(private app: Application) {
        this.app = app;
        this.channelService = app.get('channelService');
    }

    private channelService: ChannelService;
    private MEMBER_QUIT = 'onMemberQuit';
    private DISMISS = 'onDismiss';
    private GUILD_INFO_UPDATE = 'onGuildInfoUpdate';
    private DEMOTION = 'onDemotion';
    private PROMOTION = 'onPromotion';
    private GUILD_REC_ADD = 'onGuildRecAdd';
    private GUILD_BOSS_OPEN = 'onGuildBossStatus';
    private GATE_ACT_RANK = 'onGuildGateRankUpdate';    // 军团活动排行榜
    private CITY_ACT_RANK = 'onGuildCityRankUpdate';    // 军团活动排行榜
    private GUILD_GATE_ACT_HP = 'onGuildGateHpUpdate';   // 军团活动蛮夷入侵排行榜
    private GUILD_ACTIVITY_END = 'onGuildActivityEnd';    // 军团活动结束
    private GUILD_CITY_DECLARE = 'onGuildCityDeclare';    // 有军团对这个城池进行宣战了
    private GUILD_CITY_ACT_HP = 'onGuildCityGateHpUpdate'; // 诸侯入侵城门血条
    private GUILD_RACE_UPDATE = 'onRaceHorseUpdate';   /// 更新木牛流马
    private GUILD_RACE_EVENT = 'onRaceEventUpdate';   /// 更新木牛流马
    private GUILD_POP_UP_ACTIVITY = 'onActivityUpdate';   /// 向军团成员发送弹窗礼包
    private GUILD_TRAIN_RESET = 'onGuildTainReset'; // 试炼场重置
    private GUILD_BOSS_ENCOURAGE = 'onGuildBossEncourage'; // 鼓舞

    /**
     * 封装，军团相关channel名: 'guild'+guildCode
     * @param guildCode 军团code
     * @param create 是否创建channel 
     */
    private getChannel(guildCode: string, create: boolean = false) {
        let channelName = groupRoomId(CHANNEL_PREFIX.GUILD, guildCode);
        let channel = this.channelService.getChannel(channelName, create);
        return channel
    }

    /**
     * 封装，向单人发推送
     * @param guildCode 军团code
     * @param path 推送地址
     * @param roleId 玩家id
     * @param message 推送信息
     * @param sid 玩家服
     */
    private pushMessageByUids(guildCode: string, path: string, roleId: string, message: { code: string, roleId?: string }, sid?: string) {

        let channel = this.getChannel(guildCode);
        let uids = [];
        if (!sid) {
            sid = channel && channel.getMember(roleId)['sid'];
        }
        if (sid) {
            uids.push({ uid: roleId, sid });
            this.channelService.pushMessageByUids(path, resResult(STATUS.SUCCESS, message), uids);
        }
        return channel
    }

    /**
     * 封装，向channel发推送
     * @param guildCode 军团code
     * @param path 推送地址
     * @param message 推送信息
     */
    private pushMessage(guildCode: string, path: string, message: any) {
        let channel = this.getChannel(guildCode);
        if (!!channel) {
            channel.pushMessage(path, resResult(STATUS.SUCCESS, message));
        }
        return channel
    }

    /**
     * 诸侯混战，按城池区分channel
     * @param cityId 城池id
     * @param create 是否创建channel 
     */
    private getCityChannel(cityId: number, create: boolean = false) {
        let channelName = groupRoomId(CHANNEL_PREFIX.CITY, cityId);
        let channel = this.channelService.getChannel(channelName, create);
        return channel
    }

    /**
     * 封装，向channel发推送
     * @param cityId 城池id
     * @param path 推送地址
     * @param message 推送信息
     */
    private pushMessageToCity(cityId: number, path: string, message: any) {
        let channel = this.getCityChannel(cityId);
        if (!!channel) {
            channel.pushMessage(path, resResult(STATUS.SUCCESS, message));
        }
        return channel
    }

    /**
     * 踢出某个成员
     * @param guildCode 军团code
     * @param roleId 踢出玩家roleId
     * @param guild 军团信息
     * @param sid 玩家sid
     */
    public memberQuit(guildCode: string, roleId: string, guild: GuildType, sid?: string) {
        // 被踢出公会
        this.pushMessageByUids(guildCode, this.MEMBER_QUIT, roleId, {
            code: guildCode,
            roleId
        }, sid);
        // 更新人数减少
        this.updateInfo(guildCode, { memberCnt: guild.memberCnt, guildCe: guild.guildCe });
        leaveGuildChannel(roleId, sid, guildCode);
    }

    /**
     * 解散军团
     * @param guildCode 军团code
     */
    public dismiss(guildCode: string) {
        let channel = this.pushMessage(guildCode, this.DISMISS, { code: guildCode });
        if (!!channel) {
            channel.destroy();
        }
    }

    /**
     * 更新军团信息
     * @param guildCode 军团code
     * @param info 军团相关信息
     */
    public updateInfo(guildCode: string, info: any) {
        this.pushMessage(guildCode, this.GUILD_INFO_UPDATE, info);
    }

    /**
     * 更换团长信息
     * @param guildCode 军团code
     * @param managerCnt 管理员人数
     * @param newLeader 新的团长
     * @param oldLeaderId 旧团长
     */
    public changeLeader(guildCode: string, managerCnt: number, newLeader: RoleType, oldLeaderId: string) {
        let { roleId, roleName, frame, head, spine, lv, quitTime } = newLeader;
        this.updateInfo(guildCode, { managerCnt, leader: { roleId, roleName, frame, head, spine, lv, quitTime } });
        this.demotion(guildCode, oldLeaderId);
        this.promotion(guildCode, roleId);
    }

    /**
     * 向旧团长推送降职信息
     * @param guildCode 军团code
     * @param roleId 旧团长id
     */
    public demotion(guildCode: string, roleId: string) {
        this.pushMessageByUids(guildCode, this.DEMOTION, roleId, {
            code: guildCode
        });
    }

    /**
     * 向新团长推送升职信息
     * @param guildCode 军团code
     * @param roleId 新团长id
     */
    public promotion(guildCode: string, roleId: string) {
        this.pushMessageByUids(guildCode, this.PROMOTION, roleId, {
            code: guildCode
        });
    }

    /**
     * 添加动态
     * @param guildRecType 动态
     */
    public addRec(guildRecType: GuildRecType) {
        let { guildCode, type, params, createTime } = guildRecType;
        this.pushMessage(guildCode, this.GUILD_REC_ADD, { type, params, createTime });
    }

    /**
     * 向军团推送城门血量
     * @param guildCode 
     */
    public pushGateHp(guildCode: string, gateHp: number) {
        this.pushMessage(guildCode, this.GUILD_GATE_ACT_HP, { gateHp });
    }

    /**
     * 向军团推送排行榜名次
     * @param guildCode 
     */
    public pushRank(guildCode: string, msg: GuildRankParams) {
        this.pushMessage(guildCode, this.GATE_ACT_RANK, msg);
    }

    /**
     * 向军团推送排行榜名次
     * @param guildCode 
     */
    public pushCityActRank(guildCode: string, msg: GuildRankParams) {
        this.pushMessage(guildCode, this.CITY_ACT_RANK, msg);
    }

    /**
     * @description 向军团推送结束活动
     * @param guildCode 
     */
    public async sendGuildActivityEnd(guildCode: string) {
        console.log("MSG END")
        this.pushMessage(guildCode, this.GUILD_ACTIVITY_END, {});
    }

    /**
     * @description 向城池推送有宣战
     * @param cityId 城池
     * @param declareGuildCode 宣战的军团code
     * @param declareCount 宣战数量
     */
    public async sendGuildCityDeclare(cityId: number, declareGuildCode: string, declareCount: number) {
        this.pushMessageToCity(cityId, this.GUILD_CITY_DECLARE, {
            cityId,
            declareGuildCode,
            declareCount
        });
    }

    /**
     * @description 推送城池城门血条
     * @param cityId 城池
     * @param gateHp 血条 
     */
    public async pushCityGateHp(cityId: number, gateHp: number) {
        this.pushMessageToCity(cityId, this.GUILD_CITY_ACT_HP, {
            cityId,
            gateHp
        });
    }

    /**
     * @description 推送木牛流马状态
     * @param guildCode 军团
     * @param woodenHorseList 木马
     * @param ranks 军团排名和自己所在的排名
     */
    public async pushRaceHorseUpdate(guildCode: string, woodenHorseList: WoodenHorse[], ranks: GuildRankParams, events: Event[]) {
        this.pushMessage(guildCode, this.GUILD_RACE_UPDATE, {
            timestamp: Date.now(),
            woodenHorseList,
            ...ranks,
            events
        });
    }

    /**
     * @description 向军团推送事件
     * @param guildCode 
     */
    public async sendRaceEvent(guildCode: string, events: Event[]) {
        this.pushMessage(guildCode, this.GUILD_RACE_EVENT, { timestamp: Date.now(), events });
    }

    /**
     * @description 当团长开启演武台时
     * @param guildCode 
     * @param warId 
     * @param bossHp 
     * @param status 
     */
    public async pushBossStatus(guildCode: string, result: any) {
        this.pushMessage(guildCode, this.GUILD_BOSS_OPEN, pick(result, ['status', 'bossInfo', 'leaderOpenCnt']));
    }

    /**
     * @description 向军团推送弹窗礼包数据活动
     * @param guildCode 
     */
    public async sendPopUpActivity(guildCode: string, data: any[]) {
        console.log("sendPopUpActivity")
        this.pushMessage(guildCode, this.GUILD_POP_UP_ACTIVITY, data);
    }

    /**
     * @description 军团邮件
     * @param guildCode 军团code
     * @param path 推送地址
     * @param data 军团内容
     */
    public async sendMailToGuild(guildCode: string, path: string, data: { mails: MailParam[] }) {
        this.pushMessage(guildCode, path, data);
    }

    public async sendTrainReset(guildCode: string) {
        this.pushMessage(guildCode, this.GUILD_TRAIN_RESET, {});
    }

    public async pushEncourage(guildCode: string, param: {encourageCnt: number; encourageMax: number; myEncourageCnt: number;}) {
        this.pushMessage(guildCode, this.GUILD_BOSS_ENCOURAGE, param);
    }
}