import FObject, { GroupType } from "./FObject";
import CMath from "../../../util/CMath";
import BObject from "../../fight/bullet/BObject";
import FPanel from "./FPanel";
import { FFAttr } from "../../data/FFCalAttr";
import AIBase from "./AI/AIBase";
import FPanelIcon from "./FPanelIcon";
import Equip from "../../home/equip/Equip";
import { __SkillData } from "../../data/sdata/SManage";
const { ccclass, property } = cc._decorator;

/**
 * 精灵状态
 */
export const SpriteType = cc.Enum({
    NONE: 0,//站立
    MOVE: 1,//移动
    // ATK: 2, //攻击
});

/**
 * 动画类型
 */
export const SpriteActionType = cc.Enum({
    stand: 'idle',//站立
    move: 'move',//移动
    run: 'run',//跑步
    atk: 'atk',//行走攻击
    atk1: 'atk1',//站立攻击
    dead: 'dead',//死亡
    yun: 'yun',//倒地晕
    yun2: 'yun2',//晕倒地上
    dang: 'dang',//惊吓
    chuizi: 'chuizi',//锤子
    shiqu: 'shiqu'//捡起
});
/**
 * 碰撞精灵
 */
export interface ColliderSprite {
    sprite: FSprite,
    dis: number,
}
/**
 * 精灵
 */
@ccclass
export default class FSprite extends FObject {
    /**
     * 当前调用的动画
     */
    public spine: sp.Skeleton = null;

    // public hurtSpine: sp.Skeleton = null;

    // public hurtParticle: cc.ParticleSystem = null;

    @property(cc.Prefab)
    mBullet: cc.Prefab = null;//攻击效果

    // @property(cc.Node)
    // mWeapon: cc.Node = null;//武器

    public mAtkSite: sp.spine.Bone = null;//子弹发射插槽
    public mWeapon1: sp.spine.Bone = null;//武器

    mPanels: Array<FPanel> = [];//显示面板

    public mRigidBody: cc.RigidBody;//刚体

    public status = SpriteType.NONE;//当前状态

    /**
     * 当前剩余血量
     */
    public hp: number = -1;
    /**
     * 属性
     */
    public attrData: FFAttr = null;
    /**
     * 是否被激活
     */
    public isActive = true;

    public SPEED_WALK = 300;//行走速度
    // public SPEED_RUN = 350;//跑步速度
    public SPEED_SHOOT = 100;//攻击时候的移动速度
    /**
     * 当前移动的方向
     */
    private dir = { x: 0, y: 0 };
    public moveV2: cc.Vec2 = cc.v2(1, 0);
    public isWalk = false;//是否行走
    public isRuning = false;//是否跑
    public isShooting = false;//是否按住攻击按钮
    public wAngle = 0;//当前操作武器旋转角度
    /**
     * 当前是否暂停状态
     */
    public gamePause: boolean = false;

    public hitCount = 0;

    private yanwu: cc.Node = null;

    /**
     * 当前是否有盾,有盾的时候减少50%伤害
     */
    public hasDun = false;
    /**
     * 当前是否处于无敌状态
     */
    public hasWudi = false;
    onLoad() {
        let spriteNode = this.node.getChildByName('juese01');
        let spineNode0 = spriteNode.getChildByName('spineRight');
        if (this.node.name == "s1") {
            this.yanwu = spriteNode.getChildByName("yanwu_gs");
        }
        // this.hurtSpine = spriteNode.getChildByName("hurt").getComponent(sp.Skeleton);
        // this.hurtParticle = spriteNode.getChildByName("particle").getComponent(cc.ParticleSystem);
        this.mRigidBody = this.node.getComponent(cc.RigidBody);
        this.mRigidBody.allowSleep = false;

        this.spine = spineNode0.getComponent(sp.Skeleton);

        this.mAtkSite = this.spine.findBone('zidan');
        this.mWeapon1 = this.spine.findBone('control');
    }
    start() {
        if (this.id > 0) {//载入预设怪物数据
            let main = this.map.ff.main;
            let attrData = main.sManage.getMonsterData(this.id);
            this.setAttrData(attrData);
            this.hp = this.attrData.hp;
            for (let i = 0; i < this.mPanels.length; i++) {
                const element = this.mPanels[i];
                element.updatePanel()
            }
        }
        this.setYanwu(false);
        this.updateSkin()
    }
    /**
     * 使用锤子
     */
    public useHammer() {
        Equip.chaneWeapon(this.spine, '1000')
    }
    public updateSkin() {
        // if (this.hp <= 0) {
        //     return
        // }
        // if (this.attrData.skin) {
        //     this.spine.setSkin(this.attrData.skin)
        // }
        // if (this.attrData.weapon) {
        //     Equip.chaneWeapon(this.spine, this.attrData.weapon)
        // }
    }
    update(dt) {
        if (this.gamePause) {
            return;
        }
        this.updateMove(dt)
    }

