
local function luxiniadir (path) 
	local find = string.gsub(path,".*/([^/]*)","%1"):gsub("%*.%*",".*"):gsub("%*.",".*%.")
	local path = string.gsub(path,"(.*)/[^/]*","%1")
	
	local tab = {}
	for name in lfs.dir(path) do 
		if (string.match(name,find)) then 
			table.insert(tab,name)
		end
	end
	return tab
end

local tilefiles = luxiniadir(projectpath.."/models/level/*.f3d")
local mapobjectfiles = luxiniadir(projectpath.."/models/mapobjects/*.f3d")
local totalcount = table.getn(tilefiles)+table.getn(mapobjectfiles)
local loaded = 0
local l2dbar = l2dtext.new("hu","loading 0%",xmasfont)
l2dbar:parent(l2dnode.getroot())

function barupdate ()
	l2dbar:text(string.format("loading %i%%",loaded / totalcount*100))
	local len = string.len(l2dbar:text())
	l2dbar:pos(320-len*8,300,0)
	coroutine.yield()
end

function getModelColMesh (mdl,id)
	local indices,vertices= {},{}
	local hitmeshes
	local globalprop = {}
	
	local function addmesh (m)
		local useindex,usevertices = indices,vertices
		local hitmesh = false
		local props = globalprop
		if (m:texname() and string.find(m:texname(),"hitzone")) then 
			useindex = {}
			usevertices = {}
			hitmesh = true
			props = {}
		end
		if (m:texname() and string.find(m:texname(),"light")) then 
			return 
		end

		for i=0,m:indexPrimitivecount()-1 do
			local tri = {m:indexPrimitive(i)}
			local a,b,c = unpack(tri)
			--_print(a,b,c)
			if (not (a==b or b==c or c==a)) then
				local offset = table.getn(usevertices)/3
				for j=1,3 do
					local p = {m:vertexPos(tri[j])}
					props.min = props.min or {p[1],p[2],p[3]}
					props.max = props.max or {p[1],p[2],p[3]}
					for k=1,3 do
						props.min[k] = math.min(props.min[k], p[k])
						props.max[k] = math.max(props.max[k], p[k])
						--print(string.format("%.2f %.2f %.2f",props.min[k], p[k],props.max[k]))
					end
					table.insert(usevertices,p[1])
					table.insert(usevertices,p[2])
					table.insert(usevertices,p[3])
				end
				table.insert(useindex,offset)
				table.insert(useindex,offset+1)
				table.insert(useindex,offset+2)
			end
		end
		
		if (hitmesh) then
			hitmeshes = hitmeshes or {}
			cntr = {(props.min[1]+props.max[1])*0.5,(props.min[2]+props.max[2])*0.5,
				(props.min[3]+props.max[3])*0.5 }
			table.insert(hitmeshes,{data = dgeomtrimeshdata.new(useindex,usevertices), 
				aabox = props, center = cntr})
		end
	end
	
	for i=0,mdl:meshcount()-1 do
		addmesh(mdl:meshid(i)) 
	end
	local props = globalprop
	local cntr = {(props.min[1]+props.max[1])*0.5,(props.min[2]+props.max[2])*0.5,
		(props.min[3]+props.max[3])*0.5 }
	
	return 	{data = dgeomtrimeshdata.new(indices,vertices), aabox = globalprop, center = cntr}, hitmeshes
end

wavsounds = {
	hohoho = {},
	drop01 = {},
	drop02 = {},
	drop03 = {},
	typewriter = {},
	cr_bell = {}
}

for a,b in pairs(wavsounds) do 
	b.snd = sound.load(a..".wav")
	--b.snd:play()
end

function autotable () 
	local tab = {}
	setmetatable(tab,{__index = 
		function (self,id)
			if (not rawget(self,id)) then rawset(self,id,{}) end 
			return rawget(self,id) 
		end})
	return tab
end

levelnodes = {
	nodes = {},
	nodeids = {},
	categories = {},
	north = autotable(),
	south = autotable(),
	west = autotable(),
	east = autotable()
}

