using Spine.Unity;
using Spine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum DemonicState
{
    Idle = 0,
    Walk = 2,
    Rise = 3,//空中上升
    Fall = 4,//空中下落
    Hurt = 5,
    Attack = 6,
    Die = 7,
}

public enum DemonicTargetType
{
    Player = 0,
    Demonic = 1,
    FlyDemonic = 2,
    LowHPDemonic = 3,
    Tower = 4,
}

public class Demonic : MonoBehaviour
{
    public SkeletonMecanim mecanim;
    public Skeleton skeleton;

    public Animator ani;
    public Animator aniCollider;
    public Rigidbody rb;
    public Foot foot;
    public Transform bodyTrans;
    public UIHP uiHp;

    public float extraRiseGravity = 0; //上升时额外重力加速度
    public float extraFallGravity = -10; //下落时额外重力加速度
    //public float jumpSpeed = 10;
    //public float airJumpSpeed = 10;
    public float maxMoveSpeed = 5;
    //public float moveAcc = 5f;
    //public float airMoveAcc = 3f;

    public DemonicState state;
    [HideInInspector]
    public float invincibleTime;
    public float totalInvincibleTime = 2f;
    [HideInInspector]
    public float hurtKeepTime;
    public float totalHurtKeepTime = 0.5f;
    [HideInInspector]
    public float attackTime;
    public float totalAttack1Time = 0.5f;
    public float totalAttack2Time = 0.5f;

    public bool isDie = false;
    public int totalHp = 100;
    public int hp;
    public List<AttackInfo> attack1Infos, attack2Infos;
    public List<AttackTrigger> attackTriggers;
    public bool canFly = false;
    public float attackDistance;

    private void Awake()
    {
        if (!mecanim)
        {
            mecanim = GetComponentInChildren<SkeletonMecanim>();
            skeleton = mecanim.skeleton;
        }
        if (!ani)
        {
            ani = GetComponentInChildren<Animator>();
        }
    }

    public void BeSummon(int tHp)
    {
        totalHp = tHp;
        hp = totalHp;
        ChangeState(DemonicState.Idle);
    }

    private void FixedUpdate()
    {
        OnState();
    }

    public void Turn()
    {
        bodyTrans.localScale = new Vector3(-bodyTrans.localScale.x, bodyTrans.localScale.y, bodyTrans.localScale.z);
    }

    public Vector3 GetMoveDir()
    {
        return Vector3.zero;
    }

    public bool GetAttack()
    {
        return false;
    }

    public void OnState()
    {
        invincibleTime -= Time.deltaTime;
        hurtKeepTime -= Time.deltaTime;
        attackTime -= Time.deltaTime;
        Vector3 leftDir = GetMoveDir();
        bool isAttack = GetAttack();
        switch (state)
        {
            case DemonicState.Idle:
                if (isAttack)
                {
                    Attack2();
                    break;
                }
                if (!foot.TrigGround)
                {
                    if (rb.velocity.y > 0)
                    {
                        ChangeState(DemonicState.Rise);
                        break;
                    }
                    else
                    {
                        ChangeState(DemonicState.Fall);
                        break;
                    }
                }
                if (leftDir.x > 0.3f || leftDir.x < -0.3f)
                {
                    ChangeState(DemonicState.Walk);
                    break;
                }
                //rb.velocity = Vector3.zero;
                break;
            case DemonicState.Walk:
                if (isAttack)
                {
                    Attack2();
                    break;
                }
                if (!foot.TrigGround)
                {
                    if (rb.velocity.y > 0)
                    {
                        ChangeState(DemonicState.Rise);
                        break;
                    }
                    else
                    {
                        ChangeState(DemonicState.Fall);
                        break;
                    }
                }
                if (leftDir.x < 0.3f && leftDir.x > -0.3f)
                {
                    ChangeState(DemonicState.Idle);
                    break;
                }
                if (leftDir.x > 0.3f)
                {
                    //rb.velocity += Vector3.right * moveAcc * Time.deltaTime;
                    rb.velocity = Vector3.right * maxMoveSpeed;
                    //if (rb.velocity.x > maxMoveSpeed)
                    //{
                    //    rb.velocity = new Vector3(maxMoveSpeed, rb.velocity.y, rb.velocity.z);
                    //}
                    if (bodyTrans.localScale.x > 0)
                    {
                        Turn();
                    }
                }
                else if (leftDir.x < -0.3f)
                {
                    //rb.velocity -= Vector3.right * moveAcc * Time.deltaTime;
                    rb.velocity = Vector3.left * maxMoveSpeed;
                    //if (rb.velocity.x < -maxMoveSpeed)
                    //{
                    //    rb.velocity = new Vector3(-maxMoveSpeed, rb.velocity.y, rb.velocity.z);
                    //}
                    if (bodyTrans.localScale.x < 0)
                    {
                        Turn();
                    }
                }
                break;
            case DemonicState.Rise:
                if (rb.velocity.y <= 0)
                {
                    ChangeState(DemonicState.Fall);
                    break;
                }
                //if (btnJumpPress || cacheJumpTime > 0)
                //{
                //    if (!airJumped && rb.velocity.y < airJumpSpeed)
                //    {
                //        airJumped = true;
                //        AirJump();
                //        break;
                //    }
                //}
                
                rb.velocity += Vector3.up * extraRiseGravity * Time.deltaTime;
                break;
            case DemonicState.Fall:
                if (foot.TrigGround)
                {
                    ChangeState(DemonicState.Idle);
                    break;
                }
                //if (foot.canStepPlayers.Count > 0)
                //{
                //    Jump(jumpSpeed / 2);
                //    StepOther();
                //    break;
                //}
                //if (foot.canStepEnemyList.Count > 0)
                //{
                //    Jump(jumpSpeed / 2);
                //    StepEnemy();
                //    break;
                //}
                //if (btnJumpPress || cacheJumpTime > 0)
                //{
                //    if (!airJumped)
                //    {
                //        airJumped = true;
                //        AirJump();
                //        break;
                //    }
                //    else if (canJumpTick >= runner.Tick)
                //    {
                //        Jump();
                //        break;
                //    }
                //}
                rb.velocity += Vector3.up * extraFallGravity * Time.deltaTime;
                break;
            case DemonicState.Hurt:
                if (hurtKeepTime <= 0)
                {
                    ChangeState(DemonicState.Idle);
                    break;
                }
                if (!foot.TrigGround)
                {
                    rb.velocity += Vector3.up * extraFallGravity * Time.deltaTime;
                }
                rb.velocity = rb.velocity / 5 * 4;
                break;
            case DemonicState.Attack:
                if (attackTime <= 0)
                {
                    ChangeState(DemonicState.Idle);
                    break;
                }
                break;
            default:
                break;
        }
    }

