import { mongoose, prop, Ref } from "@typegoose/typegoose";
import { LADDER_STATUS } from "../../consts";
import { ArtifactModelType } from "../../db/Artifact";
import Hero, { HeroType, Talent } from '../../db/Hero';
import { LadderMatchType } from "../../db/LadderMatch";
import { LadderMatchRecType } from "../../db/LadderMatchRec";
import { RoleType } from "../../db/Role";
import { gameData } from "../../pubUtils/data";
import { EXTERIOR, LADDER } from "../../pubUtils/dicParam";
import { DicLadderDifficultRatio } from "../../pubUtils/dictionary/DicLadderDifficultRatio";
import { DicWarJson } from "../../pubUtils/dictionary/DicWarJson";
import { RoleRankInfo } from "../rank";

// ladderMatch表
export class LadderDefenseHero {
    @prop({ required: true })
    actorId: number;        // 武将id
    @prop({ required: true })
    ai: number;              // ai逻辑，1-进攻型 2-防守型
    @prop({ required: true })
    dataId: number;
    @prop({ required: true })
    order: number;
    @prop({ ref: 'Hero', type: mongoose.Schema.Types.ObjectId })
    hero: Ref<Hero>;
    @prop({ required: true })
    ce: number;

    constructor(param: { actorId: number, ai: number, dataId: number, order: number }, heroId: string, ce: number) {
        this.actorId = param.actorId;
        this.ai = param.ai;
        this.dataId = param.dataId;
        this.order = param.order;
        this.hero = heroId;
        this.ce = ce;
    }
}

// ladderMatch表
export class LadderDefense {
    
    @prop({ required: true })
    warId: number;
    @prop({ required: true, type: LadderDefenseHero, _id: false })
    heroes: LadderDefenseHero[];
    
    constructor(heroes: LadderDefenseHero[], warId: number) {
        this.heroes = heroes;
        this.warId = warId;
    }
}


// LadderMatch表
export class LadderOppPlayerInDB {
    @prop({ required: true })
    rank: number;
}


class HeroArtifact {
    @prop({ required: true })
    artifactId: number;
    
    @prop({ required: true })
    lv: number;
}

// ladderMatchRec
export class LadderOppPlayerHeroInfo {
    @prop({ required: true })
    hid: number;					// 武将id
    @prop({ required: true })
    skinId: number;					// 皮肤id
    @prop({ required: true })
    quality: number;					// 品质
    @prop({ required: true })
    star: number;					// 星级
    @prop({ required: true })
    colorStar: number;			 // 彩星
    @prop({ required: true })
    lv: number;					// 等级
    @prop({ required: true, type: HeroArtifact, _id: false })
    artifact: HeroArtifact[] = [];					// 等级

    setByWarJson(warJson: DicWarJson) {
        this.hid = warJson.actorId;
        this.skinId = warJson.actorId;
        this.lv = warJson.lv;
        let dicHero = gameData.hero.get(warJson.actorId);
        if(dicHero) {
            this.quality = dicHero.quality;
            if(this.quality == 4) {
                this.star = 6;
                this.colorStar = warJson.star;
            } else {
                this.star = warJson.star;
                this.colorStar = 0;
            }
        }
    }

    setByDefenseHero(hero: HeroType) {
        this.hid = hero.hid;
        this.skinId = hero.skinId;
        this.quality = hero.quality;
        this.star = hero.star;
        this.colorStar = hero.colorStar;
        this.lv = hero.lv;
    }

    setArtifact(artifact: ArtifactModelType) {
        if(artifact) this.artifact.push({ artifactId: artifact.artifactId, lv: artifact.lv });
    }
}

