import { GUILDACTIVITY } from "../../pubUtils/dicParam";
import { SimpleGuildRankParam, SimpleRoleRankParam } from '../rank'
import { prop } from "@typegoose/typegoose";
import { CITY_STATUS, RACE_ACTIVITY_STATUS, RACE_EVENT } from "../../consts";
import { gameData, getRaceEventItems } from "../../pubUtils/data";
import { getRandEelm } from "../../pubUtils/util";
import { RewardInter } from "../../pubUtils/interface";

export class GateMembersRec {
    roleId: string;
    round: number = 0;
    enemies: number[] = [];
    constructor(roleId: string) {
        this.roleId = roleId;
    }
}

class WoodenHorseMember {
    roleId: string;
    roleName: string;
    sid: string;
    items?: RewardInter[];
}

// 木牛流马
export class WoodenHorse {
    @prop({required: true})
    serverId: number = 0;               // 服务器id
    @prop({required: true})
    guildCode: string = "";             // 军团code 木马的唯一标识
    @prop({required: true})
    guildName: string = "";             // 军团名
    @prop({required: true})
    guildCe: number = 0;                // 军团战力
    @prop({required: true})
    status: number = 0;                 // 状态 0-停止 1-开启 2-结束
    @prop({required: true})
    speed: number = GUILDACTIVITY.RACE_INIT_SPEED; // 速度
    @prop({required: true})
    durability: number = 100;           // 耐久度
    @prop({required: true})
    distance: number = 0;               // 距离
    @prop({required: true})
    startTime: number = 0;              // 开始时间
    @prop({required: true})
    time: number = 0;                   // 到达时间
    @prop({required: true})
    memberCnt: number = 0;              // 成员人数
    @prop({required: true})
    members: WoodenHorseMember[] = [];  // 成员
    @prop({required: true})
    shield: number = 0;                 // 护盾数量
    @prop({required: true})
    shieldTime: number = 0;             // 天师盾符
    @prop({required: true})
    stopContinueTime: number = 0;           // 鬼手阴符

    constructor(guildCode: string, guildName: string, guildCe: number, serverId: number) {
        this.guildCode = guildCode;
        this.guildName = guildName;
        this.guildCe = guildCe;
        this.serverId = serverId;
    }

    /**
     * 根据时间计算当前木马速度距离耐久等
     * @param events 
     * @returns {boolean} needSendEnd 是否跑到终点发送结束新号 
     */
    public calCurWoodenHorse(events: Event[]): boolean {
        if(this.status == RACE_ACTIVITY_STATUS.END) return false;
        if(this.status == RACE_ACTIVITY_STATUS.WAITING && this.stopContinueTime && Date.now() > this.stopContinueTime) {
            this.status = RACE_ACTIVITY_STATUS.START; this.stopContinueTime = 0;
        }

        if(this.status == RACE_ACTIVITY_STATUS.START) {
            if(this.distance >= GUILDACTIVITY.RACEACTIVITY_LENGTH) {
                this.distance = GUILDACTIVITY.RACEACTIVITY_LENGTH;
                this.status = RACE_ACTIVITY_STATUS.END;
                this.speed = 0;
                return true;
            }

            this.distance = Math.floor((this.distance + (Date.now() - this.time)/1000 * this.speed ) * 1000)/1000; // 1位小数点
            this.time = Date.now();
        }
        let effectiveEvents = new Array<Event>();
        for(let i = 0; i < events.length; i++) {
            let event = events[i];
            if(!event.startTime && event.startDistance && this.distance > event.startDistance) {
                let startTime = Date.now() - Math.floor((this.distance - event.startDistance) / this.speed);
                event.setStartTime(startTime); // 距离生效的事件的实际生效时间，主要用于速度叠加顺序
            }
            let isEffective = false;
            if(event.startTime <= Date.now() && event.endTime > Date.now()) {
                isEffective = true;
            } else if (event.startDistance <= this.distance && event.endDistance > this.distance) {
                isEffective = true;
            } else if (event.endTime < Date.now() || event.endDistance < this.distance) {
                if(event.endTime && event.startTime == event.endTime) {
                    isEffective = true;
                }
                if(event.endDistance && event.startDistance == event.endDistance) {
                    isEffective = true;
                }

                let index = events.findIndex(cur => cur.id == event.id);
                events.splice(index, 1);
            }
            if(isEffective) {
                effectiveEvents.push(event);
            }
        }

        effectiveEvents.sort((a, b) => a.startTime - b.startTime);
        this.speed = GUILDACTIVITY.RACE_INIT_SPEED + this.memberCnt * GUILDACTIVITY.RACE_PER_SPEED;
        for(let { id, count, endTime } of effectiveEvents) {
            this.calEvent(id, count, endTime);
        }
        if(this.durability <= 0) {
            this.status = RACE_ACTIVITY_STATUS.END;
            this.speed = 0;
        } 
        return false;
    }

