import { GVGRecModel } from './../../../../../shared/db/GVGRec';
import { LeagueGood } from './../../../../../shared/domain/gvgField/returnData';
import { GVGTeamModel } from './../../../../../shared/db/GVGTeam';
import { GVGUserDataModel } from './../../../../../shared/db/GVGUserData';
import { GVGCityModel } from './../../../../../shared/db/GVGCity';
import { Application, BackendSession, ChannelService, HandlerService } from "pinus";
import { STATUS } from "../../../consts";
import { LineupHero } from "../../../domain/roleField/hero";
import { resResult } from "../../../pubUtils/util";

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

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

    // 保存队伍
    // index: 队伍索引位置
    // head: 头像
    // frame: 相框
    // spine: 形象
    // lineup: 阵容
    async saveTeam(msg: { index: number, head: number, frame: number, spine: number, lineup: [ LineupHero ] }, session: BackendSession) {
        return resResult(STATUS.SUCCESS, { teams: [ 'teamCode' ] });
    }

    // 获取城池信息
    async getCity(msg: { cityId: number }, session: BackendSession) {
        const { cityId } = msg;

        const city = await GVGCityModel.findOne({ cityId }).lean();
        return resResult(STATUS.SUCCESS, { city });
    }

    // 进入城池
    async enterCity(msg: { cityId: number }, session: BackendSession) {
        const { cityId } = msg;

        let valid = false;
        if (!valid) {
            return resResult(STATUS.GVG_BATTLE_CITY_FULL);
        }

        const city = await GVGCityModel.findOne({ cityId }).lean();
        return resResult(STATUS.SUCCESS, { city });
    }

    // 离开城池
    async leaveCity(msg: { cityId: number }, session: BackendSession) {
        return resResult(STATUS.SUCCESS);
    }

    // 开始移动
    // areaId: 要移动的目标据点 id
    async startMove(msg: { cityId: number, areaId: number, teamCode: string }, session: BackendSession) {
        const { areaId, cityId } = msg;
        const moveTime = Date.now();

        return resResult(STATUS.SUCCESS, { areaId, cityId, moveTime });
    }

    // 停止移动
    // areaId: 移动到的目标据点 id
    async stopMove(msg: { cityId: number, areaId: number, teamCode: string }, session: BackendSession) {
        const { areaId, cityId, teamCode } = msg;
        const players = await GVGUserDataModel.find({ cityId, areaId }).limit(20).lean();
        const curTeam = await GVGTeamModel.findOneAndUpdate({ teamCode }, { areaId }).lean();
        return resResult(STATUS.SUCCESS, { areaId, cityId, players, curTeam });
    }

    // 队伍入驻积分点
    async teamSettle(msg:  { cityId: number, areaId: number, pointId: number, teamCode: string }, session: BackendSession) {
        const { pointId, teamCode } = msg;
        const curTeam = await GVGTeamModel.findOneAndUpdate({ teamCode }, { pointId }).lean();
        return resResult(STATUS.SUCCESS, { curTeam });
    }

    // 队伍离开积分点
    async teamLeave(msg: any, session: BackendSession) {
    }

    // 队伍开始攻击
    // teamCode: 攻击方队伍
    // oppoTeamCode: 防守方队伍
    async battleStart(msg: { teamCode: string, oppoTeamCode: string }, session: BackendSession) {
        const { teamCode, oppoTeamCode } = msg;
        const teams = await GVGTeamModel.find({ teamCode: { $in: [ teamCode, oppoTeamCode ] } }).lean();
        let teamInvalid = false;
        let invalidTeamCode = '';
        teams.forEach(team => {
            if (team.attackTime > Date.now() - 1000 * 5) {
                teamInvalid = true;
                invalidTeamCode = team.teamCode;
            }
        });
        if (teamInvalid) {
            return resResult(STATUS.GVG_BATTLE_TEAM_INVALID, { teamCode: invalidTeamCode });
        }
        return resResult(STATUS.SUCCESS);
    }

    // 队伍停止攻击
    async battleEnd(msg: { battleCode: string, isSuccess: boolean }, session: BackendSession) {
        const { battleCode, isSuccess } = msg;
        // ! 根据 battleCode 获取 teamCode
        const teamCode = '';
        const leagueGoods: LeagueGood[] = null;
        // ! 计算并更新两支队伍耐久
        const curTeam = await GVGTeamModel.findOneAndUpdate({ teamCode }, {}).lean();
        // ! 推送战斗结果给对手队伍
        // const channel = this.channelService.getChannel(teamCode, false);
        // if (!!channel) {
        //     channel.pushMessage('onBattleResult', { isSuccess });
        // }
        // ! 结算奖励
        if (isSuccess) {
            // ! 更新 leagueGoods
        }
        return resResult(STATUS.SUCCESS, { curTeam, leagueGoods });
    }

    // 使用道具
    // teamCode: 要使用道具的队伍
    async useItem(msg: { itemId: number, teamCode: string }, session: BackendSession) {
        const { itemId, teamCode } = msg;
        // ! 检查道具是否存在
        // ! 检查道具是否可以使用在该队伍
        const team = await GVGTeamModel.findOneAndUpdate({ teamCode }, {}).lean();
        // ! 根据 item 使用效果更新 team
        return resResult(STATUS.SUCCESS, { team });
    }

    // 复活队伍
    async reviveTeam(msg: { teamCode: string }, session: BackendSession) {
        const { teamCode } = msg;
        // ! 检查该队伍是否可以复活，可以的话更新队伍状态
        const team = await GVGTeamModel.findOneAndUpdate({ teamCode }, {}).lean();
        // 更新成功返回队伍信息
        return resResult(STATUS.SUCCESS, { team });
    }

    // 获取战报
    // type: 战报类型
    async getRecs(msg: { type: number }, session: BackendSession) {
        const { type } = msg;
        // 根据 type 获取战报
        const recs = await GVGRecModel.find({ type }).limit(20).lean();
        return resResult(STATUS.SUCCESS, { recs });
    }

    // 获取概况
    async getOverview(msg: {}, session: BackendSession) {
        const cities = await GVGCityModel.find({}).lean();
        // ! 重新组织每个城市的数据，添加据点和积分点的信息
        return resResult(STATUS.SUCCESS, { cities });
    }

    // 获取区域上的队伍
    async getAreaTeams(msg: { cityId: number, areaIds: [number] }, session: BackendSession) {
        const { cityId, areaIds } = msg;
        const queryParam = {};
        areaIds.forEach(areaId => {
            queryParam[areaId] = [{ $match: { areaId, cityId } }, { $limit: 20 }];
        });
        const teams = await GVGTeamModel.aggregate([
            { $facet: queryParam },
        ]);
        return resResult(STATUS.SUCCESS, { teams });
    }
}
