AreaGenerator = class("AreaGenerator")

function AreaGenerator:new(def, level, index)
	local gen = instance(self)
	gen.def = def
	gen.index = index
	gen.level = level
	gen.areas = {}
	return gen
end

function AreaGenerator:generate_using_rules(rules, team, location, yield)
	for area_type, num in pairs(self.def.areas) do
		for i=1,num do
			local area = rules:generate_instance("area", area_type, self.level)
			area:set_location(location)
			area:set_rules(rules)
			area:set_team(team)
			area:generate()
			table.insert(self.areas, area)			
			app.checkYield(yield)
		end
	end	
end

function AreaGenerator:get_areas()
	return self.areas
end

local function area_prio(a,b)
	return a.def.layout_prio > b.def.layout_prio
end

function AreaGenerator:layout_areas(universe, scol, srow, yield)
	--highest prio up top. Pick location first
	shellsort(self.areas, area_prio)	
	--reset placed bool
	for index, area in ipairs(self.areas) do
		area.placed = false
		area.col = scol
		area.row = srow
	end

	--in order, allow each area to place itself as close as possible to the center.
	for index, area in ipairs(self.areas) do
		local offset_angle = math.randomAngle()
		local while_break = 0
		local new_angle_try = 0
		local new_angle_limit = 10
		local hypo = area:get_hypo()
		--local area_max_range = cell_range-hypo
		app.checkYield(yield)
		while true do
			while_break = while_break+ 1
			local all_good = true
			for _, blocking_area in ipairs(self.areas) do
				if blocking_area.placed then
					if not blocking_area.def.allow_overlap then
						if blocking_area:is_area_intersecting_any_shape(area) then
							--print("Blocked internal", area.index, area.col, area.row, blocking_area.col, blocking_area.row, area:get_hypo(), area.bounds:get_width(), area.bounds:get_height(), blocking_area.bounds:get_width(), blocking_area.bounds:get_height())
							all_good = false
							break
						end
					end
				else
					--this has not been layed out, ignore its bounds
					break
				end
				app.checkYield(yield)
			end
			if all_good then
				if universe:is_area_intersecting_any_shape(area, yield) then
					all_good = false
				end				
			end

			if not all_good then
				--layout not good, lets move it out somewhere
				local dist = math.random(2,4)
				new_angle_try = new_angle_try + dist
				if new_angle_try >= new_angle_limit then
					offset_angle = math.randomAngle()
					area.col = scol
					area.row = srow
					new_angle_limit = new_angle_limit*2					
				else
					area.col = math.round(area.col + math.cos(offset_angle)*dist)
					area.row = math.round(area.row + math.sin(offset_angle)*dist)
					offset_angle = offset_angle + math.random()*math.pi*0.05 - math.random()*math.pi*0.05
				end
			else				
				--print("final pos", area.index, area.col, area.row)
				area.placed = true		
				break
			end
			app.checkYield(yield)
			if while_break > 50 then
				--print("FAILED TO LAYOUT AREA!!! CHECK YO DAMN ALGO")
				break
			end
		end
		app.checkYield(yield)
		--print("LAYOUTED area", area.index, area.col, area.row)
	end
	--for index, area in ipairs(self.areas) do
	--	print(area.index)
	--end
end