using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;

public class PlayerBehavior : MonoBehaviour
{
    [Header("Physics:")]
    private float _hInput;
    private Rigidbody2D _rb;
    private int forward = 1;
    public PlayerInput playerInput;

    [Header("Tambourine:")]
    [SerializeField] private Launch launcher;
    [HideInInspector] public bool hasTambourine = true;
    GameObject tambourine;
    bool unlockedTambourine;

    [Header("Clarinet:")]
    bool unlockedClarinet;
    public bool isDash = false;
    public float bonk = 2f;
    private Vector2 saveVelocity;
    public bool isInWater = false;
    //dont know if gravity matters
    public float dashForce = 1.2f;
    private float dashTime = 1.0f;
    private float dashInc = 0.1f;
    private float currentDash = 0.0f;
    Vector2 dashVec;
    private bool lowSpeed = false;

    [Header("Grappling:")]
    [SerializeField] public Tutorial_GrapplingGun grapplingGun;
    [SerializeField] public Tutorial_GrapplingRope grapplingRope;
    private GameObject grappleSurface;

    [Header("Controllers:")]
    [SerializeField] private PlayerMovement playerController;
    private GameUIController gameUI;

    Animator animator;
    [HideInInspector] public bool playerIsAlive = true;

    [Header("Sound")]
    [SerializeField] public AudioClip footstepSound;
    [SerializeField] public AudioClip deathSound;
    AudioSource audioSource;


    void Awake()
    {  // initialize
        _rb = GetComponent<Rigidbody2D>();

        gameUI = GameObject.FindGameObjectWithTag("GameUICanvas").GetComponent<GameUIController>();

        audioSource = this.gameObject.GetComponent<AudioSource>();
        audioSource.clip = footstepSound;
        audioSource.loop = true;

        animator = this.gameObject.GetComponent<Animator>();
        GameObject.Find("Main Camera").GetComponent<CameraMovement>().player = this.gameObject;
        playerIsAlive = true;
    }

    void Start()
    {
        gameUI.UpdateInstrumentUI();
        currentDash = dashTime;
    }

    void Update()
    {
        unlockedTambourine = StateController.Instance.HasTambourine();
        if (playerIsAlive)
        {
            // throw tambourine
            if (playerInput.actions["ThrowTambourine"].WasPressedThisFrame())
            {
                ThrowTambourine();
            }

            // grapple
            tambourine = GameObject.FindGameObjectWithTag("tambourine");
            if (playerInput.actions["Grapple"].WasPressedThisFrame())
            {
                AttemptGrapple();
            }
            if (playerInput.actions["Grapple"].WasReleasedThisFrame() && grapplingRope.isGrappling)
            {
                LetGoOfGrapple();
            }

            Animate();
        }

        unlockedClarinet = StateController.Instance.HasClarinet();
        if (playerIsAlive && unlockedClarinet)
        {
            if (playerInput.actions["ClarinetDive"].WasPressedThisFrame())
            {
                isDash = true;
                playerInput.DeactivateInput();
                currentDash = 0.0f;
                // set so if in water dash will still be true
                // otherwise turn dash off 
            }
            if (!playerController.IsGrounded() && isDash && (currentDash < dashTime))
            {
                if (forward == 1)
                {
                    dashVec = new Vector2(1f, -1f) * dashForce;
                    _rb.AddForce(dashVec, ForceMode2D.Impulse);
                }
                else
                {
                    dashVec = new Vector2(-1f, -1f) * dashForce;
                    _rb.AddForce(dashVec, ForceMode2D.Impulse);
                }
                currentDash += dashInc;
            }
            else if (!isInWater)
            {
                isDash = false;
                currentDash = 0.0f;
                _rb.AddForce(-(dashVec), ForceMode2D.Impulse);
                dashVec = Vector2.zero;
                playerInput.ActivateInput();
            }
            else
            {
                currentDash = 0.0f;
                dashVec = Vector2.zero;
            }
        }
    }

    void Animate()
    {
        // start walking
        if (playerInput.actions["Move"].WasPressedThisFrame())
        {
            animator.SetBool("Walking", true);
        }
        // return to idle animation
        if (playerInput.actions["Move"].WasReleasedThisFrame())
        {
            animator.SetBool("Walking", false);
        }
    }

    void OnMove(InputValue value)
    {
        if (playerIsAlive)
        {
            _hInput = value.Get<Vector2>().x;
            if (_hInput < 0)
            {
                if (forward != -1)
                { // if character hasnt already flipped 
                    FlipRenderer();
                }
                forward = -1;
            }
            else if (_hInput > 0)
            {
                if (forward != 1)
                { // if character hasnt already flipped 
                    FlipRenderer();
                }
                forward = 1;
            }
        }

    }

    void FlipScale()
    { // DOENST WORK RIGHT (that's so sad for you)
        Vector3 currentScale = this.gameObject.transform.localScale;
        currentScale.x *= -1;
        this.gameObject.transform.localScale = currentScale;
    }

    void FlipRenderer()
    {
        GetComponent<SpriteRenderer>().flipX = !GetComponent<SpriteRenderer>().flipX;
    }