    public setPause(pause: boolean) {
        this.gamePause = pause
        if (this.gamePause) {
            this.setDir({ x: 0, y: 0 });
            this.setWalk(false);
        }
    }
    /**
     * 设置坐标和方向
     */
    public setPosition(pos) {
        this.node.setPosition(pos);
    }
    /**
     * 设置子弹
     * @param mBullet 
     */
    public setBullet(mBullet) {
        this.mBullet = mBullet;
    }
    /**
     * 设置属性
     * @param attrData 
     */
    public setAttrData(attrData: FFAttr) {
        this.attrData = attrData;
        //mBullet
        if (this.mBullet) {
            let node = cc.instantiate(this.mBullet);
            node.destroy();
        } else {
            if (!attrData.bullet) {
                attrData.bullet = '1001'
            }
            attrData.bullet = '1101'
            cc.resources.load('prefab/bullet/' + attrData.bullet, cc.Prefab, (err, prefab: cc.Prefab) => {
                if (err) {
                    cc.error(err);
                } else {
                    //加载结束
                    this.mBullet = prefab;
                    let node = cc.instantiate(this.mBullet);
                    node.destroy();
                }
            });
        }
        let asset = 'prefab/common/hp_monter';
        if (this.node.group == 'B') {
            asset = 'prefab/common/hp_monter_red'
        }
        cc.resources.load(asset, cc.Prefab, (err, prefab: cc.Prefab) => {
            if (err) {
                cc.error(err);
            } else {
                //加载结束
                let node = cc.instantiate(prefab);
                let panel = node.getComponent(FPanel);
                panel.sprite = this;
                this.mPanels.push(panel);
                node.y = -10;
                node.parent = this.node;
                panel.updatePanel();
            }
        });
    }
    public flushAttrData(attrData: FFAttr) {
        this.attrData = attrData;
        this.updateSkin()

        if (!attrData.bullet) {
            attrData.bullet = '1001'
        }
        cc.resources.load('prefab/bullet/' + attrData.bullet, cc.Prefab, (err, prefab: cc.Prefab) => {
            if (err) {
                cc.error(err);
            } else {
                //加载结束
                this.mBullet = prefab;
                let node = cc.instantiate(this.mBullet);
                node.destroy();
            }
        });
    }
    /**
     * 添加面板显示
     */
    public addPanelHUD() {
        let res = this.ff.fres;
        let node = cc.instantiate(res.mHudPrefab)
        node.parent = res.mHudNode;

        let panelIcon = node.getComponent(FPanelIcon)
        panelIcon.sprite = this
        panelIcon.setIcon()
        this.mPanels.push(panelIcon)
    }



