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

public class Tutorial_GrapplingGun : MonoBehaviour {

    [Header("Scripts References:")]
    public Tutorial_GrapplingRope grappleRope;

    [Header("Main Camera:")]
    public Camera m_camera;

    [Header("Transform References:")]
    public Transform gunHolder;
    public Transform gunPivot;
    public Transform firePoint;

    [Header("Physics References:")]
    public SpringJoint2D m_springJoint2D;
    public DistanceJoint2D m_distanceJoint2D;
    public Rigidbody2D m_rigidBody2D;

    [Header("Rotation:")]
    [SerializeField] private bool rotateOverTime = true;
    [Range(0, 60)][SerializeField] private float rotationSpeed = 4;

    [Header("Distance:")]
    [SerializeField] private bool hasMaxDistance = false;
    [SerializeField] private float maxDistance = 20;

    private enum LaunchType {
        TransformLaunch,
        PhysicsLaunch
    }

    [Header("Launching:")]
    [SerializeField] private bool launchToPoint = true;
    [SerializeField] private LaunchType launchType = LaunchType.PhysicsLaunch;
    [SerializeField] private float launchSpeed = 1;

    [Header("No Launch To Point")]
    [SerializeField] private bool autoConfigureDistance = false;
    [SerializeField] private float targetDistance = 3;
    [SerializeField] private float targetFrequency = 1;

    [HideInInspector] public Vector2 grapplePoint;
    [HideInInspector] public Vector2 grappleDistanceVector;

    [HideInInspector] public bool inDistanceRange = false;


    void Start() {
        m_camera = GameObject.FindGameObjectWithTag("MainCamera").GetComponent<Camera>();
        grappleRope.enabled = false;
        m_springJoint2D.enabled = false;
        m_distanceJoint2D.distance = targetDistance + .5f;
        m_distanceJoint2D.enabled = false;
        inDistanceRange = false;
    }

    void Update() {
        // if (Input.GetKeyDown(KeyCode.Mouse0)) {
        //     SetGrapplePoint();
        // } else if (Input.GetKey(KeyCode.Mouse0)) {
        //     if (grappleRope.enabled) {
        //         RotateGun(grapplePoint, false);
        //     } else {
        //         Vector2 mousePos = m_camera.ScreenToWorldPoint(Input.mousePosition);
        //         RotateGun(mousePos, true);
        //     }

        //     if (launchToPoint && grappleRope.isGrappling) {
        //         if (launchType == LaunchType.TransformLaunch) {
        //             Vector2 firePointDistance = firePoint.position - gunHolder.localPosition;
        //             Vector2 targetPos = grapplePoint - firePointDistance;
        //             gunHolder.position = Vector2.Lerp(gunHolder.position, targetPos, Time.deltaTime * launchSpeed);
        //         }
        //     }
        // } else if (Input.GetKeyUp(KeyCode.Mouse0)) {
        //     ReleaseGrapple();
        // } else {
            Vector2 mousePos = m_camera.ScreenToWorldPoint(Mouse.current.position.ReadValue());
            RotateGun(mousePos, true);
        // }

        if (grappleRope.isGrappling && !inDistanceRange && Vector2.Distance(grapplePoint, new Vector2(m_rigidBody2D.transform.position.x, m_rigidBody2D.transform.position.y)) < targetDistance) {
            print(Vector2.Distance(grapplePoint, new Vector2(m_rigidBody2D.transform.position.x, m_rigidBody2D.transform.position.y)) + ", target: " + targetDistance);
            inDistanceRange = true;
        }
        if (inDistanceRange) {
            m_distanceJoint2D.enabled = true;
        }
    }

    void RotateGun(Vector3 lookPoint, bool allowRotationOverTime) {
        Vector3 distanceVector = lookPoint - gunPivot.position;
        float angle = Mathf.Atan2(distanceVector.y, distanceVector.x) * Mathf.Rad2Deg;

        if (rotateOverTime && allowRotationOverTime) {
            gunPivot.rotation = Quaternion.Lerp(gunPivot.rotation, Quaternion.AngleAxis(angle, Vector3.forward), Time.deltaTime * rotationSpeed);
        } else {
            gunPivot.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
        }

    }