    void ThrowTambourine()
    {
        if (unlockedTambourine && hasTambourine && !grapplingRope.isGrappling)
        {
            launcher.ThrowTambourine(forward);
            SetHasTambourine(false);
        }
    }

    public void SetHasTambourine(bool state)
    {
        hasTambourine = state;
        gameUI.ToggleTambourine(state);
    }

    void AttemptGrapple()
    {
        if (tambourine != null)
        { // grapple to tambourine
            if (!grapplingRope.isGrappling && tambourine.GetComponent<TambourineBehavior>().pinned)
            {
                grapplingGun.GrappleToTambourine(tambourine);
                grapplingRope.isGrappling = true;
            }
        }
        else
        {
            if (grappleSurface != null)
            {
                grapplingGun.GrappleToSurface(grappleSurface.transform.position);
                grapplingRope.isGrappling = true;
            }
        }
    }

    void LetGoOfGrapple()
    {
        bool currentlyPaused = StateController.Instance.isPaused;
        if (grapplingRope.isGrappling && !currentlyPaused)
        {
            print("currently paused is " + currentlyPaused + ", releasing grapple");
            if (tambourine != null)
            {
                tambourine.GetComponent<TambourineBehavior>().DestroySelf();
            }
            grapplingGun.ReleaseGrapple();
        }
    }

    void Bounce()
    {
        Vector2 reflect;
        if(lowSpeed)
        {
            reflect = new Vector2(saveVelocity.x,-(saveVelocity.y) * 0.75f);
        }
        else
        {
            reflect = new Vector2(saveVelocity.x,-(saveVelocity.y) * bonk);
        }
        //reflect = new Vector2(saveVelocity.x,-(saveVelocity.y) * bonk);
        _rb.AddForce(reflect, ForceMode2D.Impulse);
        reflect = Vector2.zero;
        isDash = false;
    }

    void Water()
    {
        if (Mathf.Abs(_rb.velocity.y) < 2f)
        {
            lowSpeed = true;
            saveVelocity = Vector2.zero;
        }
        else
        {
            saveVelocity = _rb.velocity;
        }
    }

    void OnTriggerEnter2D(Collider2D col)
    {
        if (col.tag == "grappleSurface")
        {
            grappleSurface = col.gameObject;
        }
        else if (col.tag == "instaDeath")
        {
            print("player fell in spikes");
            StartCoroutine(DestroyPlayer());
        }
        else if (col.tag == "spawnPoint")
        {
            StateController.Instance.spawnPoint.GetComponent<SpawnPointBehavior>().DeactivateSpawnPoint();
            col.GetComponent<SpawnPointBehavior>().ActivateSpawnPoint();
        }
        else if (col.tag == "Trumpet")
        {
            this.playerController.in_range = true;
            this.playerController.enemy = col.transform.parent.gameObject;
        }
        else if (col.tag == "water")
        {
            isInWater = true;
            Water();
        }
    }

    void OnTriggerExit2D(Collider2D col)
    {
        if (col.tag == "grappleSurface")
        {
            grappleSurface = null;
        }
        else if (col.tag == "Trumpet")
        {
            this.playerController.in_range = false;
            this.playerController.enemy = null;
        }
        else if (col.tag == "water")
        {
            isInWater = false;
            isDash = false;
            playerInput.ActivateInput();
            saveVelocity = Vector2.zero;
        }
    }

    void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.tag == "Enemy" || collision.gameObject.tag == "ProjectileEnemy")
        {
            if (collision.transform.position.y < transform.position.y)
            {
                _rb.AddForce(Vector2.up * 8, ForceMode2D.Impulse);
                collision.gameObject.GetComponent<EnemyPatrol>().DefeatEnemy();
            }
            else
            {
                StartCoroutine(DestroyPlayer());
                print("enemy defeated player");
            }
        }
        else if (collision.gameObject.tag == "Projectile")
        {
            Destroy(collision.gameObject);
            StartCoroutine(DestroyPlayer());
        }
        //stupid stuff for claude's house
        else if (collision.gameObject.tag == "SirJacques")
        {
            Destroy(collision.gameObject);
        }
        else if (collision.gameObject.tag == "Door")
        {
            StateController.Instance.RespawnPlayer();
        }
        else if (collision.gameObject.tag == "bouncy")
        {
            Bounce();
        }
    }

    IEnumerator DestroyPlayer()
    {
        if (playerIsAlive)
        {
            print("destroyPlayer called");
            playerIsAlive = false;
            audioSource.clip = deathSound;
            audioSource.loop = false;
            audioSource.Play();
            playerInput.ActivateInput();

            // animate
            animator.Play("Die");
            // yield return new WaitForSeconds(animator.GetCurrentAnimatorStateInfo(0).length);
            yield return new WaitForSeconds(audioSource.clip.length);

            // this.stateController.SetDeathCanvasActive(true);

            if (grapplingRope.isGrappling) {
                LetGoOfGrapple();
            }

            // destroy all tambourines
            GameObject[] currentTambourines = GameObject.FindGameObjectsWithTag("tambourine");
            foreach (GameObject tambourine in currentTambourines)
            {
                tambourine.GetComponent<TambourineBehavior>().DestroySelf();
                // Destroy(tambourine);
            }

            StateController.Instance.RespawnPlayer();
        }
    }
}