
local activeblocks = 0
local levelovertime = 0

function initlevel (lvl)
	do
		local function bthink (self)
			if (self.body:state() and not self.pstate) then
				self.l3ds[1]:color(1,1,1,1)
				self.pstate = true
				self:activate()
			elseif (not self.body:state() and self.pstate) then
				self.pstate = false
				self.l3ds[1]:color(self.r,self.g,self.b,1)
				self:deactivate()
				return
			end
			if (not self.body:state()) then self:deactivate() return end
			
			local x,y,z = self.body:angvel()
			self.body:angvel(x*0.99,y*0.99,z*0.99)
			x,y,z = self.body:velocity()
			self.body:velocity(x*0.999,y*0.999,z*0.999)
			x,y,z = self.body:pos()
			
			if (z<-2.7 and self.active) then
				activeblocks = activeblocks - 1
				self.active = false
				self.body:disabletime(100)
				self.body:velthreshold(0.04)
				self.body:minenableforce(0.001)
				self.body:nextminenableforce(0.001)
				self.geoms[1]:surfaceid(1)
				score.bricked(self)
			end
			
			self.stime = (self.stime or 0)
			if (self.stime>0) then
				local fm = self.body:jointenergy(50000)
				if (fm>0.1) then
					local tap = soundnode.new(self.tap)
					gain = math.max(0,math.min(1,fm/10))
					tap:pitch(1.0)
					tap:gain(gain)
					tap:rewind()
					tap:velocity(self.body:velocity())
					
					self.stime = -25
					tap:pos(self.body:pos())
					tap:play()
					if (fm>0.5) then
						for i=0,self.body:jointcount()-1 do
							local jn = self.body:joint(i)
							local x,y,z = jn:pos()
							local nx,ny,nz = jn:normal()
							hitpsys.spawn (x,y,z,nx,ny,nz, fm*100) 
						end
					end
				end
				
				
				--local fm = self.body:jointenergy()
				--if (fm>0.00001) then 
					--sounds.tap1:play() 
				--	self.stime = -10
				--end
			else self.stime = self.stime + 1 end
		end
		
		
		local sz = screenratio/1.5
		local function addbrick (x,y,w,h,d,rgb,mass) 
			local R,G,B = unpack(rgb)
			w,h = w or sz, h or sz
			local b = box.new(box,{x,0,y},{w,d or sz/2,h},0.2/sz*(mass or 1))
			--b.body:maxcontacts(2)
			b.body:lock(2,0,0.05,1)
			b.body:state(false)
			b.body:minactdepth(-1)
			--b.body:maxcontacts(1)
			b.body:minenableforce(0.0006)
			b.body:nextminenableforce(0.0006)
			b.geoms[1]:enabledspace(entity.space)
			b.geoms[1]:disabledspace(static.space)
			b.active = true
			b.tap = sounds.tap4
			local l = 1
			R,G,B = 	R or math.sin(x*l     + math.sin(y)^2)^2+0.4, 
						G or math.cos(x*l*0.5 + math.cos(y)^2)^2+0.4,
						B or 0.0
			b.r,b.g,b.b = R,G,B
			b.l3ds[1]:color(R,G,B,1)
			b.think = bthink
			activeblocks = activeblocks + 1
			return b
		end
		
		if (not lvl) then
			for h=1,5,sz do
				for i=-screenratio*5,screenratio*5,sz do
					addbrick(i,h)
				end
			end
		else 
			local colors = lvl.colors or {}
			local heights = lvl.heights or {}
			local transform = lvl.bodytransform or function () end
			sz = sz * (lvl.sizemul or 1)
			local d = lvl.depth and (lvl.depth*sz) or sz
			local weightmul = lvl.weightmul or 1
			local H = lvl.height or 1
			for y,line in ipairs(lvl) do
				local mw = (string.len(line)+1)*0.5

				for i = 1,string.len(line) do
					local c = string.sub(line,i,i)
					local h = heights[c] or H
					if (colors[c]) then
						local val = colors[c]
						local X,Y = (i-mw)*sz, -y*sz
						if (type(val) == "function") then 
							val = val(c,X,Y,i,y)
						end
						transform(addbrick(X,Y*H+6,sz,h*sz,d,val,weightmul),mw,sz,i,y)
					end
				end
			end
		end
	end
	player.new()
	local resetpos = {0,0,-1}
	local b = ball.new(resetpos,0.25*screenratio,0.1/screenratio)
	b.body:autodisable(false)
	b.body:lock(2,0)
	--b.body:minactdepth(5)
	b.geoms[1]:surfaceid(2)
	b.tap = sounds.tap6
	local rtime = 0
	
	function b.think (self)
		local vx,vy,vz = self.body:velocity()
		local v = (vx*vx+vy*vy+vz*vz)^0.5
		local x,y,z = self.body:pos()
		self.stop = self.stop or 0
		rtime = rtime + 1
		
		self.stime = self.stime or 0
		if (self.stime>0) then
			local fm = self.body:jointenergy(10000)
			if (fm>0.001) then
				local tap = soundnode.new(b.tap)
				tap:pos(b.body:pos())
				gain = math.max(0.001,math.min(1,(fm/10)))
				tap:pitch(1.0)
				tap:gain(gain)
				tap:velocity(self.body:velocity())
				tap:rewind()
				tap:play()
				--_print("play",self.stime)
				self.stime = -10
			end
			for i=0,self.body:jointcount()-1 do
				local jn = self.body:joint(i)
				local x,y,z = jn:pos()
				local nx,ny,nz = jn:normal()
				hitpsys.spawn (x,y,z,nx,ny,nz, fm*100) 
			end
			
		else self.stime = self.stime + 1 end
		
		local reset = (Keyboard.isKeyDown(key.reset))
		local inp = {input.joystick()}	
		if (inp[1]) then reset = (inp[inp[3]+6] or reset) end
--		if (keys[string.byte(' ')]) then reset = true end
		if (reset and rtime > 0) then
			score.ballfetch()
			rtime = -100
			self.body:pos(unpack(resetpos))
			self.body:velocity(0,0,0)
		end
	end
	pball = b
	
	dworld.surfacecombination(1,2,2)
	dworld.surfacecombination(1,1,1)
	dworld.surfacecombination(0,2,2)
	dworld.surfacecombination(4,2,2)
	dworld.surfacebitbounce(2,true)
	dworld.surfacebounce(2,0.92)
	dworld.surfacemu(2,0)
end

function start (lvl)
	entity.deleteall()
	initlevel(lvl)
	levelovertime = 0
	levelfinished = false
end

do
	local simtime = 0
	local synctime = luxinia.time()
					
--	start()
	
	local function think ()
		local cnt = 0
		while (cnt < 10 and synctime < luxinia.time()) do
			entity.thinkall()
			
			
			dworld.collidetest(space)
			dworld.makecontacts()
			dworld.quickstep(0.58)
			
			score.tick()
		
			
			synctime = synctime + 10
			simtime = simtime + 10
			cnt = cnt + 1
			if (activeblocks == 0) then 
				levelovertime = levelovertime + 1
				if (levelovertime>200) then 
					endlevel()
				end
			end
		end
		if (cnt>=10) then
			synctime = luxinia.time()
		end
	end
	
	Timer.set("actinoids",think)
end