// ladderMatchRec
export class LadderOppPlayerInfo {
    @prop({ required: true })
    oldRank: number = 0;					// 原排名
    @prop({ required: true })
    newRank: number = 0;					// 交换后的排名   
    @prop({ required: true })
    roleId: string = '';					// 角色 id
    @prop({ required: true })
    roleName: string = LADDER.LADDER_ROBOT_NAME; // 角色 名
    @prop({ required: true, default: 0 })
    lv: number = 1;               // 等级
    @prop({ required: true, default: EXTERIOR.EXTERIOR_FACE })
    head: number = EXTERIOR.EXTERIOR_FACE;          // 头像
    @prop({ required: true, default: EXTERIOR.EXTERIOR_FACECASE })
    frame: number = EXTERIOR.EXTERIOR_FACECASE;          // 相框
    @prop({ required: true, default: EXTERIOR.EXTERIOR_APPEARANCE })
    spine: number = EXTERIOR.EXTERIOR_APPEARANCE;             // 形象
    @prop({ required: true, default: 0 })
    title: number = 1;            // 爵位
    @prop({ required: true, default: 0 })
    ce: number = 0;               // 防守战力
    @prop({ required: true, default: false })
    isSuccess: boolean = false;			// 是否胜利
    @prop({ required: true, default: [], type: LadderOppPlayerHeroInfo, _id: false })
    heroes: LadderOppPlayerHeroInfo[] = [];			   	// 武将
    @prop({ required: true })
    isRobot: boolean = false;					// 原排名

    initByPlayer(rank: number, role: RoleType, heroes: LadderOppPlayerHeroInfo[], defCe: number, isSuccess: boolean ) {
        this.oldRank = rank;
        this.newRank = rank;
        this.roleId = role.roleId;
        this.roleName = role.roleName;
        this.head = role.head;
        this.frame = role.frame;
        this.spine = role.spine;
        this.title = role.title;
        this.ce = defCe;
        this.lv = role.lv;
        this.isSuccess = isSuccess;
        this.heroes = heroes;
        this.isRobot = false;
    }

    initByRobot(dicLadderDifficultRatio: DicLadderDifficultRatio, heroes: LadderOppPlayerHeroInfo[], isSuccess: boolean) {
        this.oldRank = dicLadderDifficultRatio.rank;
        this.newRank = dicLadderDifficultRatio.rank;
        this.roleId = `robot${this.oldRank}`;
        this.head = dicLadderDifficultRatio.head;
        this.spine = dicLadderDifficultRatio.spine;
        this.ce = dicLadderDifficultRatio.ce;
        this.lv = dicLadderDifficultRatio.level;
        this.isSuccess = isSuccess;
        this.heroes = heroes;
        this.isRobot = true;
    }

}

// defense字段 接口返回
export class LadderDefenseHeroReturn {
    actorId: number;        // 武将id
    ai: number;              // ai逻辑，1-进攻型 2-防守型
    dataId: number;
    order: number;

    constructor(defenseHero: LadderDefenseHero) {
        this.actorId = defenseHero.actorId;
        this.ai = defenseHero.ai;
        this.dataId = defenseHero.dataId;
        this.order = defenseHero.order;
    }
}

// defense字段 接口返回
export class LadderDefenseReturn {
    warId: number;
    defCe: number = 0;
    heroes: LadderDefenseHeroReturn[] = [];

    constructor(defense: LadderDefense) {
        if(!defense) return;
        this.warId = defense.warId;
        for(let defenseHero of defense.heroes) {
            this.defCe += defenseHero.ce;
            this.heroes.push(new LadderDefenseHeroReturn(defenseHero));
        }
    }
}

// oppPlayers字段接口返回
export class LadderOppPlayerReturn {
    rank: number = 0;           // 对手排名
    roleId: string = '';        // 对手玩家id            
    roleName: string = LADDER.LADDER_ROBOT_NAME;      // 对手玩家名            
    head: number = EXTERIOR.EXTERIOR_FACE;          // 头像            
    frame: number = EXTERIOR.EXTERIOR_FACECASE;         // 相框            
    spine: number = EXTERIOR.EXTERIOR_APPEARANCE;         // 形象            
    lv: number = 1;            // 对手玩家等级            
    title: number = 1;          // 对手爵位
    defCe: number = 0;         // 对手防守阵容战力
    isRobot: boolean = true;      // 是否是机器人  

    constructor(rank: number) {
        this.rank = rank;
    }

    setByRedis(param: RoleRankInfo, defCe: number) {
        this.isRobot = false;
        this.roleId = param.roleId;
        this.roleName = param.roleName;
        this.head = param.head;
        this.frame = param.frame;
        this.spine = param.spine;
        this.lv = param.lv;
        this.title = param.title;
        this.defCe = defCe;
    }

