require("pathfinding/vertex");
require("pathfinding/node");
require('pathfinding/math');
Polygon	=	class.new();

function Polygon:constructor(...)
	if( getmetatable(...) ~= getmetatable(Vertex) ) then
		self.vertices	=	...;
	else
		self.vertices	=	{...};
	end
end

-- Extrudes a polygon and returns the new, extruded copy
--[[function Polygon:extrude(dist)

end]]

function Polygon:getVertex(index)
	if( index < 1 or index > #self.vertices ) then
		return nil;
	end

	return self.vertices[index];
end

function Polygon:getVertices()
	return self.vertices;
end

-- Get the index of a vertice that is previous to 'fromIndex'; Loops around
function Polygon:previousIndex(fromIndex)
	assert(#self.vertices); -- Cannot get previous if there's no vertices
	assert(fromIndex ~= 0); -- Cannot be 0
	if( fromIndex < 0 ) then
		-- If negative, loop around in reverse.
		local absIndex = math.abs(fromIndex) % #self.vertices;
		fromIndex =  #self.vertices - absIndex + 1;
	end

	local newIndex = (fromIndex - 1);
	if( newIndex == 0 ) then
		newIndex = #self.vertices;
	end
	return newIndex;
end

-- Get the index of a vertice that is next to 'fromIndex'; Loops around
function Polygon:nextIndex(fromIndex)
	assert(#self.vertices); -- Cannot get previous if there's no vertices
	assert(fromIndex ~= 0); -- Cannot be 0
	if( fromIndex < 0 ) then
		-- If negative, loop around in reverse.
		local absIndex = math.abs(fromIndex) % #self.vertices;
		fromIndex =  #self.vertices - absIndex + 1;
	end

	local newIndex = (fromIndex + 1);
	if( newIndex == #self.vertices + 1 ) then
		newIndex = 1;
	end
	return newIndex;
end

-- Convert a polygon to nodes
function Polygon:toNodes()
	local nodes = {};

	-- Insert a new node for each vertex
	for i,v in pairs(self.vertices) do
		table.insert(nodes, Node(v.x, v.y));
	end

	-- Connect them together
	for i,thisNode in pairs(nodes) do
		-- If last node in the list, loop back to first
		local nextNodeIndex = i + 1;
		if( nextNodeIndex > #nodes ) then
			nextNodeIndex = 1;
		end
		local nextNode = nodes[nextNodeIndex];

		-- Connect this node to next node, and next node to this node
		thisNode:addConnection(nextNode);
		nextNode:addConnection(thisNode);
	end

	return nodes;
end

-- Expand (inflate/extrude) a polygon by some distance
--[[	DEPRECATED; use Clipper instead
function Polygon:offset(dist)
	assert(#self.vertices >= 2);

	-- Finds the intersection point between two rays perpendicular to edges (vertex1->vertex2 and vertex2->vertex3) offset by some amount
	-- ie. Where our new, offset vertex should be placed
	

	-- Extrude an edge some distance
	local function extrudeEdge(vertex1, vertex2, dist)
		local dx		=	vertex2.x - vertex1.x;
		local dy 		=	vertex2.y - vertex1.y;
		local normal	=	math.atan(dy, dx) - math.pi*0.5;

		-- Move each point along the normal, expand
		local v1		=	Vertex(vertex1.x + math.cos(normal) * dist, vertex1.y + math.sin(normal) * dist);
		local v2		=	Vertex(vertex2.x + math.cos(normal) * dist, vertex2.y + math.sin(normal) * dist);

		return v1, v2;
	end

	local newVerts = {};
	for i,v in pairs(self.vertices) do
		local prevIndex =	self:previousIndex(i);
		local nextIndex	=	self:nextIndex(i);

		-- Construct temporary segments by extruding edges along their normal
		local v1, v2	=	extrudeEdge(self.vertices[prevIndex], self.vertices[i], dist);
		local v3, v4	=	extrudeEdge(self.vertices[i], self.vertices[nextIndex], dist);

		--printf("Extrude edge 1: (%0.3f, %0.3f), (%0.3f, %0.3f)\n", v1.x, v1.y, v2.x, v2.y);

		-- Find the intersection point of the two edges
		local nv = lineIntersection(v1, v2, v3, v4);
		if( not nv ) then
			-- Should only happen if they are parallel, but... that shouldn't normally happen
			nv = Vertex(self.vertices[i].x, self.vertices[i].y);
		end

		--printf("Intersection Point: (%0.3f, %0.3f)\n", nv.x, nv.y);
		table.insert(newVerts, nv);
	end

	return Polygon(newVerts);
end]]