local dir_factors = {
	{x = 1, y = 0},
	{x = 0, y = 1},
	{x = -1, y = 0},
	{x = 0, y = -1},
}

AREA_SHAPE_GENERATORS = {
	sprawling = {
		generate = function(self, def)
			
			local core = self:create_shape(0,0,"core")
			if def.core_radius then
				core:set_circle(0,0, def.core_radius, true)
			end

			local min = def.sprawl_length_min or 1
			local max = def.sprawl_length_max or 3

			local wmin = def.sprawl_width_min or 1
			local wmax = def.sprawl_width_max or 3
			local x,y = 0,0

			for j=1,def.sprawl_times do
				local num_dirs = #dir_factors
				local initial_sprawl_dir = math.random(1,num_dirs)
				local sprawl_dir = initial_sprawl_dir
				local x1 = x
				local y1 = y
				for i=1,def.sprawl_segments do
					local main = self:create_shape(0,0,"main")
					local path = self:create_shape(0,0,"path")
					
					local len = math.random(min, math.max(min, max))
					
					local dir = dir_factors[sprawl_dir]
					local x2 = x1 + len*dir.x
					local y2 = y1 + len*dir.y
					path:set_line(x1,y1,x2,y2, true)

					--create fuzzy main around sprawling paths
					for c=1,len/4 do
						local xd = x2-x1
						local yd = y2-y1
						local vx = math.round(x1 + math.random(xd))
						local vy = math.round(y1 + math.random(yd))
						local rad = math.random(wmin, wmax)
						main:set_circle(vx, vy, rad, true)
					end
					main:set_line(x1,y1,x2,y2, nil)

					--print("pre", sprawl_dir)
					sprawl_dir = math.normalize(sprawl_dir + math.random(1,3)-2,1,num_dirs)
					--print(sprawl_dir)
					if math.random() < (def.sprawl_direction_stickyness or 0.5) then
						sprawl_dir = initial_sprawl_dir --certain stickness towards direction
					end
					x1 = x2
					y1 = y2

				end
			end
		end,
	},
	room = {
		generate = function(self, def)
			local ratio_range = def.room_ratio_range or 0.2
			local aspect_ratio = math.random(1-ratio_range, 1+ratio_range)				
			local size = def.room_size or 5

			local rw = math.round(size*aspect_ratio)
			local rh = math.round(size/aspect_ratio)

			local blocking = self:create_shape(0,0,"blocking")
			local block_w = rw+2
			local block_h = rh+2
			blocking:set_centered_rectangle(0,0,block_w,block_h,true)
			blocking:set_centered_rectangle(0,0,rw,rh,nil)

			local main = self:create_shape(0,0,"main")
			local edge = self:create_shape(0,0,"edge")
			local path = self:create_shape(0,0,"path")
			local core = self:create_shape(0,0,"core")
			
			local esize = def.entrance_size or 1

			for i=1,def.entrances or 1 do
				local horisontal = math.random() > 0.5
				local x1,y1,x2,y2
				if horisontal then
					local startx = 2-block_w*0.5
					x1 = -esize*0.5
					x2 = esize*0.5
					y1 = (math.random() > 0.5) and -block_h*0.5 or block_h*0.5
					y2 = y1
				else
					local starty = 2-block_h*0.5
					y1 = -esize*0.5
					y2 = esize*0.5
					x1 = (math.random() > 0.5) and -block_w*0.5 or block_w*0.5
					x2 = x1
				end
				blocking:set_line(x1,y1,x2,y2, nil)
				edge:set_line(x1,y1,x2,y2, true)
				path:set_line(x1,y1,x2,y2, true)
			end

			main:set_centered_rectangle(0,0,rw-2,rh-2,true) --fill center

			edge:set_centered_rectangle(0,0,rw,rh,true)
			edge:set_centered_rectangle(0,0,rw-2,rh-2,nil) --only leave a border
				
			local core_factor = def.core_factor or 0.5
			local cw,ch = math.ceil(rw*core_factor),math.ceil(rh*core_factor)
			core:set_centered_rectangle(0,0,rw*core_factor,rh*core_factor,true) --fill core

			local paths = def.paths or 0
			for p=1,paths do
				local px,py = math.random(-rw*0.5,rw*0.5),math.random(-rh*0.5,rh*0.5)
				local pw,ph = rw,rh
				if math.random() > 0.5 then
					px = 0
					ph = 1
				else
					py = 0
					pw = 1
				end					
				edge:set_centered_rectangle(px, py, pw, ph, nil) --clear edge					
				path:set_centered_rectangle(px, py, pw, ph, true) --set path
			end
		end,
	},
	dungeon = {
		generate = function(self, def)

		end,
	},
	blob = {
		generate = function(self, def)
			local main = self:create_shape(0,0,"main")
			local ang = math.randomAngle()
			local size = (def.blob_size or 10)
			local size_variance = (def.blob_size_variance or 0.5)
			local spread = (def.blob_spread_factor or 0.5)

			for i=1,def.blob_density or 1 do
				local rad = math.random()*size*size_variance + size*(1-size_variance)
				local dist = math.random()*size*spread
				local x,y = math.round(math.cos(ang)*dist), math.round(math.sin(ang)*dist)
				main:set_circle(x,y,rad, true)
			end

			local core_rad = def.core_radius
			if core_rad then
				local core = self:create_shape(0,0,"core")				
				core:set_circle(0,0,core_rad, true)
			end
		end,
	},
}

