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

public class Demonic : MoveCharacter
{
    public int id;
    public float costMp = 10;
    public float totalSummonTime = 0.5f;
    public SearchState searchState;
    public float attackDistance;
    public float maxAttackDis, minAttackDis;
    public bool needToChange;
    public bool canFly = false;
    public float flyHeight;
    public float flyUpSpeed = 10;
    public int sortingOrder = 0;

    public int playerID;
    public bool hasEffect = false;

    private void Awake()
    {
        
    }

    private void Start()
    {
        if (needToChange)
        {
            attackDistance = Random.Range(minAttackDis, maxAttackDis);
        }
    }

    private void OnDisable()
    {
        PlayersInput.instance[playerID].OnDemonicRecycle(this);
    }

    public override void FixedUpdate()
    {
        if (!isNonAttack)
        {
            OnSearchState();
        }
        OnState();
    }

    public bool SearchTarget()
    {
        targetCharacter = searchTrigger.GetMinDisTarget(targetTypes, canHitFly);
        if (targetCharacter != null)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    public void ChangeSearchState(SearchState newState)
    {
        switch (searchState)
        {
            case SearchState.NoTarget:
                break;
            case SearchState.InSearchScope:
                break;
            case SearchState.InAttackScope:
                break;
            default:
                break;
        }
        searchState = newState;
        switch (searchState)
        {
            case SearchState.NoTarget:
                targetCharacter = null;
                break;
            case SearchState.InSearchScope:
                break;
            case SearchState.InAttackScope:
                break;
            default:
                break;
        }
    }

    public void OnSearchState()
    {
        switch (searchState)
        {
            case SearchState.NoTarget:
                if (SearchTarget())
                {
                    ChangeSearchState(SearchState.InSearchScope);
                    break;
                }
                //向玩家基地移动
                break;
            case SearchState.InSearchScope:
                if (!SearchTarget())
                {
                    targetCharacter = null;
                    ChangeSearchState(SearchState.NoTarget);
                    break;
                }
                if (targetCharacter != null && Mathf.Abs(targetCharacter.transform.position.x - transform.position.x) <= attackDistance)
                {
                    ChangeSearchState(SearchState.InAttackScope);
                    break;
                }
                break;
            case SearchState.InAttackScope:
                if (targetCharacter != null)
                {
                    if (!targetCharacter.gameObject.activeInHierarchy || targetCharacter.isDie
                        || Mathf.Abs(targetCharacter.transform.position.x - transform.position.x) > attackDistance)
                    {
                        ChangeSearchState(SearchState.NoTarget);
                    }
                }
                else
                {
                    ChangeSearchState(SearchState.NoTarget);
                }
                break;
            default:
                break;
        }
    }

    public override Vector3 GetMoveDir()
    {
        Vector3 moveDir = Vector3.zero;
        if (canMove)
        {
            switch (searchState)
            {
                case SearchState.NoTarget:
                    //if (PlayerController.instance.bodyTrans.localScale.x > 0)
                    //{
                    //    moveDir = Vector3.left;
                    //}
                    //else
                    //{
                    //    moveDir = Vector3.right;
                    //}
                    moveDir = Vector3.left;
                    break;
                case SearchState.InSearchScope:
                    if (targetCharacter)
                    {
                        if (targetCharacter.transform.position.x - transform.position.x < 0)
                        {
                            moveDir = Vector3.left;
                        }
                        else
                        {
                            moveDir = Vector3.right;
                        }
                    }
                    else
                    {
                        moveDir = Vector3.zero;
                    }
                    break;
                case SearchState.InAttackScope:
                    if (targetCharacter)
                    {
                        if (targetCharacter.transform.position.x - transform.position.x < 0)
                        {
                            moveDir = Vector3.left;
                        }
                        else
                        {
                            moveDir = Vector3.right;
                        }
                    }
                    else
                    {
                        moveDir = Vector3.zero;
                    }
                    break;
                default:
                    break;
            }
        }
        return moveDir;
    }

    public bool GetAttack()
    {
        if (searchState == SearchState.InAttackScope)
        {
            return true;
        }
        return false;
    }

    public void AdjustHeight()
    {
        if (canFly)
        {
            if (transform.position.y - flyHeight > 0.1f)
            {
                Vector3 pos = transform.position;
                pos.y -= flyUpSpeed * Time.deltaTime;
                transform.position = pos;
            }
            else if (transform.position.y - flyHeight < -0.1f)
            {
                Vector3 pos = transform.position;
                pos.y += flyUpSpeed * Time.deltaTime;
                transform.position = pos;
            }
        }
    }

    public override void OnState()
    {
        base.OnState();
        hurtKeepTime -= Time.deltaTime;
        attackTime -= Time.deltaTime;
        dieKeepTime -= Time.deltaTime;
        invincibleTime -= Time.deltaTime;
        weakTime -= Time.deltaTime;
        Vector3 leftDir = GetMoveDir();
        bool isAttack = GetAttack();
        
        switch (state)
        {
            case CharacterState.Idle:
                if (isAttack)
                {
                    Attack2();
                    break;
                }
                if (!foot.TrigGround && !canFly)
                {
                    if (rb.velocity.y > 0)
                    {
                        ChangeState(CharacterState.Rise);
                        break;
                    }
                    else
                    {
                        ChangeState(CharacterState.Fall);
                        break;
                    }
                }
                if (leftDir.x > 0.3f || leftDir.x < -0.3f)
                {
                    ChangeState(CharacterState.Run);
                    break;
                }
                AdjustHeight();
                //rb.velocity = Vector3.zero;
                break;
            case CharacterState.Run:
                if (isAttack)
                {
                    Attack2();
                    break;
                }
                if (!foot.TrigGround && !canFly)
                {
                    if (rb.velocity.y > 0)
                    {
                        ChangeState(CharacterState.Rise);
                        break;
                    }
                    else
                    {
                        ChangeState(CharacterState.Fall);
                        break;
                    }
                }
                if (leftDir.x < 0.3f && leftDir.x > -0.3f)
                {
                    ChangeState(CharacterState.Idle);
                    break;
                }
                if (leftDir.x > 0.3f)
                {
                    //rb.velocity += Vector3.right * moveAcc * Time.deltaTime;
                    rb.velocity = Vector3.right * moveSpeed;
                    //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 * moveSpeed;
                    //if (rb.velocity.x < -maxMoveSpeed)
                    //{
                    //    rb.velocity = new Vector3(-maxMoveSpeed, rb.velocity.y, rb.velocity.z);
                    //}
                    if (bodyTrans.localScale.x < 0)
                    {
                        Turn();
                    }
                }
                AdjustHeight();
                break;
            case CharacterState.Rise:
                if (rb.velocity.y <= 0)
                {
                    ChangeState(CharacterState.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 CharacterState.Fall:
                if (foot.TrigGround || canFly)
                {
                    ChangeState(CharacterState.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 CharacterState.Hurt:
                if (hurtKeepTime <= 0 && rb.velocity.magnitude < hurtChangeVelocity)
                {
                    ChangeState(CharacterState.Idle);
                    break;
                }
                if (!foot.TrigGround)
                {
                    rb.velocity += Vector3.up * extraFallGravity * Time.deltaTime;
                }
                Vector3 vel = rb.velocity;
                vel.x = vel.x * (1 - decelerationRatio * Time.deltaTime);
                rb.velocity = vel;
                break;
            case CharacterState.Coma:
                break;
            case CharacterState.Attack:
                if (attackTime <= 0)
                {
                    ChangeState(CharacterState.Idle);
                    break;
                }
                break;
            case CharacterState.Die:
                if (dieKeepTime <= 0)
                {
                    print("Die:" + gameObject.name);
                    gameObject.SetActive(false);
                    break;
                }
                break;
            case CharacterState.Weak:
                if (weakTime <= 0)
                {
                    ChangeState(CharacterState.Idle);
                    break;
                }
                break;
            default:
                break;
        }
    }

    public override void ChangeState(CharacterState newState)
    {
        if(state == newState)
        {
            return;
        }
        switch (state)
        {
            case CharacterState.Idle:
                break;
            case CharacterState.Run:
                rb.velocity = Vector3.zero;
                break;
            case CharacterState.Rise:
                break;
            case CharacterState.Fall:
                rb.velocity = Vector3.zero;
                break;
            case CharacterState.Hurt:
                break;
            case CharacterState.Coma:
                foreach(GameObject i in HitCols)
                {
                    i.SetActive(true);
                }
                break;
            case CharacterState.Attack:
                aniCollider.Play("NotAttack", 1, 0);
                break;
            case CharacterState.Die:
                isDie = false;
                break;
            case CharacterState.Weak:
                if (canFly)
                {
                    rb.constraints += 4; //RigidbodyConstraints.FreezePositionY = 4，不能直接加
                }
                break;
            default:
                break;
        }
        CharacterState oldState = state;
        state = newState;
        switch (newState)
        {
            case CharacterState.Idle:
                ani.Play("idle", 0, 0);
                aniCollider.Play("Idle", 0, 0);
                rb.velocity = Vector3.zero;
                //animalAni.SetInteger("state", (int)PlayerState.Idle);
                break;
            case CharacterState.Run:
                ani.Play("walk", 0, 0);
                aniCollider.Play("Walk", 0, 0);
                //animalAni.SetInteger("state", (int)PlayerState.Walk);
                break;
            case CharacterState.Rise:
                aniCollider.Play("Rise", 0, 0);
                break;
            case CharacterState.Fall:
                ani.Play("fall", 0, 0);
                aniCollider.Play("Fall", 0, 0);
                //animalAni.SetInteger("state", (int)PlayerState.Fall);
                break;
            case CharacterState.Hurt:
                ani.Play("hitted", 0, 0);
                aniCollider.Play("Hurt", 0, 0);
                invincibleTime = totalInvincibleTime;
                hurtKeepTime = minHurtKeepTime;
                //ani.Play("Invincible", 2, 0);
                break;
            case CharacterState.Coma:
                //ani.Play("Coma", 0, 0);
                ani.Play("idle", 0, 0);
                aniCollider.Play("Idle", 0, 0);
                foreach (GameObject i in HitCols)
                {
                    i.SetActive(false);
                }
                rb.velocity = Vector3.zero;
                break;
            case CharacterState.Attack:
                break;
            case CharacterState.Die:
                ani.Play("die", 0, 0);
                aniCollider.Play("Die", 0, 0);
                isDie = true;
                dieKeepTime = totalDieKeepTime;
                //接尸体存入动效
                //友方死亡后计入尸体
                PlayersInput.instance[playerID].corpses++;
                //print(PlayersInput.instance[0].corpses);
                break;
            case CharacterState.Weak:
                aniCollider.Play("Weak", 0, 0);
                ani.Play("weak", 0, 0);
                Vector3 velocity = rb.velocity;
                velocity.y = weakUpSpeed;
                rb.velocity = velocity;
                weakTime = totalWeakTime;
                if (canFly)
                {
                    rb.constraints -= RigidbodyConstraints.FreezePositionY;
                }
                break;
            default:
                break;
        }
    }

    public override void Attack1()
    {
        base.Attack1();
        Vector3 moveDir;
        if (PlayersInput.instance[playerID].bodyTrans.localScale.x > 0)
        {
            moveDir = Vector3.left;
        }
        else
        {
            moveDir = Vector3.right;
        }
        if (moveDir.x > 0.3f)
        {
            if (bodyTrans.localScale.x > 0)
            {
                Turn();
            }
        }
        else if (moveDir.x < -0.3f)
        {
            if (bodyTrans.localScale.x < 0)
            {
                Turn();
            }
        }
        invincibleTime = totalAttack1Time;
        attackTarget = targetCharacter;
    }

    public override void Attack2()
    {
        base.Attack2();
        attackTarget = targetCharacter;
    }

}