    private calEvent(id: number, count: number = 1, endTime?: number) {
        let { effect } = gameData.raceActivityEvents.get(id);

        switch (id) {
            case RACE_EVENT.LIANNU:
                if (this.shieldTime < Date.now()) {
                    if (this.shield >= count) {
                        this.shield -= count;
                    } else {
                        this.shield = 0;
                        this.durability -= (count - this.shield) * effect[0];
                        if(this.durability > 100) this.durability = 100;
                        if(this.durability < 0) this.durability = 0;
                    }
                }
                break;
            case RACE_EVENT.GUISHOUYINFU:
                if (this.shieldTime < Date.now()) {
                    this.stopContinueTime = endTime;
                    this.status = RACE_ACTIVITY_STATUS.WAITING;
                    this.time = endTime;
                    this.speed = 0;
                }
                break;
            case RACE_EVENT.FENGCHE:
            case RACE_EVENT.WUGUIBANYUNFU:
                this.speed *= Math.pow(1 + effect[0] / 100, count); break;
            case RACE_EVENT.LUDUN:
                this.shield += count * effect[0]; break;
            case RACE_EVENT.TIANSHIDUNFU:
                this.shieldTime = endTime; break;
            case RACE_EVENT.JIASU_1:
                this.speed *= Math.pow(1 + effect[0] / 100, count); break;
            case RACE_EVENT.JIASU_2:
                this.speed += effect[0]; break;
            case RACE_EVENT.HUIFU_1:
                this.durability += effect[0]; 
                if(this.durability > 100) this.durability = 100;
                if(this.durability < 0) this.durability = 0;
                break;
            case RACE_EVENT.JIANSU_1:
                this.speed *= Math.pow(1 - effect[0] / 100, count); break;
            case RACE_EVENT.JIANSU_2:
                this.speed -= effect[0]; break;
            case RACE_EVENT.SHANGHAI_1:
                this.durability -= effect[0]; 
                if(this.durability > 100) this.durability = 100;
                if(this.durability < 0) this.durability = 0;
                break;
            case RACE_EVENT.ITEM:
                let ranMember: WoodenHorseMember[] = getRandEelm(this.members, GUILDACTIVITY.RACEACTIVITY_EVENT_MEMBERCNT);
                if(ranMember.length <= 0) ranMember = this.members;
                for(let obj of ranMember) {
                    let item = gameData.raceEventItems;
                    obj.items = (obj.items||[]).concat(item);
                }
                for(let obj of this.members) {
                    let item = getRaceEventItems();
                    obj.items = (obj.items||[]).concat(item);
                }
                break;
        }
    }


    public joinMember(roleId: string, roleName: string, sid: string) {
        if(this.members.findIndex(cur => cur.roleId == roleId) == -1) {
            this.members.push({ roleId, roleName, sid });
            this.speed++;
            this.memberCnt++;
        }
        return this;
    }

}

export class Event {
    @prop({required: true})
    id: number;
    @prop({required: true})
    fromGuild: string;
    @prop({required: true})
    toGuild: string;
    @prop({required: true})
    startTime?: number;
    @prop({required: true})
    startDistance?: number;
    @prop({required: true})
    endTime?: number;
    @prop({required: true})
    endDistance?: number;
    @prop({required: true})
    count: number = 1;

    constructor(id: number, fromGuild: string, toGuild: string, count?: number, distance?: number) {
        let dicEvent = gameData.raceActivityEvents.get(id);
        this.id = id;
        this.fromGuild = fromGuild;
        this.toGuild = toGuild;
        
        if(distance) {
            this.startDistance = distance;
            this.endDistance = this.startDistance + dicEvent.continueDistance;
        }
        if(dicEvent.effectTime) {
            this.startTime = Date.now() + dicEvent.effectTime * 1000;
            this.endTime = this.startTime + dicEvent.continueTime * 1000;
        }
        if(count) {
            this.count = count;
        }
    }

    setStartTime(time: number) {
        this.startTime = time;
    }
}

export interface GuildRankParams {
    guildRank: SimpleGuildRankParam[],
    myGuildRank: SimpleGuildRankParam,
    memberRank?: SimpleRoleRankParam[],
    myMemberRank?: SimpleRoleRankParam
}

export class Member {
    @prop({required: true})
    roleId: string;            // 玩家id
    @prop({required: true})
    job: number;             // 在军团的职位
}

export class CityParam {
    cityId: number = 0;   // 城池id
    guardGuildCode: string = ''; // 占领军团id
    guardGuildName: string = ''; // 占领军团名
    declareCount: number = 0; // 宣战数
    status: number = CITY_STATUS.NOT_OPEN;   // 城池对于我军状态

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