    protected setWeaponAngle(angle: number) {
        if (this.mWeapon1) {
            this.wAngle = angle * 180 / Math.PI;
            // console.log("=====wAngle===", this.wAngle);
            this.mWeapon1.rotation = this.wAngle + 180;//this.spine.node.scaleX > 0 ? this.wAngle - 90 : -(this.wAngle - 90);
        }
    }
    /**
     * 更新武器旋转角度
     */
    protected updateWeaponAngle(angle: number) {
        if (this.mWeapon1) {
            // this.mWeapon1.data.rotation = (angle - 90) * this.spine.node.scaleX + 90
            this.mWeapon1.rotation = (angle - 90) * this.spine.node.scaleX
            // console.log("======武器角度=====", this.mWeapon1.rotation)
        }
    }
    /**
     * 角色状态改变后更新角色动作
     */
    public updateAction() {
        if (this.isWalk) {
            if (this.isShooting) {
                this.createBullet();
                this.playAction(SpriteActionType.atk, false, () => {
                    this.updateSpine();
                    // this.tmpDir.x = this.dir.x;
                    // this.tmpDir.y = this.dir.y;
                    this.updateAction();
                });
            } else {
                this.playAction(SpriteActionType.move, true);
            }
        } else {
            if (this.isShooting) {
                this.createBullet();
                this.playAction(SpriteActionType.atk1, false, () => {
                    this.updateSpine();
                    // this.tmpDir.x = this.dir.x;
                    // this.tmpDir.y = this.dir.y;
                    this.updateAction();
                });
            } else {
                this.playAction(SpriteActionType.stand, true);
            }
        }
    }
    /**
     * 更新动画朝向
     */
    public updateSpine(): boolean {
        let csprite: FSprite = this.findEnemy(1300).sprite;
        let p1 = this.node.getPosition();
        if (csprite && csprite.isValid) {
            let p2 = csprite.node.getPosition();
            if (p1.x == p2.x) {
            } else if (p1.x - p2.x > 3) {
                this.setLR(-1);
            } else {
                this.setLR(1);
            }
            //计算弧度
            // let angle = Math.floor(CMath.getAngle(p1, p2) * (180 / Math.PI));
            //this.wAngle = angle
            // this.updateWeaponAngle(angle);
        } else {
            // this.updateSpineByDir();
            // this.updateWeaponAngle(this.wAngle);
        }
        return false;
    }
    private updateSpineByDir() {
        if (this.dir.x >= 0) {
            this.setLR(1);
        } else {
            this.setLR(-1);
        }
    }
    /**
     * 设置精灵方向
     */
    public setDir(dir): boolean {
        if (this.gamePause) {
            return;
        }
        if (dir.x == 0 && dir.y == 0) {
            this.setWalk(false);
            return false;
        }
        if (this.isWalk && this.dir.x == dir.x && this.dir.y == dir.y) {
            return true;
        }
        this.dir.x = dir.x;
        this.dir.y = dir.y;
        this.setWalk(true);
        return true;
    }
    /**
     * 设置是否移动
     * @param isWalk 
     */
    public setWalk(isWalk: boolean) {
        this.isWalk = isWalk;
        // this.updateSpine()
        // this.updateAction();
    }
    /**
     * 设置是否跑
     * @param isRuning 
     */
    // public setRuning(isRuning: boolean) {
    //     this.isRuning = isRuning;
    //     this.updateAction();
    // }
    /**
     * 攻击时候的方向
     */
    /**
     * 设置攻击
     * @param isShooting 
     */
    public setShooting(isShooting: boolean) {
        this.isShooting = isShooting;
        if (isShooting && this.status == SpriteType.NONE) {
            // this.tmpDir.x = this.dir.x;
            // this.tmpDir.y = this.dir.y;
            this.updateAction();
        }
    }

    public updateMove(dt) {
        if (this.isWalk) {
            // this.mRigidBody.allowSleep = false;
            let speed = 0;
            if (this.isShooting) {
                speed = this.SPEED_SHOOT;
            } else {
                speed = this.SPEED_WALK;
            }
            this.node.x += this.dir.x * dt * speed;
            this.node.y += this.dir.y * dt * speed;
            this.setYanwu(true);
        } else {
            // this.mRigidBody.allowSleep = true;
            this.setYanwu(false);
        }

    }
    /**
    * 移动到某个点
    * @param x 
    * @param y 
    */
    public moveTo(pos: cc.Vec2, dt): boolean {
        // this.node.x = pos.x;
        // this.node.y = pos.y;
        let speed = 1200;
        let px = this.node.x > pos.x ? -speed : speed;
        let py = this.node.y > pos.y ? -speed : speed;
        this.node.x += dt * px;
        this.node.y += dt * py;
        if (px > 0) {
            if (this.node.x > pos.x) {
                this.node.x = pos.x;
            }
        } else {
            if (this.node.x < pos.x) {
                this.node.x = pos.x;
            }
        }
        if (py > 0) {
            if (this.node.y > pos.y) {
                this.node.y = pos.y;
            }
        } else {
            if (this.node.y < pos.y) {
                this.node.y = pos.y;
            }
        }
        return false;
    }



