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

public class Tutorial_GrapplingRope : MonoBehaviour {

    [Header("General References:")]
    public Tutorial_GrapplingGun grapplingGun;
    public LineRenderer m_lineRenderer;

    [Header("General Settings:")]
    [SerializeField] private int precision = 40;
    [Range(0, 20)] private float straightenLineSpeed = 5;

    [Header("Rope Animation Settings:")]
    public AnimationCurve ropeAnimationCurve;
    [Range(0.1f, 4)] [SerializeField] private float startWaveSize = 2;
    float waveSize = 0;

    [Header("Rope Progression:")]
    public AnimationCurve ropeProgressionCurve;
    [SerializeField] [Range(1,50)] private float ropeProgressionSpeed = 1;

    float moveTime = 0;

    [HideInInspector] public bool isGrappling = true;
    bool straightLine = false;
    
    [Header("Spider")]
    bool hasPlayedThwip = false;
    [SerializeField] GameObject sirJacques;


    private void OnEnable() {
        // print("on enabled called");
        moveTime = 0;
        m_lineRenderer.positionCount = precision;
        waveSize = startWaveSize;
        straightLine = false;

        LinePointsToFirePoint();

        m_lineRenderer.enabled = true;
        sirJacques.SetActive(true);
    }

    private void OnDisable() {
        // print("on disabled called");
        m_lineRenderer.enabled = false;
        isGrappling = false;
        hasPlayedThwip = false;
        sirJacques.SetActive(false);
    }

    private void LinePointsToFirePoint() {
        sirJacques.transform.position = grapplingGun.firePoint.position;
        for (int i = 0; i < precision; i++) {
            m_lineRenderer.SetPosition(i, grapplingGun.firePoint.position);
        }
    }

    void Update() {
        moveTime += Time.deltaTime;
        if (!hasPlayedThwip) {
            this.gameObject.GetComponent<AudioSource>().Play();
            hasPlayedThwip = true;
        }
        DrawRope();
    }

    void DrawRope() {
        // print("drawing");
        // print("isGrappling: " + isGrappling);
        if (!straightLine) {
            // float roundedLinePos = Mathf.Round(m_lineRenderer.GetPosition(precision - 1).x * 100.0f) * .01f;
            // float roundedGrapplePos = Mathf.Round(m_lineRenderer.GetPosition(precision - 1).x * 100.0f) * .01f;
            // // print(roundedLinePos + " / " + roundedGrapplePos);
            // if (roundedLinePos == roundedGrapplePos) {
            if (m_lineRenderer.GetPosition(precision - 1).x == grapplingGun.grapplePoint.x) {
                straightLine = true;
            } else {
                DrawRopeWaves();
            }
        } else {
            if (!isGrappling) {
                grapplingGun.Grapple();
                isGrappling = true;
            }
            if (waveSize > 0) {
                waveSize -= Time.deltaTime * straightenLineSpeed;
                DrawRopeWaves();
            } else {
                waveSize = 0;
                if (m_lineRenderer.positionCount != 2) {
                    m_lineRenderer.positionCount = 2;
                }
                DrawRopeNoWaves();
            }
        }
    }

    void DrawRopeWaves() {
        // print(moveTime);
        for (int i = 0; i < precision; i++) {
            float delta = (float)i / ((float)precision - 1f);
            Vector2 offset = Vector2.Perpendicular(grapplingGun.grappleDistanceVector).normalized * ropeAnimationCurve.Evaluate(delta) * waveSize;
            Vector2 targetPosition = Vector2.Lerp(grapplingGun.firePoint.position, grapplingGun.grapplePoint, delta) + offset;
            Vector2 currentPosition = Vector2.Lerp(grapplingGun.firePoint.position, targetPosition, ropeProgressionCurve.Evaluate(moveTime) * ropeProgressionSpeed);

            sirJacques.transform.position = currentPosition;
            m_lineRenderer.SetPosition(i, currentPosition);
        }
    }

    void DrawRopeNoWaves() {
        sirJacques.transform.position = grapplingGun.grapplePoint;
        m_lineRenderer.SetPosition(0, grapplingGun.firePoint.position);
        m_lineRenderer.SetPosition(1, grapplingGun.grapplePoint);
    }
}
