config = {
	quadsize = 300,
	heightstep = 50
}

do
	gameconfig = gameconfig or {weather = 3, lightning = 3}
	local res,err = loadfile("gameconfig.lua")
	if (res) then
		local err,res = pcall(res)
		if (res) then
			for i,v in pairs(res) do
				gameconfig[i] = v
			end
		end
	else
		_print(err)
	end

	local exit = system.exit
	function system.exit ()
		local tab = {"return {"}
		for i,v in pairs(gameconfig) do
			table.insert(tab, string.format("\t%s = %i,",i,v))
		end
		table.insert(tab,"}\n")

		fp = io.open(projectpath.."/gameconfig.lua","w")
		fp:write(table.concat(tab,"\n"))
		fp:close()
		exit()
	end

	if (gameconfig.weather<3) then snow.stop() else snow.start() end
end



space 			= dspacehash.new()
staticspace 	= dspacehash.new()
presentspace 	= dspacehash.new()
plane 			= dgeomplane.new(0,0,1,-500)
staticspace:collidetest(false)
staticspace:add(plane)
space:add(presentspace)
space:add(staticspace)



function initmenubackground ()
	if (menuison)  then return end
	--_print("initmenubackground")
	menulevel = levelmap.load("intro.lvl.lua")
	l3dcamera.default():fov(45)
	l3dcamera.default():frontplane(64)
	menucamnode = actornode.new("")
	l3dcamera.default():linkinterface(menucamnode)
	menucamnode:pos(150,-200,700)
	menucamnode:rotrad(0,0,0.2)

	local function loadstaticmodel(name,layer)
		local res = model.load(name,false,true)
		local l3d = l3dmodel.new(name,layer,res,false,false)

		l3d:rfLitSun(true)
		l3d:rfLitFX(true)

		return l3d;
	end

	local function loaddynamicmodel(name,layer)
		local res = model.load(name,true,true, technique.arb_v():supported())
		local l3d = l3dmodel.new(name,layer,res,true,false)

		l3d:rfLitSun(true)
		l3d:rfLitFX(true)

		return l3d;
	end

	s3dintroanim = actornode.new("root")
	s3dintroanim:pos(133,-126,0)
	s3dintroanim:rotrad(0,0,math.pi*0.6)
	local layer = l3dset.get(0):layer(1)
	local l3d = loaddynamicmodel("intro/wmann_rudi_intro.f3d",layer)
	l3d:linkinterface(s3dintroanim)
	local anim = animation.load("wmann_rudi_intro_anim01.ma",true,false)
	local atime = anim:length()
	l3d:seqAnimsource(0,0,anim)
	l3d:seqAnimstart(0,0,0)
	l3d:seqAnimlength(0,0,atime)
	l3d:seqOffset(0,0)
	l3d:seqLoop(0,true)
	l3d:seqState(0,1)

	l3dwmann = l3d;


	l3dsled = loadstaticmodel("sled.f3d",layer)
	sledactor = actornode.new("sled")
	l3dsled:linkinterface(sledactor)
	sledactor:pos(170,-100,0)
	sledactor:rotrad(0,0,math.pi*0.3)



	local sled = entity.new("giftactor",-50,0,2)
	sled:addl3d(loadstaticmodel("intro/wmann_rudi_intro_riesengift.f3d",layer))
	sled:addl3d(loadstaticmodel("intro/wmann_rudi_intro_riesengiftcard.f3d",layer))
	sled:addgeom(dgeombox.new(50,15,1),2)
	local lring,rring = dgeombox.new(1,1,1),dgeombox.new(1,1,1)
	sled:addgeom(dgeomtransform.new(),1,lring,-14,29,8)
	sled:addgeom(dgeomtransform.new(),1,rring, 14,29,8)
	sled:makebody()
	sled.body:rotrad(0,0,-math.pi*0.5)
	sled.body:massbox(0.01,30,80,1)
	sled.body:autodisable(false)
	sled.body:lock(2,-20)

	local rudi = entity.new("rudizieher",10,0,2)
	local l3d = rudi:addl3d(loaddynamicmodel("reindeeranim.f3d",layer))
	rudi:addgeom(dgeombox.new(20,40,1),3)
	rudi:makebody()
	rudi.body:rotrad(0,0,-math.pi*0.5)
	rudi.body:massbox(0.01,30,80,1)
	--rudi.body:masstranslate(0,0,-10)
	rudi.body:autodisable(false)
	rudi.body:lock(2,-20)

	local anim = animation.load("reindeerwalk.ma",true,false)
	local atime = anim:length()
	l3d:seqAnimsource(0,0,anim)
	l3d:seqAnimstart(0,0,0)
	l3d:seqAnimlength(0,0,atime)
	l3d:seqOffset(0,0)
	l3d:seqLoop(0,true)
	l3d:seqState(0,1)

	balljoint = djointhinge.new()
	balljoint:attach(rudi.body,sled.body)
	balljoint:anchor(50,0,0)
	balljoint:axis(0,1,0)
	balljoint:histop(0.3)
	balljoint:lostop(-0.3)
	balljoint:cfm(0.8)

	function rudi.think(self)
		rudi.body:addforce(0.3,0,0, 10,0,0)
		local vx,vy,vz = rudi.body:velocity()
		vx,vy,vz = vx*0.7,vy*0.7,vz*0.7
		rudi.body:velocity(vx,vy,vz)
		local v = (vx*vx+vy*vy+vz*vz)^0.5
		l3d:seqSpeed(0,v*60)
		local x,y,z = rudi.body:pos()
		if (x>300) then
			rudi.body:pos(10,0,2)
			sled.body:pos(-50,0,2)
		end

	end

	local ropetex = texture.load("rope.tga")
	local ac1 = sled:getnewactor()
	ac1:linkbone(l3d,"Bip01 R Clavicle",
		matrix4x4.new({1,0,0,0,  0,1,0,0, 0,0,1,0, 0,5,0,1}))
	local ac2 = sled:getnewactor()
	ac2:linkbone(l3d,"Bip01 L Clavicle",
		matrix4x4.new({1,0,0,0,  0,1,0,0, 0,0,1,0, 0,5,0,1}))
	local acm = sled:getnewactor()
	acm:linkbone(l3d,"Bip01 Neck",
		matrix4x4.new({1,0,0,0,  0,1,0,0, 0,0,1,0, 4,3,0,1}))

	local r1 = sled:addl3d(l3dtrail.new("rope1",layer,5))
	r1:materialnormalized(true)
	r1:typeworldref(true)
	r1:facecamera(true)
	r1:matsurface(ropetex)
	r1:materialscale(60,1)
	local p1 = sled:getnewactor() p1:link(rring)
	local p2 = sled:getnewactor() p2:link(lring)

	r1:spawnworldref(p1,2)
	r1:spawnworldref(ac1,2)
	r1:spawnworldref(acm,2)
	r1:spawnworldref(ac2,2)
	r1:spawnworldref(p2,2)

	space:delete()
	space = dspacehash.new()
	space:add(entity.space)
	space:add(menulevel.space)

	menuison = true
	--_print("init background finished")