    // public playAction(nActionType, loop?: boolean, finishBack?: () => void) {
    //     if (finishBack) {
    //         this.spine.setCompleteListener(() => {
    //             this.spine.setCompleteListener(null);
    //             finishBack();
    //         });
    //     }
    //     if (!this.isActive) {
    //         return;
    //     }
    //     this.spine.setAnimation(0, nActionType, loop);
    // }


    public setLR(lr: number) {
        let scaleX = Math.abs(this.spine.node.scaleX);
        if (lr == -1) {
            this.spine.node.scaleX = -scaleX;
        } else {
            this.spine.node.scaleX = scaleX;
        }
    }
    public getLR(): number {
        if (this.spine.node.scaleX > 0) {
            return 1
        } else {
            return -1;
        }
    }
    /**
     * hit事件回调
     */
    public fireCallback: () => void;
    public setFireCallback(fireCallback: () => void) {
        this.fireCallback = fireCallback;
    }
    /**
     * 
     * @param prefab 添加攻击特效
     */
    public addSendEffect(prefab: cc.Prefab, target: cc.Node) {
        if (prefab) {
            let node = cc.instantiate(prefab);
            let x = this.mAtkSite.worldX * this.spine.node.scaleX
            let y = this.mAtkSite.worldY
            let pos = cc.v2(x, y);
            node.setPosition(pos);
            node.parent = this.node;

            // if(this.mWeapon1){
            //     node.angle = this.mWeapon1.data.rotation*this.spine.node.scaleX
            //     node.scaleX = this.spine.node.scaleX
            // }
            if (target) {
                let p1 = this.node.getPosition();
                let p2 = target.getPosition();
                //计算弧度
                let angle = Math.floor(CMath.getAngle(p1, p2) * (180 / Math.PI));
                node.angle = angle
            } else {
                node.angle = this.wAngle
            }
            let spine = node.getComponent(sp.Skeleton)
            spine.setCompleteListener(() => {
                node.destroy()
            });
            spine.setAnimation(0, 'atk', false)

        }
    }

    createBullet() {
        if (this.isValid && !this.gamePause) {
            let node = cc.instantiate(this.mBullet);
            node.group = 'bullet';

            let x = this.node.x + this.mAtkSite.worldX * this.spine.node.scaleX
            let y = this.node.y + this.mAtkSite.worldY

            let pos = cc.v2(x, y);
            node.setPosition(pos);

            let bObject = node.getComponent(BObject);
            bObject.setSprite(this);

            let csprite: FSprite = this.findEnemy(2000).sprite;

            node.parent = this.map.mSprites;
            if (csprite && csprite.isValid) {
                bObject.fire(csprite.node);
                this.addSendEffect(bObject.mStartEffect, csprite.node);
            } else {//没有目标的时候,向朝向开火
                bObject.fireAngle1(this.wAngle);
                this.addSendEffect(bObject.mStartEffect, null);
            }
            if (this.fireCallback) {
                this.fireCallback();
            }
            if (this.node == this.ff.mainSprite.node) {
                if (this.hitCount > 4) {
                    this.ff.shockMap();
                    this.hitCount = 0;
                } else {
                    this.hitCount++;
                }
            }
            this.ff.main.playerEffectByPath('music/magic_1001_fs');
        }
    }