    public void Attack1()
    {
        ani.Play("attack1", 0, 0);
        aniCollider.Play("Attack1", 1, 0);
        attackTime = totalAttack1Time;
        for (int i = 0; i < attack1Infos.Count; i++)
        {
            attackTriggers[i].damage = attack1Infos[i].damage;
            Vector3 attackDir = attack1Infos[i].attackDir.normalized;
            if (bodyTrans.localScale.x < 0)
            {
                attackDir.x = -attackDir.x;
            }
            attackTriggers[i].force = attackDir * attack1Infos[i].force;
        }
        ChangeState(DemonicState.Attack);
    }

    void Attack2()
    {
        ani.Play("attack2", 0, 0);
        aniCollider.Play("Attack2", 1, 0);
        attackTime = totalAttack2Time;
        for (int i = 0; i < attack2Infos.Count; i++)
        {
            attackTriggers[i].damage = attack2Infos[i].damage;
            Vector3 attackDir = attack2Infos[i].attackDir.normalized;
            if (bodyTrans.localScale.x < 0)
            {
                attackDir.x = -attackDir.x;
            }
            attackTriggers[i].force = attackDir * attack2Infos[i].force;
        }
        ChangeState(DemonicState.Attack);
    }

    public void ChangeState(DemonicState newState)
    {
        switch (state)
        {
            case DemonicState.Idle:
                break;
            case DemonicState.Walk:
                rb.velocity = Vector3.zero;
                break;
            case DemonicState.Rise:
                break;
            case DemonicState.Fall:
                rb.velocity = Vector3.zero;
                break;
            case DemonicState.Hurt:
                break;
            case DemonicState.Attack:
                aniCollider.Play("NotAttack", 1, 0);
                break;
            case DemonicState.Die:
                isDie = false;
                break;
            default:
                break;
        }
        DemonicState oldState = state;
        state = newState;
        switch (newState)
        {
            case DemonicState.Idle:
                ani.Play("idle", 0, 0);
                aniCollider.Play("Idle", 0, 0);
                rb.velocity = Vector3.zero;
                //animalAni.SetInteger("state", (int)PlayerState.Idle);
                break;
            case DemonicState.Walk:
                ani.Play("walk", 0, 0);
                aniCollider.Play("Walk", 0, 0);
                //animalAni.SetInteger("state", (int)PlayerState.Walk);
                break;
            case DemonicState.Rise:
                aniCollider.Play("Rise", 0, 0);
                break;
            case DemonicState.Fall:
                aniCollider.Play("Fall", 0, 0);
                //animalAni.SetInteger("state", (int)PlayerState.Fall);
                break;
            case DemonicState.Hurt:
                ani.Play("hitted", 0, 0);
                aniCollider.Play("Hurt", 0, 0);
                hurtKeepTime = totalHurtKeepTime;
                invincibleTime = totalInvincibleTime;
                //ani.Play("Invincible", 2, 0);
                break;
            case DemonicState.Attack:
                break;
            case DemonicState.Die:
                ani.Play("die", 0, 0);
                aniCollider.Play("Die", 0, 0);
                isDie = true;
                break;
            default:
                break;
        }
    }

    public void BeHit(int damage, Vector3 force)
    {
        hp -= damage;
        uiHp.ShowHP(hp, totalHp);
        rb.AddForce(force);
        if (hp < 0)
        {
            ChangeState(DemonicState.Die);
        }
        else
        {
            ChangeState(DemonicState.Hurt);
        }
    }
}