end

function exitmenu ()
	if (not menuison) then return end
	menulevel:cleanup()
	menulevel = nil
	menucamnode:delete()
	l3dcamera.default():frontplane(256)
	s3dintroanim:delete()
	l3dwmann:delete()
	l3dsled:delete()
	sledactor:delete()
	menuison = false
	space:remove(entity.space)
	entity.removeall()
	balljoint:delete()
end

menupage = {activepage = nil, onactivate = function () end}
function menupage.new (items, onactivate)
	local self = {}
	setmetatable(self,{__index = menupage})
	self.items = {}
	self.active = 1
	self.onactivate = onactivate
	self.cx,self.cy = 320,240
	if (items) then
		for i,v in pairs(items) do
			self:add(v[1],v[2],v[3],v.keylistener)
		end
	end
	local tex = texture.load("hud/border.tga",false)
	local bgtex = texture.load("holz/holzwand1.jpg",false)
	local shtex = texture.load("hud/shadowborder.tga",false)
	self.trail = l3dtrail.new("trailborder",layer,34)
	self.trail:matsurface(tex)
	self.trail:materialnormalized(true)
	self.trail:materialscale(60,1)
	self.trail:spawnstep(0)
	self.trail:facecamera(false)
	self.trail:size(3,6)
	self.trail:rfBlend(true)
	self.trail:rsBlendmode(blendmode.decal())

	self.l2ds = {}

	self.shtrail = l3dtrail.new("shadowtrail",layer,34)
	self.shtrail:matsurface(shtex)
	self.shtrail:materialnormalized(true)
	self.shtrail:materialscale(60,1)
	self.shtrail:spawnstep(0)
	self.shtrail:facecamera(false)
	self.shtrail:size(3,8)
	self.shtrail:rfBlend(true)
	self.shtrail:rsBlendmode(blendmode.modulate())