    setByRobot(ladderDifficultRatio: DicLadderDifficultRatio) {
        this.isRobot = true;
        this.roleId = `robot${this.rank}`;
        this.head = ladderDifficultRatio.head;
        this.spine = ladderDifficultRatio.spine;
        this.lv = ladderDifficultRatio.level;
        this.defCe = ladderDifficultRatio.ce;
    }
}

// getData总体返回
export class LadderDataReturn {
    rank: number = 0;
    historyRank: number = 0;
    challengeCnt: number = 0;
    buyCnt: number = 0;
    refOppCnt: number = 0;
    defense: LadderDefenseReturn = null;
    status: LADDER_STATUS = LADDER_STATUS.NO;
    time: number = 0;
    battleCode: string = '';
    oppPlayers: LadderOppPlayerReturn[] = []

    setLadderData(ladderData: LadderMatchType, ladderRec?: LadderMatchRecType) {
        this.rank = ladderData.rank;
        this.historyRank = ladderData.historyRank;
        this.challengeCnt = ladderData.challengeCnt;
        this.buyCnt = ladderData.buyCnt;
        this.refOppCnt = ladderData.refOppCnt;
        if(ladderData.defense) {
            this.defense = new LadderDefenseReturn(ladderData.defense);
        }
        if(ladderRec) {
            this.battleCode = ladderRec.battleCode;
            this.status = ladderRec.status;
            if(this.status == LADDER_STATUS.BATTLE) {
                this.time = Math.floor(ladderRec.battleTime/1000) + LADDER.LADDER_BATTLE_COUNTDOWN;
            } else if (this.status == LADDER_STATUS.CHECK) {
                this.time = Math.floor(ladderRec.checkTime/1000) + LADDER.LADDER_BATTLE_PREPARE_COUNTDOWN;
            }
        }
    }

    setOppPlayers(oppPlayers: LadderOppPlayerReturn[]) {
        this.oppPlayers = oppPlayers;
    }

}

// getOppLineup返回
export class LadderOppLineupReturn {
    myRank: number = 0;
    isRobot: boolean = true;
    rank: number = 0;
    roleId: string = '';
    roleName: string = LADDER.LADDER_ROBOT_NAME;
    title: number = 1;
    guildName: string = '';
    defCe: number = 0;
    heroes: LadderOppPlayerHeroInfo[] = []

    setMyRank(myRank: number) {
        this.myRank = myRank;
    }

    setRobot(ladderDifficultRatio: DicLadderDifficultRatio, warJsons: DicWarJson[]) {
        this.isRobot = true;
        this.rank = ladderDifficultRatio.rank;
        this.roleId = `robot${this.rank}`;
        this.defCe = ladderDifficultRatio.ce;
        for(let warJson of warJsons) {
            if(warJson.relation == 2) {
                let hero = new LadderOppPlayerHeroInfo();
                hero.setByWarJson(warJson);
                this.heroes.push(hero);
            }
        }
    }

    /**
     * 
     * @param ladderMatch 需要是populate过role和defense.hero
     */
    setPlayer(ladderMatch: LadderMatchType) {
        this.isRobot = false;
        this.rank = ladderMatch.rank;
        this.roleId = ladderMatch.roleId;
        let role = <RoleType>ladderMatch.role;
        this.roleName = role.roleName;
        this.title = role.title;
        this.guildName = role.guildName;
        for(let defenseHero of (ladderMatch.defense?.heroes||[])) {
            this.defCe += defenseHero.ce;
            let hero = new LadderOppPlayerHeroInfo();
            hero.setByDefenseHero(<HeroType>defenseHero.hero);
            this.heroes.push(hero);
        }
    }
}

// getOppData接口的返回
export class LadderOppDetailHeroReturn {
    actorId: number = 0;             // 武将id            
    skinId: number = 0;              // 皮肤id，fashions表的heroId
    actorName: string = '';           // 武将名            
    dataId: number = 0;              // 出兵表唯一id            
    relation: number = 0;            // 地方还是我方            
    dirction: number = 0;           // 方向            
    outIndex: number = 0;            // 玩家设置的出场顺序，即order字段
    x: number = 0;                   // 战场x坐标            
    y: number = 0;                   // 战场y坐标            
    var: number = 0;                 // 变量            
    lv: number = 0;                  // 等级            
    hide: number = 0;                // 是否隐藏            
    initial_ai: number = 0;          // ai类型            
    attribute: string = '';          // 武将属性，格式 id&val|id&val|...，这里的次级属性都是没有除1000的值
    star: number = 0;                     // 星级            
    colorStar: number = 0;                // 彩星
    quality: number = 0;                  // 品质
    job: number = 0;                  // 职业
    skill: string = '';                    // 技能
    seid: string = '';                     // 技能 
    spine: string = '';                    // 动画
    talent: Talent[] = [];
    subHid: number = 0;                      // 副将
    artifact: HeroArtifact[] = [];