    // void SetGrapplePoint() {
    //     Vector2 distanceVector = m_camera.ScreenToWorldPoint(Input.mousePosition) - gunPivot.position;
    //     // print("clicked" + m_camera.ScreenToWorldPoint(Input.mousePosition));
    //     // print("distance vector: " + distanceVector);

    //     if (Physics2D.Raycast(firePoint.position, distanceVector.normalized)) {
    //         RaycastHit2D _hit = Physics2D.Raycast(firePoint.position, distanceVector.normalized);
    //         print(_hit.transform.gameObject.name);
    //         if (_hit.transform.gameObject.layer == grappleLayerNumber || grappleToAll) {
    //             if (Vector2.Distance(_hit.point, firePoint.position) <= maxDistance || !hasMaxDistance) {
    //                 // print("gunPivot " + gunPivot.position + ", grappling to: " + _hit.point);
    //                 grapplePoint = _hit.point;
    //                 grappleDistanceVector = grapplePoint - (Vector2)gunPivot.position;
    //                 grappleRope.enabled = true;
    //             }
    //         }
    //     }
    // }

    public void Grapple() {
        print("grapple");
        m_springJoint2D.autoConfigureDistance = false;
        m_distanceJoint2D.autoConfigureDistance = false;

        if(!launchToPoint && !autoConfigureDistance) {
            m_springJoint2D.distance = targetDistance;
            print("Sprint Joint Distance:" + m_springJoint2D.distance);
            m_springJoint2D.frequency = targetFrequency;
        }
        if (!launchToPoint) {
            if (autoConfigureDistance) {
                m_springJoint2D.connectedAnchor = grapplePoint;
                m_springJoint2D.enabled = true;
                // print("Spring Joint Enabled");
                print("Sprint Joint Distance:" + m_springJoint2D.distance);

                m_distanceJoint2D.connectedAnchor = grapplePoint;
            }
        } else {
            switch (launchType) {
                case LaunchType.PhysicsLaunch:
                    m_springJoint2D.connectedAnchor = grapplePoint;
                    m_distanceJoint2D.connectedAnchor = grapplePoint;

                    Vector2 distanceVector = firePoint.position - gunHolder.position;

                    m_springJoint2D.distance = distanceVector.magnitude;
                    m_springJoint2D.frequency = launchSpeed;
                    m_springJoint2D.enabled = true;

                    // m_distanceJoint2D.maxDistanceOnly = false;
                    m_distanceJoint2D.distance = targetDistance + .5f;
                    break;
                case LaunchType.TransformLaunch:
                    m_rigidBody2D.gravityScale = 0;
                    m_rigidBody2D.velocity = Vector2.zero;
                    break;
            }
        }
    }

    public void GrappleToTambourine(GameObject tambourine) {
        grappleRope.enabled = true;

        grapplePoint = tambourine.transform.position;

        m_springJoint2D.autoConfigureDistance = false;
        m_distanceJoint2D.autoConfigureDistance = false;

        m_springJoint2D.frequency = targetFrequency;

        m_springJoint2D.connectedAnchor = grapplePoint;
        m_springJoint2D.enabled = true;
        // print("Spring Joint Enabled");

        m_distanceJoint2D.connectedAnchor = grapplePoint;
    }

    public void GrappleToSurface(Vector2 surfacePoint) {
        grappleRope.enabled = true;

        grapplePoint = surfacePoint;

        m_springJoint2D.autoConfigureDistance = false;
        m_distanceJoint2D.autoConfigureDistance = false;

        m_springJoint2D.frequency = targetFrequency;

        m_springJoint2D.connectedAnchor = grapplePoint;
        m_springJoint2D.enabled = true;
        // print("Spring Joint Enabled");

        m_distanceJoint2D.connectedAnchor = grapplePoint;
    }

    public void ReleaseGrapple() {
        grappleRope.enabled = false;
        m_springJoint2D.enabled = false;
        m_distanceJoint2D.enabled = false;
        inDistanceRange = false;
        m_rigidBody2D.gravityScale = 1;
        // print("disabled");
    }

    private void OnDrawGizmosSelected() {
        if (firePoint != null && hasMaxDistance) {
            Gizmos.color = Color.green;
            Gizmos.DrawWireSphere(firePoint.position, maxDistance);
        }
    }

}