--	tex:clamp(true)

	self.quad = l3dtrail.new("background",layer,2)
	self.quad:matsurface(bgtex)
	self.quad:planarmap(2)
	self.quad:planarscale(0.01)
	self.quad:facecamera(false)
	self.quad:spawnstep(0)

	self.border = l2dnode3d.new("trailborder",self.trail)
	self.border:parent(l2dnode.getroot())
	self.border:sortid(5)
	self.bordershadow = l2dnode3d.new("trailborder",self.shtrail)
	self.bordershadow:parent(l2dnode.getroot())
	self.bordershadow:sortid(4)
	self.background = l2dnode3d.new("windowbackground",self.quad)
	self.background:parent(l2dnode.getroot())
	menupage.activepage = self
	return self
end

function menupage.think ()
	local self = menupage.activepage
	local lastkeys,lastcodes = Keyboard.getPressedKeys ()
	if (not self.visible) then return end

	for i,v in pairs(self.items) do
		if (v.keylistener) then
			for i,c in ipairs(lastcodes) do
				v:keylistener(c)
			end
		end
	end


	if (self.think~=menupage.think) then self:think() end
end

function menupage.addimage (self, img, x,y,w,h)
	local l2d = l2dimage.new(img,texture.load(img,false))
	l2d:parent(l2dnode.getroot())
	l2d:pos(x,y,5)
	l2d:scale(w,h,1)
	l2d:rfBlend(true)
	l2d:rsBlendmode(blendmode.decal())
	l2d:sortid(50)
	table.insert(self.l2ds,l2d)
	return l2d
end

function menupage.l2dpos (self,id,x,y,z)
	local px,py,pz = self.l2ds[id]:pos()
	x,y,z = x or px, y or py, z or pz
	self.l2ds[id]:pos(x,y,z)
end

function menupage.add (self, str, fn, arg, keylistener)
	local item = {text = str, len = string.len(str),
		fn = fn, l2d = l2dtext.new("item",str,xmasfont),
		l2dshadow = l2dtext.new("item",str,xmasfont),
		l2demboss = l2dtext.new("item",str,xmasfont),
		arg = arg,keylistener = keylistener}
	item.l2d:parent(l2dnode.getroot())
	item.l2d:spacing(12)
	item.l2dshadow:parent(l2dnode.getroot())
	item.l2dshadow:spacing(12)
	item.l2dshadow:color(0,0,0,1)
	item.l2dshadow:sortid(-1)
	item.l2demboss:parent(l2dnode.getroot())
	item.l2demboss:spacing(12)
	item.l2demboss:color(0,0,0,0.3)

	item.l2d:rfNodraw(true)
	item.l2demboss:rfNodraw(true)
	item.l2dshadow:rfNodraw(true)
	item.l2d:sortid(2)
	item.l2demboss:sortid(3)
	item.l2dshadow:sortid(1)
	table.insert(self.items,item)
