using Unity.Mathematics;
using UnityEngine;

public class HaseBewegung : MonoBehaviour
{
    const float MAX_HINTERLAUF_ANGLE = 10;
    const float HINTERLAUF_TIME = 1;
    public float jumpVelocityX;
    public float maxJumpVelocityY;
    public float waitingTimeBetweenJumps;
    public float earRigidity;
    public GameObject hinterlauf;
    public GameObject loeffel;
    public GameObject kopf;

    private float xTarget;
    private uint collisions;
    private float nextJumpTime;
    private bool lookingRight;
    private float jumpStartTime;

    private Rigidbody2D rigidBody;
    public void GoToXPosition(float x){
        xTarget = x;
    }

    public void Turn(){
        GetComponent<SpriteRenderer>().flipX = lookingRight;
        loeffel.GetComponent<SpriteRenderer>().flipX = lookingRight;
        hinterlauf.GetComponent<SpriteRenderer>().flipX = lookingRight;
        kopf.GetComponent<SpriteRenderer>().flipX = lookingRight;
        lookingRight = !lookingRight;
        Vector3 v = loeffel.transform.localPosition;
        v.x = -v.x;
        loeffel.transform.localPosition = v;
        v = hinterlauf.transform.localPosition;
        v.x = -v.x;
        hinterlauf.transform.localPosition = v;
        v = kopf.transform.localPosition;
        v.x = -v.x;
        kopf.transform.localPosition = v;
        loeffel.transform.localRotation = Quaternion.Inverse(loeffel.transform.localRotation);
        hinterlauf.transform.localRotation = Quaternion.Inverse(hinterlauf.transform.localRotation);
        kopf.transform.localRotation = Quaternion.Inverse(kopf.transform.localRotation);
        transform.rotation = Quaternion.Inverse(transform.rotation);
    }

    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        rigidBody = GetComponent<Rigidbody2D>();
        collisions = 0;
        lookingRight = true;
        nextJumpTime = 0f;
        jumpStartTime = 0;
    }

    // Update is called once per frame
    void Update()
    {
        if (!targetReached()) {
            if (collisions > 0){
                if (Time.time > nextJumpTime){
                    StartJump();
                    nextJumpTime = 0;
                } else if (nextJumpTime == 0){
                    nextJumpTime = Time.time + waitingTimeBetweenJumps;
                    rigidBody.linearVelocityX = 0;
                }
            }
        } else {
            rigidBody.linearVelocityX = 0;
            rigidBody.linearVelocityY = math.min(rigidBody.linearVelocityY, 0f);
        }
        float earAngle = math.acos(earRigidity / rigidBody.linearVelocityX) / math.PIHALF * 50;
        loeffel.transform.localRotation = Quaternion.AngleAxis(earAngle, Vector3.forward);
        float timeFactor = (Time.time - jumpStartTime) / HINTERLAUF_TIME;
        if (timeFactor < .5f){
            hinterlauf.transform.localRotation = Quaternion.AngleAxis(MAX_HINTERLAUF_ANGLE * timeFactor * 2, Vector3.forward);
        } else if (timeFactor < 1.0f){
            hinterlauf.transform.localRotation = Quaternion.AngleAxis(MAX_HINTERLAUF_ANGLE * (1 - timeFactor) * 2, Vector3.forward);
        } else {
            hinterlauf.transform.localRotation = Quaternion.identity;
        }
    }

    void OnCollisionEnter2D(Collision2D collision){
        if (collision.gameObject.layer == 7){ //That layer is the ground.
            if (collisions == 0){
                rigidBody.linearVelocityX = 0;
            }
            collisions++;
        }
    }

    void OnCollisionExit2D(Collision2D collision){
        if (collision.gameObject.layer == 7){ //That layer is the ground.
            collisions--;
        }
    }

    private void StartJump(){
        rigidBody.linearVelocityX = jumpVelocityX;
        rigidBody.linearVelocityY = maxJumpVelocityY;
        jumpStartTime = Time.time;
    }

    private bool targetReached(){
        return (lookingRight && transform.position.x >= xTarget) || (!lookingRight && transform.position.x <= xTarget);
    }
}