    public tmpActionType = null;
    public playAction(nActionType, loop?: boolean, finishBack?: () => void): boolean {
        if (!this.isActive) {
            return false;
        }
        if (!this.spine) {
            return false;
        }
        // cc.log('nActionType : ',this.tmpActionType,nActionType);
        if (nActionType == this.tmpActionType) {
            return false;
        }
        if (finishBack) {
            this.spine.setCompleteListener(() => {
                this.spine.setCompleteListener(null);
                this.tmpActionType = null;
                finishBack();
            });
        }
        //this.spine.setEventListener(null);
        // cc.log('nActionType : ',this.tmpActionType,nActionType);
        this.tmpActionType = nActionType;
        this.spine.setAnimation(0, nActionType, loop);
        return true
    }
    public playAction2(nActionType, loop?: boolean, finishBack?: () => void) {
        this.status = SpriteType.NONE
        if (finishBack) {
            this.spine.setCompleteListener(() => {
                this.spine.setCompleteListener(null);
                this.tmpActionType = null;
                finishBack();
            });
        }
        this.spine.setEventListener(null);
        this.spine.setAnimation(0, nActionType, loop);
    }
    /**
     * 攻击对手进行结算
     * @param target 
     */
    public atkjs(target: FSprite, _skillData?: __SkillData) {
        let reslut = this.calculate(this.attrData, target.attrData, _skillData);
        target.reduce(reslut);
        if (this == this.ff.mainSprite as FSprite) {
            this.ff.flushHP(target);
        } else {
            this.ff.updateHP(target);
        }

        // this.ff.main.playSound2('music/magic_1001_sj');
        //对方存在AI,设置仇恨
        if (target.hp > 0) {
            let baseAI = target.node.getComponent(AIBase);
            if (baseAI) {
                baseAI.setTarget(this);
            }

            // 播放受击动画和粒子特效
            // if (target.node.group == "B") {
            //     target.hurtParticle.enabled = true;
            //     target.hurtSpine.enabled = true;
            //     target.hurtSpine.setAnimation(0, "hurt", false);
            //     target.hurtSpine.setCompleteListener(() => {
            //         target.hurtParticle.enabled = false;
            //     })
            // }
        }
    }
    /**
     * 被攻击
     * @param attrData 
     */
    public bAtkjs(attrData: FFAttr) {
        let reslut = this.calculate(attrData, this.attrData);
        this.reduce(reslut);
    }
    /**
    * 计算攻击
    * @param fd 
    */
    private calculate(A: FFAttr, B: FFAttr, _skillData?: __SkillData): any {
        let xx = A.atk - B.def;
        if (_skillData) {
            // 1 水
            // 2 火
            // 3 土
            // 4 风
            // 5 雷
            // 6 光
            // 7 暗
            if (_skillData.value4 == 1) {
                xx += A.water
            } else if (_skillData.value4 == 2) {
                xx += A.fire
            } else if (_skillData.value4 == 3) {
                xx += A.earth
            } else if (_skillData.value4 == 4) {
                xx += A.wind
            } else if (_skillData.value4 == 5) {
                xx += A.thunder
            }
        }
        if (xx <= 0) {
            xx = 1;
        }
        let hp = xx * 500 / (B.def + 300);
        if (hp < 1) {
            hp = 1;
        }
        let bj = false
        let sk = false
        let rand = CMath.getRandom(1, 100)
        if (rand < 30) {
            bj = true
            hp += hp * 3 / 10
        }
        if (_skillData) {
            hp = hp * _skillData.value1 / 100
            sk = true
        }
        let xd = hp / 10;
        let xxd = CMath.getRandom(-xd, xd);
        hp += xxd;
        if (hp < 10) {
            hp = CMath.getRandom(1, 10);
        }
        hp = Math.floor(hp)

        return {
            hp: Math.floor(hp),
            bj: bj,
            sk: sk
        }
    }
    /**
     * 返回敌人的分组
     */
    public getEnemyGroup() {
        return this.node.group == 'A' ? 'B' : 'A';
    }
    /**
     * 查找周边可攻击对象
     */
    public findEnemy(radius: number): ColliderSprite {
        let mGroup = this.getEnemyGroup();
        let minDis = 0
        let targetSprite = null;
        if (this.map) {
            let nodes = this.map.getSprites();
            for (let i = 0; i < nodes.length; i++) {
                const node = nodes[i];
                let sobj = node.getComponent(FSprite);
                if (sobj && node.active && sobj.isActive && sobj.hp > 0 && sobj.node.group == mGroup) {
                    let dis = cc.Vec2.distance(this.node.getPosition(), node.getPosition());
                    if (dis < radius) {
                        if (targetSprite == null) {
                            targetSprite = sobj;
                            minDis = dis;
                        } else if (dis < minDis) {
                            targetSprite = sobj;
                            minDis = dis;
                        }
                    }
                }
            }
        }
        return {
            sprite: targetSprite,
            dis: minDis
        };
    }
    public wudi(time) {
        this.hasWudi = true
        cc.tween(this.node).sequence(
            cc.delayTime(time),
            cc.callFunc(() => {
                this.hasWudi = false
            })
        ).start()
    }
    public reduce(result: any) {
        let hp = result.hp
        if (hp <= 0) {
            return
        }
        if (this.hasWudi) {
            return
        }
        if (this.hp <= 0) {//已经死了
            return
        }
        if (!this.ff.lockCamera) {
            return
        }

        let bj = result.bj
        let sk = result.sk
        this.playHit();
        if (this.hasDun) {
            hp = Math.floor(hp / 2);
        }
        if (sk) {
            this.showNumber('/' + hp, this.ff.mSkillFont);
        } else if (bj) {
            this.showNumber('/' + hp, this.ff.mBjFont, null, true);
        } else {
            this.showNumber('/' + hp, this.ff.mRed);
        }
        this.hp -= hp;
        if (this.hp <= 0) {
            this.hp = 0;
            this.isActive = false;

            if (this.ff.clearCallback) {
                this.ff.clearCallback(this);
            }
            if (this.ff.removeCallback) {
                this.ff.removeCallback(this);
            }
            if (this == this.ff.mainSprite as FSprite) {
                // this.ff.mainSprite = null;
            } else {
                this.removeSelf();
            }
        }
        this.updatePanel();
    }
    public updatePanel() {
        for (let i = 0; i < this.mPanels.length; i++) {
            const element = this.mPanels[i];
            element.updatePanel();
        }
    }

