using System;
using System.Collections;
using Audio;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;

namespace Bow
{
    public class Arrow : XRGrabInteractable
    {
        public AudioClipGroup hitSounds;

        public float speed = 2000.0f;
        public Transform tip = null;

        private bool _inAir = false;
        private Vector3 _lastPosition = Vector3.zero;

        private Rigidbody _rigidbody = null;

        protected override void Awake()
        {
            base.Awake();
            _rigidbody = GetComponent<Rigidbody>();
        }

        private void FixedUpdate()
        {
            if (!_inAir) return;
            CheckForCollision();
            _lastPosition = tip.position;
        }

        private void CheckForCollision()
        {
            RaycastHit hit;
            if (Physics.Linecast(_lastPosition, tip.position, out hit, LayerMask.GetMask("Default"),
                QueryTriggerInteraction.Ignore))
            {
                hit.collider.gameObject.SendMessage("OnArrowHit", this,
                    SendMessageOptions.DontRequireReceiver);
                Stop();
                hitSounds.Play();
            }
        }

        private void Stop()
        {
            _inAir = false;
            SetPhysics(false);
        }

        public void Release(float pullValue)
        {
            _inAir = true;
            SetPhysics(true);

            MaskAndFire(pullValue);
            StartCoroutine(RotateWithVelocity());

            _lastPosition = tip.position;
        }

        private void SetPhysics(bool usePhysics)
        {
            _rigidbody.isKinematic = !usePhysics;
            _rigidbody.useGravity = usePhysics;
        }

        private void MaskAndFire(float power)
        {
            colliders[0].enabled = false;
            interactionLayerMask = 1 << LayerMask.NameToLayer("IgnoreInteraction");

            Vector3 force = transform.forward * (power * speed);

            _rigidbody.AddForce(force);
        }

        private IEnumerator RotateWithVelocity()
        {
            yield return new WaitForFixedUpdate();

            while (_inAir)
            {
                Quaternion newRotation = Quaternion.LookRotation(_rigidbody.velocity, transform.up);
                transform.rotation = newRotation;
                yield return null;
            }
        }

        public new void OnSelectEntered(XRBaseInteractor interactor)
        {
            base.OnSelectEntered(interactor);
        }

        public new void OnSelectExited(XRBaseInteractor interactor)
        {
            base.OnSelectExited(interactor);
        }

        public new void OnSelectExiting(XRBaseInteractor interactor)
        {
            base.OnSelectExiting(interactor);
        }

        protected override void OnDestroy()
        {
            base.OnDestroy();
            colliders.Clear();
        }
    }
}