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

public class MoveCharacter : Character
{
    public bool canMove = true;
    public Foot foot;

    public float extraRiseGravity = 0; //上升时额外重力加速度
    public float extraFallGravity = -10; //下落时额外重力加速度
    public float moveSpeed = 5;
    //[HideInInspector]
    public float beRepelValue;
    public float totalBeRepelValue;
    [HideInInspector]
    public float weakTime;
    public float totalWeakTime;
    public float weakUpSpeed = 10f;
    public float decelerationRatio = 1f;
    public float minHurtKeepTime = 0.2f;
    [HideInInspector]
    public float hurtKeepTime = 0;
    public float hurtChangeVelocity = 1;

    [Header("新增漂浮效果参数")]
    public float maxTime = 0; //上升最大耗时
    public float minTime = 6;  //上升最小耗时
    public float maxHeight = 12;    //最大上升高度
    public float minHeight = 7;    //最小上升高度

    public float maxRotateSpeed = 20;    //最大旋转速度
    public float minRotateSpeed = 5;    //最小旋转速度

    public float floatTime = 20;     //漂浮时间

    private float curTime;      //漂浮已进行时长
    private float height;       //漂浮高度
    private float riseTime;   //上升时间
    private float curHeight;    //当前所在高度
    private float rotateSpeed;  //旋转速度
    private float rotateDir;    //旋转方向
    private float backSpeed;    //往后退的速度

    private Vector3 origPos;     //初始位置
    private float origY;
    private float pastTime;     //上升已用时间
    private float rise = 1;
    private float down = -1;
    private Vector3 oneClockwise = new Vector3(0, 0, 1);
    private Vector3 oneCounterClockwise = new Vector3(0, 0, -1);

    public int floatState; //0:不漂浮；1:漂浮中；2:飘着；3:掉下去

    public GameObject spinee;
    public MeshRenderer mesh;
    public Material[] mats;
    public Material[] outlineMats;

    public SkeletonMecanim playerMe;
    public Animator playerAni;
    public Animator playerCol;
    public Transform playerTran;
    public BeSearchTrigger playerBst;
    public GameObject playerBullet;
    public SearchTrigger playerST;
    public Foot playerFoot;
    public GameObject playerSpinee;
    public MeshRenderer playerMesh;
    public Material[] playerMats;
    public Material[] playerOut;
    public bool isInvisible;

    private void Awake()
    {
        spinee = bodyTrans.GetChild(0).gameObject;
        mesh = spinee.GetComponent<MeshRenderer>();
        mats = mesh.materials;
        origY = transform.position.y;
    }

    private void Start()
    {
        playerMe = mecanim;
        playerAni = ani;
        playerCol = aniCollider;
        playerTran = bodyTrans;
        playerBst = beSearchTrigger;
        playerBullet = bulletPrefab;
        playerST = searchTrigger;
        playerFoot = foot;
        playerSpinee = spinee;
        playerMesh = mesh;
        playerMats = mats;
        playerOut = outlineMats;
    }

    private void ChangeMat(int state)
    {
        if (spinee == null || mesh == null || mats == null)
        {
            spinee = transform.GetChild(0).GetChild(0).gameObject;
            mesh = spinee.GetComponent<MeshRenderer>();
            mats = mesh.materials;
        }
        if (state == 0)
        {
            mesh.materials = outlineMats;
        }
        else
        {
            mesh.materials = mats;
        }
    }

    public void FloatStateOn()
    {
        if (canMove)
        {
            ChangeMat(0);
            curTime = 0;
            if (floatState == 0)
            {
                origPos = transform.position;
                curHeight = origPos.y;
            }
            origPos.x = transform.position.x;
            ChangeState(CharacterState.Rise);
            floatState = 1;
            riseTime = Random.Range(minTime, maxTime);
            backSpeed = Random.Range(1, 4);
            if (gameObject.tag == "Enemy" || gameObject.tag == "Player")
            {
                backSpeed = -backSpeed;
            }
            rotateSpeed = Random.Range(minRotateSpeed, maxRotateSpeed);
            rotateDir = (1.5f - Random.Range(1, 3)) * 2;
            height = Random.Range(minHeight, maxHeight);
        }
    }

    private void RotateSelf()
    {
        transform.localEulerAngles += new Vector3(0, 0, 1) * rotateDir * rotateSpeed * Time.deltaTime;
    }

    public void CharacterFloat()
    {
        if (floatState == 1)
        {
            RotateSelf();
            curTime += Time.deltaTime;
            aniCollider.Play("Rise", 0, 0);
            curHeight = Mathf.SmoothDamp(curHeight, height, ref rise, riseTime);
            transform.position = new Vector3(origPos.x, curHeight, origPos.z);
            if (curHeight >= height - 0.02f)
            {
                floatState = 2;
                pastTime = curTime;
                height = transform.position.y;
                ChangeState(CharacterState.Float);
            }
        }
        else if (floatState == 2)
        {
            RotateSelf();
            curTime += Time.deltaTime;
            transform.position = new Vector3(origPos.x + backSpeed * (curTime - pastTime), height, origPos.z);
            if (curTime >= floatTime)
            {
                transform.localEulerAngles = new Vector3(0, 0, 0);
                floatState = 3;
                origPos.x = transform.position.x;
                ChangeState(CharacterState.Fall);
            }
        }
        else if (floatState == 3)
        {
            aniCollider.Play("Fall", 0, 0);
            if (transform.position.y >= origY + 0.05f)
            {
                curHeight -= 10 * Time.deltaTime;
                transform.position = new Vector3(origPos.x, curHeight, origPos.z);
            }
            else if (foot.TrigGround || curHeight <= origY + 0.05f)
            {
                transform.position = origPos;
                ChangeState(CharacterState.Idle);
                ChangeMat(1);
                foreach (Material m in mats)
                {
                    m.SetInt("_Outline", 0);
                    floatState = 0;
                    if (gameObject.tag == "Player")
                    {
                        GetComponent<PlayerController>().soulCollector.enabled = true;
                    }
                }
            }
        }
    }


    public void Update()
    {
        if (beLarger)
        {
            Enlarge();
        }
        if (floatState != 0)
        {
            CharacterFloat();
        }
    }

    public override void BeHit(int damage, Vector3 force, bool changeHurt, float repelValue)
    {
        if (isInvisible)
        {
            return;
        }
        if (invincibleTime > 0)
        {
            return;
        }

        hp -= damage;
        uiHp.Show(hp, totalHp);
        if (hp <= 0)
        {
            
            ChangeState(CharacterState.Die);
            rb.AddForce(force);
            return;
        }
        else if (changeHurt && state == CharacterState.Weak)
        {
            ChangeState(CharacterState.Hurt);
            rb.AddForce(force);
            beRepelValue = totalBeRepelValue;
            return;
        }
        beRepelValue -= repelValue;
        if (changeHurt && beRepelValue <= 0)
        {
            ChangeState(CharacterState.Weak);
        }
    }
}
