using System.Collections;
using Unity.Mathematics;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.InputSystem;

public class RottaMovement : MonoBehaviour
{
    //default movement speed on the ground
    public float movementSpeed = 1000f;
    //basically a factor for how much the player has control over air movement
    public float airSpeedModifier = 2f;
    private Camera gameCam;

    //jump force
    public float jumpHeight = 30f;
    public float bubbleJumpHeight = 35f;

    //cooldown between succefull jumps
    public float jumpCooldown = 1f;
    Vector3 clickPoint;

    //public GameObject testPrefab;

    private bool airBorne = false; // if in the air
    private bool canJump = true; // if jump is off cooldown
    //current movement speed in air, gets reset on collision, and set based on initial velocity on jumping
    private float airSpeed;
    private float moveHorizontal;

    private bool touchingBubble = false;

    //things for the new unity input system, ask miika for info if needed (i.e once we get more player action binds)
    //should be easy and simple now, just slightly diff
    InputAction moveAction;
    InputAction jumpAction;

    private Rigidbody2D rb;

    // Sprite rendering and animations
    private Animator animator;
    private SpriteRenderer spriteRenderer;

    //Audio Clips
    public AudioSource ratSource;
    public AudioClip Jump;
    public AudioClip Squeek;
    //public AudioClip Bubble;


    //reference for spawning in squeak bubbles
    private Squeak squeak;

    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        ratSource = GetComponent<AudioSource>();

        squeak = gameObject.GetComponent<Squeak>();
        rb = GetComponent<Rigidbody2D>();
        gameCam = Camera.main;

        // Animation components
        animator = GetComponent<Animator>();
        spriteRenderer = GetComponent<SpriteRenderer>();

        //definitions for the input system
        moveAction = InputSystem.actions.FindAction("Move");
        jumpAction = InputSystem.actions.FindAction("Jump");
    }
    void FixedUpdate()
    {
        //check current movement input
        moveHorizontal = moveAction.ReadValue<float>();
        //basically if we are sending any movement input
        if (moveHorizontal != 0)
        {
            //Debug.Log(moveHorizontal);
            if (airBorne)
            {
                //handles the smooth and slowed air control.
                //basically the math here is that every fixedUpdate cycle we take the initial speed V1, add to it a reduced version of what the ground movement would be,
                //and clamp it so its within normal playerSpeed bounds (so player cant do any tricky bullshit)
                //V0 + groundSpeed*airSpeed*TimeBetweenframes, clamped
                //so essentially the rate of accelaration is groundSpeed*airSpeed
                airSpeed = Mathf.Clamp(airSpeed + (moveHorizontal*movementSpeed*airSpeedModifier*Time.fixedDeltaTime), -movementSpeed, movementSpeed);
                // applies movement based on air speed
                rb.linearVelocity = new Vector2((airSpeed)*Time.fixedDeltaTime , rb.linearVelocity.y);

                // When airborne stop run anim and "not touching bubble"
                animator.SetBool("Run", false);
                touchingBubble = false;
            }
            else
            {
                //normal ground movement
                rb.linearVelocity = new Vector2(moveHorizontal * movementSpeed * Time.fixedDeltaTime, rb.linearVelocity.y);

                // When moving play run anim
                animator.SetBool("Run", true);

                // Flip sprite according to movement
                if(moveHorizontal == -1)
                {
                    spriteRenderer.flipX = true;
                }
                else if (moveHorizontal == 1)
                {
                    spriteRenderer.flipX = false;
                }
            }
        }
        if (moveHorizontal == 0 && !airBorne)
        {
            //snaps things to standing still more rapidly on ground
            rb.linearVelocity = new Vector2(0f, rb.linearVelocity.y);

            // When idle stop run anim
            animator.SetBool("Run", false);
        }

        if (jumpAction.IsPressed() && canJump == true && !airBorne)
        {
            //Debug.Log("Anim start");

            // When jumping stop run anim
            animator.SetBool("Run", false);

            if (!touchingBubble)
            {
                // Base jump anim
                animator.SetTrigger("Jump");

                //save current movement speed for use with air movement
                airSpeed = moveHorizontal * movementSpeed;

                //jump impulse
                rb.AddForce(new Vector2(0, jumpHeight), ForceMode2D.Impulse);

                //start jump cooldown
                StartCoroutine(JumpCoolDown());
            }
            if (touchingBubble)
            {
                // When touching bubble play jump flip anim
                touchingBubble = true;
                animator.SetTrigger("JumpOnBubble");

                //save current movement speed for use with air movement
                airSpeed = moveHorizontal * movementSpeed;

                //jump impulse
                rb.AddForce(new Vector2(0, bubbleJumpHeight), ForceMode2D.Impulse);

                //start jump cooldown
                StartCoroutine(JumpCoolDown());
            }
        }
    }
    IEnumerator JumpCoolDown()
    {
        canJump = false;
        ratSource.PlayOneShot(Jump);
        yield return new WaitForSeconds(jumpCooldown);
        canJump = true;
    }

    private void OnCollisionStay2D(Collision2D collision)
    {
        airSpeed = 0f;
        //reset airspeed on collision,only reset jump if collided with ground
        //should probably be switched to be triggers, but works fine for rihght now
        //so this requires a separate collision object on ground as opposed to wall, whereas with a trigger you could just have the triggerbox on places whare ground.
        if (collision.gameObject.CompareTag("ground"))
        {
            //check if the collsion is happening with a game object with "ground" tag.
            airBorne = false;
            //Debug.Log("airborne false");
            animator.SetBool("TouchingGround", true);
        }
        else if (collision.gameObject.CompareTag("Bubble"))
        {
            //check if the collsion is happening with a game object with "ground" tag.
            // When touching bubble allow for flip jump
            airBorne = false;
            animator.SetBool("TouchingGround", true);
            animator.SetBool("TouchingBubble", true);
            touchingBubble = true;
        }
    }
    private void OnCollisionExit2D(Collision2D collision)
    {
        airSpeed = rb.linearVelocityX;
        if (collision.gameObject.CompareTag("ground"))
        {
            //check if the collsion is happening with a game object with "ground" tag.
            airBorne = true;
            animator.SetBool("TouchingGround", false);
        }
        else if (collision.gameObject.CompareTag("Bubble"))
        {
            //check if the collsion is happening with a game object with "ground" tag.
            airBorne = true;
            animator.SetBool("TouchingGround", false);
            animator.SetBool("TouchingBubble", false);
        }
    }
    //playeril tarvii olla playerInput componentti joka hookkaa sitten bubble actioniin input systeemistä.
    public void OnScreenTap(InputAction.CallbackContext context)
    {
        if (context.started)
        {
            Debug.Log("TÄP");
            //tapPoint on klikkauksen screen koordinaatit
            var TapPoint = context.ReadValue<Vector2>();
            ratSource.PlayOneShot(Squeek);

            //clickPoint on piste pelin planella
            clickPoint = gameCam.ScreenToWorldPoint(new Vector3(TapPoint.x, TapPoint.y, 10));

            //spawnaa testiympyrä pisteeseen
            //Instantiate(testPrefab, clickPoint, quaternion.identity);
            Debug.Log(TapPoint);
            squeak.spawnBubble(clickPoint);
        }

    }
    //for test purposes

}