end

function menupage.text (self,id,str)
	self.items[id].str = str
	self.items[id].len = string.len(str)
	self.items[id].l2d:text(str)
	self.items[id].l2demboss:text(str)
	self.items[id].l2dshadow:text(str)
	self:dolayout()
end

function menupage.dolayout (self)
	local h = 18
	local y = self.cy - table.getn(self.items)*h*0.5
	local cx,cy = self.cx,240
	local mw,mh = 0,h*table.getn(self.items)
	for i,v in ipairs(self.items) do
		if (self.active == i) then
			v.l2d:color(1,0,0,1)
		else
			v.l2d:color(1,1,1,1)
		end
		local w = v.len*v.l2d:spacing()
		local x = cx-w*0.5
		v.l2d:pos(x,y,0)
		v.l2demboss:pos(x+1,y+1,0)
		v.l2dshadow:pos(x+2,y+2,0)
		y = y+h
		mw = math.max(mw,w)
	end
	local len = mw*2+mh*2

	mw = mw*0.5+10
	mh = mh*0.5+10

	--self.quad:pos(cx-mw-5,cy-mh-5,0)
	--self.quad:scale(mw*2+10,mh*2+10,1)
	self.quad:spawn(cx,cy-mh-5,-2,0,0,1)
	self.quad:spawn(cx,cy+mh+5,-2,0,0,1)
	self.quad:size(3,mw+10)

	local shx,shy = 4,4
	local tx,ty = cx-mw,cy-mh
	local z = 1
	local offset = math.pi

	self.trail:spawn(cx-mw-8,cy,z,0,0,1)
	self.shtrail:spawn(cx-mw-8+shx,cy+shy,z,0,0,1)
	self.trail:materialscale(math.floor(len/10),1)

	for i=1,8 do
		local phi = math.pi/16*i
		local c,s = math.cos(phi),math.sin(phi)
		self.trail:spawn(tx-c*8,ty-s*8,z,0,0,1)
		self.shtrail:spawn(tx-c*8+shx,ty-s*8+shy,z,0,0,1)
	end
	local tx,ty = cx+mw,cy-mh
	for i=1,8 do
		local phi = -math.pi/16*i + math.pi*0.5
		local c,s = math.cos(phi),math.sin(phi)
		self.trail:spawn(tx+c*8,ty-s*8,z,0,0,1)
		self.shtrail:spawn(tx+c*8+shx,ty-s*8+shy,z,0,0,1)
	end
	local tx,ty = cx+mw,cy+mh
	for i=1,8 do
		local phi = -math.pi/16*i + offset
		local c,s = math.cos(phi),math.sin(phi)
		self.trail:spawn(tx-c*8,ty+s*8,z,0,0,1)
		self.shtrail:spawn(tx-c*8+shx,ty+s*8+shy,z,0,0,1)
	end
	local tx,ty = cx-mw,cy+mh
	for i=1,8 do
		local phi = -math.pi/16*i + math.pi*0.5
		local c,s = math.cos(phi),math.sin(phi)
		self.trail:spawn(tx-c*8,ty+s*8,z,0,0,1)
		self.shtrail:spawn(tx-c*8+shx,ty+s*8+shy,z,0,0,1)
	end
	self.trail:spawn(cx-mw-8,cy,z,0,0,1)
	self.shtrail:spawn(cx-mw-8+shx,cy+shy,z,0,0,1)
end

function menupage.activate(self)
	self = self or menupage.activepage
	menupage.activepage:deactivate()
	for i,v in ipairs(self.items) do
		v.l2d:rfNodraw(false)
		v.l2demboss:rfNodraw(false)
		v.l2dshadow:rfNodraw(false)
	end
	for i,v in ipairs(self.l2ds) do
		v:rfNodraw(false)
	end
	menupage.activepage = self
	self.border:rfNodraw(false)
	self.bordershadow:rfNodraw(false)
	self.quad:rfNodraw(false)
	self:dolayout()
	self.visible = true
	self:onactivate()
