using UnityEngine.Events;
namespace UnityEngine.XR.Content.Interaction
{
    /// 
    /// Runs functionality when an object is tilted.
    /// Used with grabbable objects for pouring.
    /// 
    public class OnTilt : MonoBehaviour
    {
        /// 
        /// Extra angle value that is added/removed from the threshold to events from rapid-fire triggering on and off.
        /// 
        const float k_AngleBuffer = 0.05f;
        [SerializeField]
        [Tooltip("Tilt range, 0 - 180 degrees.")]
        [Range(k_AngleBuffer * 2f, (1 - k_AngleBuffer * 2f))]
        float m_Threshold = 0.5f;
        [SerializeField]
        [Tooltip("The transform to check for tilt. Will default to this object if not set.")]
        Transform m_Target;
        [SerializeField]
        [Tooltip("The transform to get as the source of the 'up' direction. Will default to world up if not set.")]
        Transform m_UpSource;
        [SerializeField]
        [Tooltip("Event to trigger when tilting goes over the threshold.")]
        UnityEvent m_OnBegin = new UnityEvent();
        [SerializeField]
        [Tooltip("Event to trigger when tilting returns from the threshold.")]
        UnityEvent m_OnEnd = new UnityEvent();
        /// 
        /// Event to trigger when tilting goes over the threshold.
        /// 
        public UnityEvent onBegin => m_OnBegin;
        /// 
        /// Event to trigger when tilting returns from the threshold.
        /// 
        public UnityEvent onEnd => m_OnEnd;
        bool m_WithinThreshold;
        void Update()
        {
            CheckOrientation();
        }
        void CheckOrientation()
        {
            var targetUp = m_Target != null ? m_Target.up : transform.up;
            var baseUp = m_UpSource != null ? m_UpSource.up : Vector3.up;
            var similarity = Vector3.Dot(-targetUp, baseUp);
            similarity = Mathf.InverseLerp(-1, 1, similarity);
            if (m_WithinThreshold)
                similarity += k_AngleBuffer;
            else
                similarity -= k_AngleBuffer;
            var thresholdCheck = (similarity >= m_Threshold);
            if (m_WithinThreshold != thresholdCheck)
            {
                m_WithinThreshold = thresholdCheck;
                if (m_WithinThreshold)
                {
                    m_OnBegin.Invoke();
                }
                else
                {
                    m_OnEnd.Invoke();
                }
            }
        }
    }
}