    public removeSelf() {
        this.gamePause = true;
        this.playAction2(SpriteActionType.dead, false, () => {
            this.node.destroy();
        });
    }
    /**
     * 显示字符
     * ; + 
     * : -
     * @param hp 
     * @param font 
     */
    private showNumber(str: string, font: cc.Font, color?: cc.Color, bs?: boolean) {
        let node: cc.Node = new cc.Node('hp');
        node.group = 'map';
        let lable: cc.Label = node.addComponent(cc.Label);

        lable.fontSize = 30;
        if (font) {
            lable.font = font;
        }
        if (color) {
            node.color = color;
        }
        lable.string = str;

        node.x = this.node.x;
        node.y = this.node.y + this.node.height * 3 / 4;

        this.map.node.addChild(node);
        let moveBy = cc.moveBy(2, cc.v2(0, 150)).easing(cc.easeSineOut());
        let fadeout = cc.fadeOut(2);
        let spawn = null
        if (bs) {
            let seq = cc.sequence(cc.scaleTo(0.05, 1.5), cc.scaleTo(0.2, 1.2));
            spawn = cc.spawn(moveBy, fadeout, seq);
        } else {
            spawn = cc.spawn(moveBy, fadeout);
        }
        let seq = cc.sequence(cc.delayTime(0.1), spawn, cc.callFunc(() => {
            node.removeFromParent(true);
            node.destroy();
        }));

        node.runAction(seq);
    }
    /**
     * 播放受击动作
     */
    public playHit() {
        let spriteNode = this.node.getChildByName('juese01');
        if (spriteNode) {
            cc.tween(spriteNode).sequence(
                cc.scaleTo(0.06, 1.1, 0.95),
                cc.scaleTo(0.06, 1, 1.1),
                cc.scaleTo(0.06, 1, 1),
            ).start();

            // cc.tween(spriteNode).sequence(
            //     cc.moveTo(0.1,cc.v2(0,-9)),
            //     cc.moveTo(0.16,cc.v2(0,6)),
            //     cc.moveTo(0.23,cc.v2(0,-6)),
            //     cc.moveTo(0.3,cc.v2(0,0)),
            // ).start();
        }
    }

    public addActiveIcon(): cc.Node {
        let node = new cc.Node('activeIcon');
        let sprite = node.addComponent(cc.Sprite);
        sprite.spriteFrame = this.ff.mActiveIcon;
        node.parent = this.node;
        node.y = this.node.height + 20
        return node;
    }

    public removeActiveIcon() {
        let node = this.node.getChildByName('activeIcon');
        if (node) {
            node.destroy();
        }
    }

    /**
     * 后面的
     */
    public nextSprite: FSprite;
    public setNext(sprite: FSprite) {
        this.nextSprite = sprite;
    }
    /**
     * 目标位置的切线方向移动
     * @param target 
     */
    public tangentMove(target: cc.Node) {

    }

    public setYanwu(status: boolean) {
        if (this.yanwu) {
            if (this.yanwu.active == status) return
            this.yanwu.active = status;
        }
    }

    public dead(){

    }


}