end

function menupage.deactivate(self)
	self = self or menupage.activepage
	for i,v in ipairs(self.items) do
		v.l2d:rfNodraw(true)
		v.l2demboss:rfNodraw(true)
		v.l2dshadow:rfNodraw(true)
	end
	for i,v in ipairs(self.l2ds) do
		v:rfNodraw(true)
	end
	self.border:rfNodraw(true)
	self.quad:rfNodraw(true)
	self.bordershadow:rfNodraw(true)
	self.visible = false
end

function menupage.up ()
	local self = menupage.activepage
	if (not self.visible) then return end
	self.active = self.active>1 and self.active - 1 or table.getn(self.items)
	if (self.items[self.active].fn==nil) then
		return self:up()
	else
		self:dolayout()
	end
end

function menupage.down ()
	local self = menupage.activepage
	if (not self.visible) then return end
	self.active = self.active<table.getn(self.items) and self.active + 1 or 1
	if (self.items[self.active].fn==nil) then
		return self:down()
	else
		self:dolayout()
	end
end

function menupage.action ()
	local self = menupage.activepage
	if (self.visible) then
		self.items[self.active].fn(self,self.active)
	end
end


loadfile("resource.lua")()
dofile("scripts/level.lua")
dofile("scripts/xmasgame.lua")
dofile("scripts/leveleditor.lua")
dofile("scripts/vehicles.lua")

dofile("scripts/hud.lua")


menu = menupage.new ({
		{"New Game",function () menupage.deactivate() exitmenu() createxmasgame() end},
		{"Highscore",function () menupage.deactivate() scoremenu:activate() end},
		{"Help",function () helpmenu:activate() end},
		{"Leveleditor",function () menupage.deactivate() exitmenu() leveleditor() end},
		{"Options",function () options:activate() end},
		{"cartest",function () cartestmenu:activate() end},
		{"About",function () about:activate() end},
		{"Quit",system.exit}
	}
)
menu:addimage("hud/present.tga",360,300,64,64)

resolutionmodes = {"640x480@16bpp","800x600@16bpp",
			"1024x768@16bpp","640x480@32bpp","800x600@32bpp",
			"1024x768@32bpp"}
weathermodes = {"off","simple","full"}
lightningmodes = {"off", "groundtiles", "full"}

options = menupage.new ( {
		{"resolution: ", function (self)
				self.resmode = self.resmode or window.res()
				self.resmode = self.resmode + 1
				self.resmode = self.resmode>5 and 0 or self.resmode
				self:text(1,"resolution: "..resolutionmodes[self.resmode+1])
			end},
		{"fullscreen: ", function (self)
			self.fullscreen = self.fullscreen or window.fullscreen()
			self.fullscreen = not self.fullscreen
			self:text(2,"fullscreen: "..tostring(self.fullscreen))
		end},
		{"lightning: "..lightningmodes[gameconfig.lightning],
			function (self)
				self.lightning = self.lightning or gameconfig.lightning
				self.lightning = math.mod(self.lightning,3)+1
				self:text(3,"lightning: "..lightningmodes[self.lightning])
			end},
		{"weather: "..weathermodes[gameconfig.weather],
			function (self)
				self.weather = self.weather or gameconfig.weather
				self.weather = math.mod(self.weather,3)+1
				self:text(4,"weather: "..weathermodes[self.weather])
			end},
		{"apply",function (self)
			if (self.resmode) then
				window.res(self.resmode)
			end
			if (self.fullscreen~=nil) then
				window.fullscreen(self.fullscreen)
			end
			if (self.resmode or self.fullscreen~=nil) then
				window.update()
			end
			if (self.lightning) then gameconfig.lightning = self.lightning end
			if (self.weather) then
				gameconfig.weather = self.weather
				if (self.weather<3) then snow.stop()
				else snow.start() end
			end
			self.resmode = nil
			self.fullscreen = nil
		end},
		{"back to mainmenu",function () menu:activate() end}
	}, function (self)
		self.resmode = nil
		self:text(1,"resolution: "..resolutionmodes[window.res()+1])
		self:text(2,"fullscreen: "..tostring(window.fullscreen()))
	end
)

