RoomDescriptor = {

}

function RoomDescriptor.CreateDungeon( Width, Height, Depth )
	local Map = {}

	local Factor = 1

	Width  = Width *Factor
	Height = Height*Factor

	PrepareDungeon( Width, Height )

	local HalfWidth  =  Width/2 - 1
	local HalfHeight = Height/2 - 1

	for X = 1, Width do
		Map[ X ] = {}

		for Y = 1, Height do
			Map[ X ][ Y ] = "."
		end
	end

	local Rooms = { }

	CreateBSP( Rooms, 1, 1, Width - 1, Height - 1, math.random( 2 ), false )

	for I = 1, #Rooms do
		for X = Rooms[ I ].X1, Rooms[ I ].X2 do
			Map[ X ][ Rooms[ I ].Y1 ] = "#"
			Map[ X ][ Rooms[ I ].Y2 ] = "#"
		end

		for Y = Rooms[ I ].Y1, Rooms[ I ].Y2 do
			Map[ Rooms[ I ].X1 ][ Y ] = "#"
			Map[ Rooms[ I ].X2 ][ Y ] = "#"
		end
	end

	for I = 1, #Rooms do
		for T = I + 1, #Rooms do
			local StartX, StartY, EndX, EndY = AdjactingSide( Rooms[ I ], Rooms[ T ] )

			if StartX then
				if EndX - StartX > 0 or EndY - StartY > 0 then
					local TileX = ( EndX - StartX > 0 and math.random( EndX - StartX ) or 0 ) + StartX
					local TileY = ( EndY - StartY > 0 and math.random( EndY - StartY ) or 0 ) + StartY

					Map[ TileX ][ TileY ] = "."

					CreateObject( "Door", TileX - 1, TileY - 1 )
				end
			end
		end
	end

	for I = 1, Max( 50*Factor, 100 ) do
		local TileX = 2 + math.random( Width  - 2 )
		local TileY = 2 + math.random( Height - 2 )

		if Map[ TileX ][ TileY ] == "." then CreateObject( SelectMonster( Depth ), TileX - 1, TileY - 1 ) end
	end

	local Places = { { 3, 3 }, { Width - 2, Height - 2 }, { Width - 2, 3 }, { 3, Height - 2 } }

	for I = 1, 3 do
		while true do
			local Index = math.random( 4 )

			if Places[ Index ] then
				Map[ Places[ Index ][ 1 ] ][ Places[ Index ][ 2 ] ] = ( I > 1 and "v" or "^" )

				Places[ Index ] = nil

				break
			end
		end
	end

	--CreateObject( "Lamp", 3, 3 )

	--local L = CreateObject( "Lamp", 20, 20 )
	--L.R = 0

	local Result = ""

	for Y = 1, Height do
		for X = 1, Width do
			Result = Result .. Map[ X ][ Y ]
		end

		Result = Result .. "\n"
	end

	return string.sub( Result, 1, string.len( Result ) - 1 )
end

function AdjactingSide( R1, R2 )
	if RectsOverlap( R1.X1, R1.Y1, R1.X2, R1.Y2, R2.X1, R2.Y1, R2.X2, R2.Y2 ) then
		if R1.X1 == R2.X2 then return R1.X1, Max( R1.Y1, R2.Y1 ) + 1, R1.X1, Max( R1.Y1, R2.Y1 ) - OverlappingAmount( R1.Y1, R1.Y2, R2.Y1, R2.Y2 ) - 1 end
		if R2.X1 == R1.X2 then return R2.X1, Max( R1.Y1, R2.Y1 ) + 1, R2.X1, Max( R1.Y1, R2.Y1 ) - OverlappingAmount( R1.Y1, R1.Y2, R2.Y1, R2.Y2 ) - 1 end

		if R1.Y1 == R2.Y2 then return Max( R1.X1, R2.X1 ) + 1, R1.Y1, Max( R1.X1, R2.X1 ) - OverlappingAmount( R1.X1, R1.X2, R2.X1, R2.X2 ) - 1, R1.Y1 end
		if R2.Y1 == R1.Y2 then return Max( R1.X1, R2.X1 ) + 1, R2.Y1, Max( R1.X1, R2.X1 ) - OverlappingAmount( R1.X1, R1.X2, R2.X1, R2.X2 ) - 1, R2.Y1 end
	else

	end

	return false, false, false, false
end

function RectsOverlap( X1, Y1, X2, Y2, X3, Y3, X4, Y4 )
	return ( X1 <= X4 and Y1 <= Y4 and X2 >= X3 and Y2 >= Y3 )
end

function OverlappingAmount( A1, A2, B1, B2 )
	if A1 <= B1 then
		return B1 - A2
	else
		return A1 - B2
	end
end

function CreateBSP( Rooms, X, Y, Width, Height, Axis, UrgentSplit )
	if ( not UrgentSplit ) and ( Width < 10 or Height < 10 ) then
		if Height >= 15 then
			CreateBSP( Rooms, X, Y, Width, Height, 2, true )
		elseif Width >= 15 then
			CreateBSP( Rooms, X, Y, Width, Height, 1, true )
		else
			Rooms[ #Rooms + 1 ] = { X1 = X, Y1 = Y, X2 = X + Width, Y2 = Y + Height }
		end
	else
		if Axis == 1 then
			local Third = math.floor( Width/3 )

			local Split = math.random( Third ) + Third

			CreateBSP( Rooms, X,         Y,         Split, Height, 2, false )
			CreateBSP( Rooms, X + Split, Y, Width - Split, Height, 2, false )
		else
			local Third = math.floor( Height/3 )

			local Split = math.random( Third ) + Third

			CreateBSP( Rooms, X, Y,         Width,          Split, 1, false )
			CreateBSP( Rooms, X, Y + Split, Width, Height - Split, 1, false )
		end
	end
end
