import { _decorator,Node } from "cc";
import GRoleBase, { GRoleAnimEvent } from "./GRoleBase";
import { ProgressBar } from "cc";
import { JNFrameInfo } from "../../../../../extensions/ngame/assets/ngame/sync/frame/JNSyncFrame";
import { GFSMAnimBase } from "../fsm/GFSMAnimBase";
import { GFSMDefaultAnim } from "../fsm/Default/GFSMDefaultAnim";
import GFSMDefault from "../fsm/Default/GFSMDefault";
import { JEasing } from "../../../../../extensions/ngame/assets/ngame/sync/frame/game/tween/JNFrameTween";
import { GAttack } from "../attack/GAttack";
import { v2 } from "cc";
import { GTactical } from "../../entity/GTactical";
import { GSkill, GSkillBase, GSkillState } from "../../skill/GSkill";
import { TB } from "../../../config/data/schema";
import { TD } from "../../../App";
import { GPetAminEnum } from "../anim/GPetAnim";
import { UIOpacity } from "cc";
import { v3 } from "cc";
const { property,ccclass } = _decorator;

//默认角色类
@ccclass('GRoleDefault')
export default class GRoleDefault extends GRoleBase<{}>{
    
    @property(Node)
    headInfo:Node;

    @property(ProgressBar)
    bloodVolume:ProgressBar;

    //能量条
    @property(ProgressBar)
    energyVolume:ProgressBar;
    
    //状态机
    fsm:GFSMDefault;

    //动画状态机
    fsmAnim:GFSMDefaultAnim;

    get isDie(){ return this._isDie}
    set isDie(value:boolean){ 
        this._isDie = value;
        //设置死亡状态
        this.fsmAnim.isDie = value;
        if(this.isDie){
            //关闭状态机
            this.fsm.close();
            //死亡回调
            this.killBack.forEach(fun => fun(this));
        }
    }

    //角色类型
    type:number;
    
    //在阵容中的下标
    tacticalIndex:number;

    //阵容
    _tactical:GTactical;
    get tactical(){return this._tactical};
    set tactical(value:GTactical){
        this.setTowards(value.towards);
        this._tactical = value;
    }
    //阵容位置
    get tacticalPos(){ return this.tactical.getPosition(this.tacticalIndex)}

    //角色技能
    skills:GSkillBase[] = [];

    //宠物死亡回调
    killBack:((role:GRoleDefault) => {})[] = [];

    @property(UIOpacity)
    opacity:UIOpacity;

    onSyncLoad(){
        super.onSyncLoad();
        
        //监听攻击
        this.fsmAnim.addEventListener(GRoleAnimEvent.Attack,this.onAttack.bind(this));
        //监听死亡击飞
        // this.fsmAnim.addStartListener(GPetAminEnum.Fly,this.onFly.bind(this));
        this.killBack.push(this.onFly.bind(this));
    }

    //初始化
    onInit(type:number,role:TB.TbGRole,tactical:GTactical,tacticalIndex:number){
        this.opacity.opacity = 0;
        
        super.init(role);
        this.type = type;

        this.range = role.roleAttackRange; //设置攻击范围
        this.role = role; //设置角色

        this.tactical = tactical;
        this.tacticalIndex = tacticalIndex;

        // 设置技能
        this.skills = role.roleSkillIds.map(skillId => {
            let info = TD.TbGRoleSkill.get(skillId);
            return (new GSkill[info.skillController]()).bind(this,info);
        })

        //设置血条位置
        if(this.spine){
            this.headInfo.setPosition(v3(this.headInfo.position.x,role.roleHight,this.headInfo.position.z))
        }
        
    }

    onSyncUpdate(dt: number,frame:JNFrameInfo, input?: {}) {

        this.opacity.opacity = 255;

        super.onSyncUpdate(dt,frame,input);

        //更新技能
        this.skills.forEach(skill => skill.onUpdate(dt));

        //更新显示
        this.bloodVolume.progress =  this.blood / this.fullBlood;
        //显示第一个技能进度条
        if(this.skills[0]){
            this.energyVolume.progress =  this.skills[0].getProgress();
        }

    }

    protected fsmCreate(): GFSMDefault {
        return new GFSMDefault(this);
    }
    protected fsmAnimCreate(): GFSMAnimBase {
        return new GFSMDefaultAnim(this.spine);
    }

    //攻击
    onAttack(){
        if(!this.fsm.enemy) return;
        // console.log(`播放动画[${this.nId}] onAttack`,this.fsm.enemy.nId)
        //敌人扣血
        let info = TD.TbGRoleAttack.get(this.role.id);
        (new GAttack[info.attackWay]()).attack(this,info);
        this.attackCallbacks.forEach(fun => fun());
    }

    //击飞
    onFly(){

        let vWorld = this.node.worldPosition;
        let vEndWorld = this.getWorldBackLen(v2(1500,500));
        this.JTween(vWorld)
            .to({x:vEndWorld.x},1200)
            .onUpdate(pos => {
                if(this.node && this.node.isValid)
                    this.node.worldPosition = pos;
            })
            .start();
        this.JTween(vWorld)
            .to({y:vEndWorld.y},1200)
            .easing(JEasing.Circular.Out)
            .onUpdate(pos => {
                if(this.node && this.node.isValid)
                    this.node.worldPosition = vWorld
            })
            .start();

    }

    //过滤敌人
    filterEnemy(roles:GRoleDefault[] = []){
        return roles.filter(role => role.type != this.type);
    }

    //恢复阵容朝向
    onRecoverTacticalTowards(){
        this.setTowards(this.tactical.towards);
    }

    //释放技能 每一次只能释放一次
    onSkill():boolean{

        for (const item of this.skills) {
            if(item.isRelease()){
                //如果可以释放则释放
                item.release();
                return true;
            }
        }
        return false;

    }

    //判断是否可以释放技能
    isReleaseSkill():boolean{
        for (const skill of this.skills) {
            if(skill.isRelease()){
                return true;
            }
        }
        return false;
    }

    //释放技能
    onReleaseSkill():boolean{
        for (const skill of this.skills) {
            if(skill.isRelease()){
                skill.release();
                return true;
            }
        }
        return false;
    }

    //是否正在释放技能
    isReleasingSkill():boolean {
        for (const skill of this.skills) {
            if(skill.state() == GSkillState.Releasing){
                return true;
            }
        }
        return false;
    }

    onQueryEunmy():GRoleBase<{}>{
        return null;
    }

    //添加一个死亡回调
    addKillBackEvent(callback:(role:GRoleDefault) => {}){
        this.killBack.push(callback);
    }

    //判断玩家是否在阵法位置
    isTacticalPos():boolean{
        return this.tactical.getPosition(this.tacticalIndex).equals(this.v2World);
    }

}