do
	cartestmenu = menupage.new ({{"Cartest"},
		{"This demonstration shows a few of the"},
		{"capabilities of the Luxinia physics simulation."},
		{""},
		{"Continue", function () cartestmenu.deactivate() exitmenu() cartest() end},
		{"back to main menu", function () menu:activate() end},
		},function (self) end
	)
	cartestmenu.active=5
end

do
	about = menupage.new (nil, function (self) self:down() end)
	local abouttx = [[
Project Xmas
Version 1.0





by
Eike Decker
and
Christoph Kubisch

http://www.luxinia.de
	]]
	for line in string.gfind(abouttx,"(.-)\n") do
		about:add(line)
	end
	about:addimage("logo2.tga",320-32,160,64,64)
	about:add("back to mainmenu",function () menu:activate() end)
	about:deactivate()
end

do
	dofile("score.lua")
	scoremenu = menupage.new (nil, function (self) self:down()
		local s = getscores()
		for i,v in pairs(s) do
			scoremenu:text(i+1,string.format("%i. %s %i",i,s[i].name,s[i].points))
		end
	end)
	scoremenu:add("--- Highscores ---")

	local s = getscores()
	for i=1,10 do
		scoremenu:add(s[i] and string.format("%i. %s %i",i,s[i].name,s[i].points) or "---")
	end

	scoremenu:add("back to mainmenu",function () menu:activate() end)
end

do
	helpmenu = menupage.new (nil, function (self) self:down() end)
	local helptx = [[
Help

You are playing Santa Clause, and it is
christmas time. Santa has to deliver the
christmas presents to every house.

You can steer him with the arrow key
and you can drop presents to the chimneys
with the left control key.

Hit the chimneys
for points and make
no misses for more points.

If you make multiple hits quickly
you will get more bonus points.

If you are finished before the time runs out,
you will get a timebonus.

]]
	for line in string.gfind(helptx,"(.-)\n") do
		helpmenu:add(line)
	end

	helpmenu:addimage("hud/time.tga",80,300,32,32)
	helpmenu:addimage("hud/timearr.tga",80,300,32,32)
	helpmenu:addimage("help/drop.tga",480,220,160,160):rotdeg(0,0,-20)
	helpmenu:addimage("help/keys.tga",40,160,160,80):rotdeg(0,0,20)

	helpmenu:add("back to mainmenu",function () menu:activate()  end)
end

menu:activate()

Keyboard.setKeyBinding (Keyboard.keycode.UP,menupage.up)
Keyboard.setKeyBinding (Keyboard.keycode.DOWN,menupage.down)
Keyboard.setKeyBinding (Keyboard.keycode.ENTER,menupage.action)

initmenubackground ()

do
	local t = 0
	function thinkxmasmenu ()
		menupage.think()
		if (not menuison) then return end
		local cnt = 0
		while (t<luxinia.time() and cnt<10) do
			local x,y,z = menucamnode:pos()
			local vz = math.max(-0.5,(25-z)*0.01)
			menucamnode:pos(150,-200,vz+z)
			entity.thinkall()

			dworld.collidetest(space)
			dworld.makecontacts()
			dworld.quickstep(1)

			t = t + 5
			cnt = cnt +1
		end
		if (cnt==10) then t = luxinia.time() end
	end

	Timer.set("thinkxmasmenu",thinkxmasmenu)
end


--if (not edit) then
--	createxmasgame()
--else
--	leveleditor()
--end
