using UnityEngine;
using VOID.Generic.Objects.Abstract;

namespace VOID.Generic.Util
{
    public static class RangeUtil
    {
        /// <summary>
        /// So far only alias to <see cref="Vector3.Distance(Vector3, Vector3)"/>
        /// </summary>
        public static float GetDistance(Vector3 pos1, Vector3 pos2)
        {
            return Vector3.Distance(pos1, pos2);
        }
        
        /// <summary>
        /// Returns distance between object and point.
        /// Also includes in calculations object's radius and height.
        /// </summary>
        public static float GetDistance(AbstractObject obj, Vector3 pos)
        {
            var objPosition = obj.transform.position;

            // Distance calculation can start from any point on object's height
            // So we can start calculating distance from any potion between object position and object position plus height
            var verticalDifference = objPosition.y - pos.y;
            if (verticalDifference < 0f)
                objPosition.y += Mathf.Min(Mathf.Abs(verticalDifference), obj.basicData.height);
            
            var fullDistance = Vector3.Distance(objPosition, pos);
            return fullDistance - obj.basicData.radius;
        }
        
        /// <summary>
        /// Returns distance between two objects.
        /// Also includes in calculations their radiuses and heights.
        /// </summary>
        public static float GetDistance(AbstractObject obj1, AbstractObject obj2)
        {
            var obj1Position = obj1.transform.position;
            var obj2Position = obj2.transform.position;

            // Distance calculation can start from any point on object's height
            // So we can start calculating distance from any potion between object position and object position plus height
            var verticalDifference = obj1Position.y - obj2Position.y;
            if (verticalDifference > 0f)
                obj2Position.y += Mathf.Min(Mathf.Abs(verticalDifference), obj2.basicData.height);
            else
                obj1Position.y += Mathf.Min(Mathf.Abs(verticalDifference), obj1.basicData.height);
            
            var fullDistance = Vector3.Distance(obj1Position, obj2Position);
            return fullDistance - obj1.basicData.radius - obj2.basicData.radius;
        }
        
        public static bool IsInRange(Vector3 pos1, Vector3 pos2, float range, bool withRangeError = true)
        {
            range += withRangeError ? 0.1f : 0f;
            return GetDistance(pos1, pos2) < range;
        }
        
        public static bool IsInRange(AbstractObject obj, Vector3 pos, float range, bool withRangeError = true)
        {
            range += withRangeError ? 0.1f : 0f;
            return GetDistance(obj, pos) < range;
        }
        
        public static bool IsInRange(AbstractObject obj1, AbstractObject obj2, float range, bool withRangeError = true)
        {
            range += withRangeError ? 0.1f : 0f;
            return GetDistance(obj1, obj2) < range;
        }
    }
}