mapobjects = {}
do 
	local files = mapobjectfiles
	local cnt = totalcount
	local prev,first
	for a,b in ipairs(files) do
		if (b:sub(1,1)~='.') then 
			local short = string.gsub(b,"\.f3d","")
			--_print("importing ",b,short)
			mapobjects[short] = {mdl = model.load("mapobjects/"..b,false,true,false)}
			mapobjects[short].colmesh,mapobjects[short].hitmeshes = getModelColMesh(mapobjects[short].mdl,short)
			mapobjects[short].name = b
			mapobjects[short].short = short
			prev,first = prev or mapobjects[short],first or mapobjects[short]
			prev.next = mapobjects[short]
			prev.next.prev = prev
			prev.next.next = first
			first.prev = mapobjects[short]
			prev = mapobjects[short]
			
			loaded = loaded + 1
			barupdate()
		end
	end

end

levelnode = {}

function levelnode.create(self,x,y,z)
	local l3d = self.load()
	local s3d = scenenode.new(self.name,true,(x or 0)*config.quadsize,(y or 0)*config.quadsize,z*config.heightstep or 0)
	self.x,self.y,self.z = x,y,z
	l3d:linkinterface(s3d)
	l3d:rfLitSun(true)
	l3d:rfLitFX(gameconfig.lightning>=2)
	l3d:projectorflag(1,true)
	return s3d,l3d
end

function levelnode.forallquads(self,...)
	local tab,n = {},1
	for x,b in pairs(self.size) do
		for y,c in pairs(b) do
			if (c) then table.insert(tab,{x,y}) end
		end
	end
	local arg = {...}
	return function ()
		local p = tab[n]
		if (not p) then return nil end
		n = n + 1
		return p[1],p[2],unpack(arg)
	end
end

function levelnode.init(self,name)
	self.name = name
	table.insert(levelnodes.nodeids,self)
	self.id = table.getn(levelnodes.nodeids)
	self.prev = levelnodes.nodeids[self.id-1]
	self.next = levelnodes.nodeids[1]
	levelnodes.nodeids[1].prev = self
	self.load = levelstrip("level/"..name..".f3d")
	self.model = model.load("level/"..name..".f3d",false,true,false)
	self.size = autotable()
	self.size[0][0] = true
	
	string.gsub(name,"_(%d+)_(%d+)_(%d+)_(%d+)",function (n,e,s,w) 
		self.categoryname = string.format("%i %i %i %i",n,e,s,w)
		levelnodes.north[n][self.id] = self
		levelnodes.south[s][self.id] = self
		levelnodes.east[e][self.id] = self
		levelnodes.west[w][self.id] = self
		self.north,self.east,self.south,self.west = n,e,s,w
	end)
	
	levelnodes.categories[self.categoryname] = 
		levelnodes.categories[self.categoryname] or {}
	table.insert(levelnodes.categories[self.categoryname],self)
--	_print("importing "..name)
	self.colmesh = getModelColMesh(self.model,self.name).data
	
	offset = 0
	vertices,index = {},{}
	
	setmetatable(self,{__index=levelnode})
end

function inittiles()
	function levelstrip(name)
		local mdl = model.load(name,false,true,false)
		local cnt = mdl:meshcount()
		for i=0,cnt-1 do
			local mesh = mdl:meshid(i)
			local tex = mesh:texture()
			--if (tex) then tex:clamp(true) end
		end
		
		return function ()
			local l3d = l3dmodel.new(name,layer,mdl,false,false)
			l3d:rfLitSun(true)
			return l3d
		end
	end
	
	for a,b in ipairs(tilefiles) do
		b = string.gsub(b,"\.f3d","")
		levelnodes.nodes[b] = {}
	end

	for name,node in pairs(levelnodes.nodes) do
		levelnode.init(node,name)
		loaded = loaded + 1
		barupdate()
	end
end

inittiles()

l2dbar:delete()
