/////////////////////////////////////////////////////////////////////////////////////////////////
// GF - Intersection
// various intersection utilitary functions
/////////////////////////////////////////////////////////////////////////////////////////////////
using UnityEngine;
using System.Collections;

public class GFIntersection 
{
	public static Vector2 SegmentVsCircle(float cx, float cy, float radius, Vector2 lineStart, Vector2 lineEnd)
	{
		Vector2 intersection1;
		Vector2 intersection2;
		int intersections = LineVsCircle(cx, cy, radius, lineStart, lineEnd, out intersection1, out intersection2);
		
		if (intersections == 1)
			return intersection1;//one intersection
		
		if (intersections == 2)
		{
			float dist1 = Distance(intersection1, lineStart);
			float dist2 = Distance(intersection2, lineStart);
			
			if (dist1 < dist2)
				return intersection1;
			else
				return intersection2;
		}
		
		return Vector2.zero;// no intersections at all
	}
	
	private static float Distance(Vector2 p1, Vector2 p2)
	{
		return (p2-p1).magnitude;
	}
	
	public static int LineVsCircle(float cx, float cy, float radius, Vector2 point1, Vector2 point2, out Vector2 intersection1, out Vector2 intersection2)
	{
		float dx, dy, A, B, C, det, t;
		
		dx = point2.x - point1.x;
		dy = point2.y - point1.y;
		
		A = dx * dx + dy * dy;
		B = 2.0f * (dx * (point1.x - cx) + dy * (point1.y - cy));
		C = (point1.x - cx) * (point1.x - cx) + (point1.y - cy) * (point1.y - cy) - radius * radius;
		
		det = B * B - 4.0f * A * C;
		if ((A <= 0.0000001f) || (det < 0.0f))
		{
			// No real solutions.
			intersection1 = new Vector2(float.NaN, float.NaN);
			intersection2 = new Vector2(float.NaN, float.NaN);
			return 0;
		}
		else if (det == 0)
		{
			// One solution.
			t = -B / (2.0f * A);
			intersection1 = new Vector2(point1.x + t * dx, point1.y + t * dy);
			intersection2 = new Vector2(float.NaN, float.NaN);
			return 1;
		}
		else
		{
			// Two solutions.
			t = (float)((-B + Mathf.Sqrt(det)) / (2.0f * A));
			intersection1 = new Vector2(point1.x + t * dx, point1.y + t * dy);
			t = (float)((-B - Mathf.Sqrt(det)) / (2.0f * A));
			intersection2 = new Vector2(point1.x + t * dx, point1.y + t * dy);
			return 2;
		}
	}
	
	public static bool 	DirVsCircle(Vector2 circleCenter, float circleRadius, Vector2 start, Vector2 end, out Vector2 intersection)
	{
		Vector2 intersection1 = Vector2.zero;
		Vector2 intersection2 = Vector2.zero;
		intersection = Vector2.zero;
		int intersections = LineVsCircle(circleCenter.x, circleCenter.y, circleRadius, start, end, out intersection1, out intersection2);
		if (intersections == 0)
			return false;
			
		Vector2 dir = (end - start).normalized;
		float d1 = Vector2.Dot(intersection1-start, dir);
		float d2 = -1.0f;
		if(intersections == 2)
			d2 = Vector2.Dot(intersection2-start, dir);
			
		if(d1 < 0.0f && d2 < 0.0f)
			return false;
			
		if(d1 < 0.0f)
			d1 = 9999999.0f;
		if(d2 < 0.0f)
			d2 = 9999999.0f;	
			
		if(d1 < d2)
		{
			intersection = intersection1;
			return true;
		}
		else
		{
			intersection = intersection2;
			return true;
		}
	}
}
