import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
import { genCode } from '../pubUtils/util';
import { RoleModel } from './Role';

class Heroes {
    @prop({ required: true })
    seqId: number; // 唯一id
    @prop({ required: true })
    hp: number; // 血量
    @prop({ required: true })
    ap: number; // 怒气
    @prop({ required: true, default: 0 })
    shield: number; // 守护盾

}

/**
  * 远征记录
  */
@index({ roleId: 1, status: 1 })
@index({ expeditionCode: 1 })

export default class ExpeditionRecord extends BaseModel {
    @prop({ required: true, default: '' })
    roleId: string;					    // 角色 id
    @prop({ required: true, default: '' })
    roleName: string;					// 角色 名
    @prop({ required: true, default: '' })
    expeditionCode: string;				// 远征的唯一标识
    @prop({ required: true, default: 0 })
    myCe: number;					    // 我方在重置时的战力
    @prop({ required: true, type: Heroes, default: [], _id: false })
    heroes: Array<Heroes>;					// 我方已出场武将
    @prop({ required: true, default: 1 })
    status: number;					    // 状态 1-显示 0-不显示
    

    public static async getCurRecord(roleId: string, lean = true) {
        const result: ExpeditionRecordType = await ExpeditionRecordModel.findOne({ roleId, status: 1 }).lean(lean);
        return result;
    }

    public static async createRecord(params: { roleId: string, roleName: string, heroes: Array<{seqId: number, hp: number, ap: number, shield: number}>, myCe: number }, lean = true) {
        const code = genCode(8);
        
        const result: ExpeditionRecordType = await ExpeditionRecordModel.findOneAndUpdate({ expeditionCode: code }, {...params, status: 1}, { new: true, upsert: true }).lean(lean);
        await RoleModel.increaseExpeditionCnt(params.roleId, 1);
        return result;
    }

    public static async hideRecord(roleId: string, lean = true) {
        const result: ExpeditionRecordType = await ExpeditionRecordModel.findOneAndUpdate({ roleId, status: 1 }, { status: 0 }, { new: true }).lean(lean);
        return result;
    }

    public static async getExpeditionRecordByCode(expeditionCode: string, lean=true) {
        const result: ExpeditionRecordType = await ExpeditionRecordModel.findOne({expeditionCode}).lean(lean);
        return result 
    }

    public static async updateHeroStatus(expeditionCode: string, oldHeroes: Array<Heroes>, heroes: Array<{dataId: number, hp: number, ap: number, shield: number}>, lean=true) {
        let pushArr = new Array(), updateArr = new Array();
        for(let hero of heroes) {
            let {dataId, hp, ap, shield = 0} = hero;
            let obj = oldHeroes.find(cur => cur.seqId == dataId);

            if(!!obj) {
                updateArr.push({seqId: dataId, hp, ap, shield});
            } else {
                pushArr.push({seqId: dataId, hp, ap, shield})
            }
        }
        for(let {seqId, hp, ap, shield} of updateArr) {
            await ExpeditionRecordModel.findOneAndUpdate(
                {expeditionCode, 'heroes.seqId': seqId },
                {$set: {'heroes.$.seqId': seqId, 'heroes.$.hp': hp, 'heroes.$.ap': ap, 'heroes.$.shield': shield}}
            )
        }
        const result: ExpeditionRecordType = await ExpeditionRecordModel.findOneAndUpdate(
            { expeditionCode },
            { $push: {heroes: {$each: pushArr} } }
        ).lean(lean)

        return result;
    }

    public static async deleteAccount(roleId: string) {
        let result = await ExpeditionRecordModel.deleteMany({roleId});
        return result;
      }
}

export const ExpeditionRecordModel = getModelForClass(ExpeditionRecord);

export interface ExpeditionRecordType extends Pick<DocumentType<ExpeditionRecord>, keyof ExpeditionRecord>{};