    constructor(warJson: DicWarJson, defensHero: LadderDefenseHero, artifacts: ArtifactModelType[]) {
        this.dataId = warJson.dataId;
        this.relation = warJson.relation;
        this.dirction = warJson.dirction;
        this.x = warJson.x;
        this.y = warJson.y;
        this.var = warJson.var;
        this.hide = warJson.hide;
        this.skill = warJson.skill;
        this.seid = warJson.seid;
        this.spine = warJson.spine;
        let dicHero = gameData.hero.get(warJson.actorId);
        if(dicHero) this.job = dicHero.jobid;

        if(defensHero) {
            this.outIndex = defensHero.order;
            this.initial_ai = defensHero.ai;
            let hero = <HeroType>defensHero.hero;
            if(hero) {
                this.actorId = hero.hid;
                this.skinId = hero.skinId;
                this.actorName = hero.hName;
                this.lv = hero.lv;
                this.star = hero.star;
                this.colorStar = hero.colorStar;
                let skin = hero.skins.find(cur => cur.enable);
                if(skin) this.talent = skin.talent;
                this.job = hero.job;
                this.subHid = hero.subHid;
                let artifact = artifacts.find(cur => cur.seqId == hero.artifact);
                if(artifact) this.artifact.push({ artifactId: artifact.artifactId, lv: artifact.lv });
            }
        }
    }

    setAttribute(attribute: string) {
        this.attribute = attribute;
    }
}

// getOppData接口的返回
export class LadderOppDetailReturn {
    battleCode: string = '';
    roleId: string = '';
    status: LADDER_STATUS = LADDER_STATUS.NO;
    time: number = 0;
    isRobot: boolean = false;
    title: number = 1;
    warId: number = 0;
    heroes: LadderOppDetailHeroReturn[] = [];
    defCe: number = 0;

    constructor(ladderRec: LadderMatchRecType) {
        this.battleCode = ladderRec.battleCode;
        this.roleId = ladderRec.roleId2;
        this.status = ladderRec.status;
        if(this.status == LADDER_STATUS.BATTLE) {
            this.time = Math.floor(ladderRec.battleTime/1000) + LADDER.LADDER_BATTLE_COUNTDOWN;
        } else if (this.status == LADDER_STATUS.CHECK) {
            this.time = Math.floor(ladderRec.checkTime/1000) + LADDER.LADDER_BATTLE_PREPARE_COUNTDOWN;
        }
    }

    setByPlayer(ladderMatch: LadderMatchType, warJsons: DicWarJson[], artifacts: ArtifactModelType[]) {
        this.isRobot = false;
        let role = <RoleType>ladderMatch.role;
        this.title = role.title;
        if(ladderMatch.defense) {
            this.warId = ladderMatch.defense.warId;
            let heroes = ladderMatch.defense.heroes||[];
            for(let hero of heroes) {
                let warJson = warJsons.find(cur => cur.dataId == hero.dataId);
                if(warJson) {
                    let obj = new LadderOppDetailHeroReturn(warJson, hero, artifacts);
                    this.heroes.push(obj);
                    this.defCe += hero.ce;
                }
            }
        }
    }

    setByRobot(dicLadderDifficultRatio: DicLadderDifficultRatio) {
        this.isRobot = true;
        this.roleId = `robot${dicLadderDifficultRatio.rank}`;
        this.warId = dicLadderDifficultRatio.gkId;
        this.defCe = dicLadderDifficultRatio.ce;
    }

    setAttribute(hid: number, attribute: string) {
        let hero = this.heroes.find(cur => cur.actorId == hid);
        if(hero) hero.setAttribute(attribute);
    }
}