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

public enum CharacterState
{
    None = 0,
    Idle = 1,
    Run = 2,
    Rise = 3,//空中上升
    Fall = 4,//空中下落
    Hurt = 5,
    Attack = 6,
    KeepAttack = 7,
    Summon = 8,
    Rush = 9,
    Sprint = 10,
    Die = 11,
    Weak = 12,
    PullRope = 13,
    Spirits = 14,   //召唤英灵
    Float = 15,   //空中漂浮
}

public enum AttackType
{
    Melee = 0,//近战
    Shoot = 1,//射击
}

public class Character : MonoBehaviour
{
    public SkeletonMecanim mecanim;
    public Skeleton skeleton;
    public MeshRenderer meshRenderer;

    public Animator ani;
    public Animator aniCollider;
    public Rigidbody rb;
    public Transform bodyTrans;
    public BeSearchTrigger beSearchTrigger;
    public UIHP uiHp;

    public CharacterState state;
    [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;
    public List<AttackInfo> attack2Infos;
    public List<AttackTrigger> attackTriggers;
    public AttackType attackType;
    public GameObject bulletPrefab;
    public List<Transform> shootPos;
    [HideInInspector]
    public float dieKeepTime;
    public float totalDieKeepTime = 2f;
    public Character attackTarget;
    public bool shootTrack = false;
    [HideInInspector]
    public float invincibleTime;
    public float totalInvincibleTime = 2f;
    public Character targetCharacter;
    public SearchTrigger searchTrigger;
    public List<TargetType> targetTypes;
    public bool canHitFly;
    public bool linked;
    public RopeJoint joint;
    public CharacterRope rope;

    public virtual void Init()
    {
        if (!mecanim)
        {
            mecanim = GetComponentInChildren<SkeletonMecanim>();
        }
        if (mecanim && skeleton == null)
        {
            skeleton = mecanim.skeleton;
        }
        if (!meshRenderer)
        {
            meshRenderer = mecanim.GetComponent<MeshRenderer>();
        }
        if (!ani)
        {
            ani = GetComponentInChildren<Animator>();
        }

        hp = totalHp;
        uiHp.Show(hp, totalHp);
        ChangeState(CharacterState.Idle);

        linked = false;
        if (joint)
        {
            Destroy(joint);
            joint = null;
        }
        if (rope)
        {
            rope = null;
        }
    }

    public virtual void FixedUpdate()
    {
        OnState();
    }

    private void OnEnable()
    {
        for (int i = 0; i < attackTriggers.Count; i++)
        {
            attackTriggers[i].gameObject.SetActive(false);
        }
    }

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

    public virtual void OnState()
    {

    }

    public virtual void ChangeState(CharacterState newState)
    {

    }

    public virtual void BeHit(int damage, Vector3 force, bool changeHurt, float repelValue)
    {
        if (invincibleTime > 0)
        {
            return;
        }
        hp -= damage;
        uiHp.Show(hp, totalHp);
        if (hp <= 0)
        {
            rb.AddForce(force);
            ChangeState(CharacterState.Die);
            return;
        }
    }

    public virtual void AttackShootEvent(int attackId, int shootId)
    {
        AttackInfo attackInfo;
        if (attackId == 1)
        {
            attackInfo = attack1Infos[shootId];
        }
        else
        {
            attackInfo = attack2Infos[shootId];
        }
        GameObject bulletObj = PoolManager.Instantiate(bulletPrefab);
        Bullet bullet = bulletObj.GetComponent<Bullet>();
        Vector3 attackDir = attackInfo.attackDir.normalized;
        if (bodyTrans.localScale.x < 0)
        {
            attackDir.x = -attackDir.x;
        }
        bullet.BeShoot(this, shootPos[shootId].position, attackDir, attackInfo.damage, attackInfo.force, attackInfo.changeHurt, attackInfo.repelValue, shootTrack, attackTarget?attackTarget:null);
    }

    public virtual Vector3 GetMoveDir()
    {
        Vector3 moveDir = Vector3.zero;
        return moveDir;
    }

    public virtual void Attack1()
    {
        Vector3 leftDir = GetMoveDir();
        if (leftDir.x > 0.3f)
        {
            if (bodyTrans.localScale.x > 0)
            {
                Turn();
            }
        }
        else if (leftDir.x < -0.3f)
        {
            if (bodyTrans.localScale.x < 0)
            {
                Turn();
            }
        }

        ani.Play("attack1", 0, 0);
        aniCollider.Play("Attack1", 1, 0);
        attackTime = totalAttack1Time;
        switch (attackType)
        {
            case AttackType.Melee:
                for (int i = 0; i < attack1Infos.Count; i++)
                {
                    attackTriggers[i].damage = attack1Infos[i].damage;
                    attackTriggers[i].changeHurt = attack1Infos[i].changeHurt;
                    attackTriggers[i].repelValue = attack1Infos[i].repelValue;
                    Vector3 attackDir = attack1Infos[i].attackDir.normalized;
                    if (bodyTrans.localScale.x < 0)
                    {
                        attackDir.x = -attackDir.x;
                    }
                    attackTriggers[i].force = attackDir * attack1Infos[i].force;
                }
                break;
            case AttackType.Shoot:
                break;
            default:
                break;
        }
        ChangeState(CharacterState.Attack);
    }

    public virtual void Attack2()
    {
        Vector3 leftDir = GetMoveDir();
        if (leftDir.x > 0.3f)
        {
            if (bodyTrans.localScale.x > 0)
            {
                Turn();
            }
        }
        else if (leftDir.x < -0.3f)
        {
            if (bodyTrans.localScale.x < 0)
            {
                Turn();
            }
        }

        ani.Play("attack2", 0, 0);
        aniCollider.Play("Attack2", 1, 0);
        attackTime = totalAttack2Time;
        switch (attackType)
        {
            case AttackType.Melee:
                for (int i = 0; i < attack2Infos.Count; i++)
                {
                    attackTriggers[i].damage = attack2Infos[i].damage;
                    attackTriggers[i].changeHurt = attack2Infos[i].changeHurt;
                    attackTriggers[i].repelValue = attack2Infos[i].repelValue;
                    Vector3 attackDir = attack2Infos[i].attackDir.normalized;
                    if (bodyTrans.localScale.x < 0)
                    {
                        attackDir.x = -attackDir.x;
                    }
                    attackTriggers[i].force = attackDir * attack2Infos[i].force;
                }
                break;
            case AttackType.Shoot:
                break;
            default:
                break;
        }
        ChangeState(CharacterState.Attack);
    }

    public void SetSortingOrder(int order)
    {
        meshRenderer.sortingOrder = order;
    }
}
