dofile("lua/modulenames.lua")
dofile("lua/datadumper.lua")
dofile("lua/keys.lua")
dofile("lua/monsters.lua")
dofile("lua/monsterstats.lua")
dofile("lua/story.lua")
dofile("lua/cfunctions.lua")
dofile("lua/levelnames.lua")
dofile("lua/levelgenerator.lua")
tmp_skeletonlist={}
tmp_zombilist={}
tmp_zspawnlist={}
tmp_bzombilist={}
tmp_brobotlist={}
tmp_soldierlist={}
tmp_bsoldierlist={}
tmp_turretlist={}
tmp_soldiertable={} --kustuta hiljem 'ra
tmp_itemspawntable={}
tmp_rareitemspawntable={}
rnddestructiontable={}
tmp_containertable={}
modlist={}
levelname=""

texturelist={}
spritelist={}
soundlist={}
objectlist={}
scripttable={}
recipetable={}

currenttransform={x=0,y=0,a=0}

do 
	local cSetBlend=SetBlend
	local blendmodes={}
	blendmodes["multiply"]=0
	blendmodes["add"]=1
	blendmodes["alpha"]=2
	blendmodes["solid"]=3
	blendmodes["mask"]=4
	blendmodes["mod2x"]=5
	
	function SetBlend(blend)
		cSetBlend(blendmodes[blend])
	end

	local cAddReaction=AddReaction
	function AddReaction(result,...)
		local recipe={}
		recipe.result=result
		recipe.ingredients={...}
		table.insert(recipetable,recipe)
		cAddReaction(result,...)
	end

end



function clamp(minval,maxval,val)
	if val<minval then val=minval end
	if val>maxval then val=maxval end
	return val
end
function LoadTexture(url,name)
	texturelist[name]=_LoadTexture(url,name)
end

function GetTexture(name)
	if texturelist[name]==nil then
		return 0
	else
		return texturelist[name]
	end	
end

function LoadSound(name,volume,...)
	soundlist[name]=_LoadSound(volume, ...)
end

function GetSound(name)
	if soundlist[name]==nil then
		return 0
	else
		return soundlist[name]
	end	
end


function AddStat(db,cat,name)
    local val=db[cat][name]
	if not val then val=0 end
	db[cat][name]=val+1
end

function ModifyValueClamp(value,increasebtn,decreasebtn,maxval,minval,step)
	if input.KeyDown(increasebtn) then value=value+step end
	if input.KeyDown(decreasebtn) then value=value-step end
	if value>maxval then value=maxval end
	if value<minval then value=minval end
	return value
end

function ModifyValueWrap(value,increasebtn,decreasebtn,maxval,minval,step)
	if input.KeyDown(increasebtn) then value=value+step end
	if input.KeyDown(decreasebtn) then value=value-step end
	if value>maxval then value=minval end
	if value<minval then value=maxval end
	return value
end

function ModifyChoiceWrap(choice,increasebtn,decreasebtn,maxval,minval)
	if input.KeyPressed(increasebtn) then choice=choice+1 end
	if input.KeyPressed(decreasebtn) then choice=choice-1 end
	if choice>maxval then choice=minval end
	if choice<minval then choice=maxval end
	return choice
end

function ModifyChoiceWrap2(choice,increasebtn,decreasebtn,maxval,minval)
	if input.KeyPressed2(increasebtn) then choice=choice+1 end
	if input.KeyPressed2(decreasebtn) then choice=choice-1 end
	if choice>maxval then choice=minval end
	if choice<minval then choice=maxval end
	return choice
end

function ModifyValueBool(value,btn)
	if input.KeyPressed(btn) then 
		if value==0 then value=1 else value=0 end
	end
	return value
end

function CreateSprite(name,texname,numx,numy,w,h,xoffset,yoffset)
	if xoffset==nil then xoffset=0 end
	if yoffset==nil then yoffset=0 end
	spritelist[name]=_CreateSprite(texname,numx,numy,w,h,xoffset,yoffset)
end

function GetSprite(name)
	if spritelist[name]==nil then
		return 0
	else
		return spritelist[name]
	end	
end

cbool={}
cbool[true]=1
cbool[false]=0

function SetDefault (t, d)
  local mt = {__index = function () return d end}
  setmetatable(t, mt)
end
function string:split(sep)
	local sep, fields = sep or ":", {}
	local pattern = string.format("([^%s]+)", sep)
	self:gsub(pattern, function(c) fields[#fields+1] = c end)
	return fields
end

function listFiles(path,ext)
	local list=_PrintDirectory(path)

	
	local split_list=list:split("\n");

	local retlist={}
			
	for k,v in pairs(split_list) do
		if string.find(v,"." .. ext,1,true) then
		table.insert(retlist,v)
		end
	end
	return retlist
end
testrot=0

do
	local cLoadLevel=LoadLevel
	LoadLevel=function(dir,preservestatus)
		preservestatus_=preservestatus		--v2ga kole. s2tib globaalse muutuja, et m2ngijale ei antaks neid asju.
--		ClearModules()0
	--	LoadModules()
		scripttable={}
		scripttable.EmergencyEffect=EmergencyEffect
		cLoadLevel(dir,preservestatus)
		levelname=dir
		SetDarkness(0)
	end
end

do 
	local cCreateNode=CreateNode
	CreateNode=function(x,y,a,typ)
--		if typ==nil then typ=0 end
		cCreateNode(x,y,a,typ)
		local tx,ty,ta=GetCreationTransform()
		local nx,ny=TransformPoint(x,y,tx,ty,ta)
		if typ==1 then
			table.insert(tmp_itemspawntable,{x=nx,y=ny})
		end
		if typ==2 then
			table.insert(tmp_rareitemspawntable,{x=nx,y=ny})
		end
	end
end

function table.find(value, l)
  for k, v in pairs(l) do
	if (v==value) then
      return k
    end
  end
  return nil
end

function toLuaEnum(enumtype,enum)
	return table.find(enum,_G[enumtype])
end

do 
	local cfunc=actor.GetAction
	actor.GetAction=function(a)
	local nr=cfunc(a)
	return table.find(nr,actions)
	end
end
	
function PlaceModule(x,y,a,modname)
	dofile("mods/"..modname..".lua")
	if modlist[modname] then
		SetCreationTransform(x,y,a)
		modlist[modname].CreateObjects()
		SetCreationTransform(0,0,0)
	else
		print("ERROR:Module " .. modname .. "does not exist\n")
	end
end

function RefreshModules()
	ClearModules()
	LoadModules()
end

function LoadModule(modname)
	local success,msg
	success,msg=pcall(function() dofile("./mods/" .. modname) end)
	if not success then
		console.Print("ERROR:"..msg)
	end
end

function LoadModules()
	ClearModules()
	modlist={}

	local modules=listFiles("./mods/","lua")
	for k,v in pairs(modules) do
		LoadModule(v)
	end

	for k,v in pairs(modlist) do
		AddModule(k)
	end
end

function PlaceAllModules()
	local mody=0
	for k,v in pairs(modlist) do
		mody=mody+v.h*0.6
	--	print("Placing module "..k.." at ".."0,"..mody.."\n")
		PlaceModule(0,mody,0,k)
		SetCreationTransform(0,0,0)
		CreateTextObj(v.h*0.6,mody,k)
	--	print("Done\n")
		mody=mody+v.h*0.6
	end
end

function table.copy(t)
	local t2 = {}
	for k,v in pairs(t) do
		t2[k] = v
	end
	return t2
end

function table.copyadd(src,dst)
	for k,v in pairs(src) do
		dst[k] = v
	end
end

function FormatTime(seconds)
	seconds=math.floor(seconds)
	local secpart=seconds%60
	local minpart=(seconds-secpart)/60
	if minpart>0 then 
		return string.format("%dm %ds",minpart,secpart) 
	else
		return string.format("%ds",secpart)
	end
end

function IntersectOBB(obb1,obb2)
	return _IntersectOBB(obb1.x,obb1.y,obb1.a,obb1.w,obb1.h,obb2.x,obb2.y,obb2.a,obb2.w,obb2.h)
end

--modules={"module1","module2"}
--itemlist["item_name"]=10
--rareitemlist["item_name"]=10
--enemylist["zombie"]=20
--deadendtable={"deadendmodule1","deadendmodule1"}

function AddToRndTable(ptr,name)
	if rnddestructiontable[name]==nil then
		rnddestructiontable[name]={}
		rnddestructiontable[name].count=0
	end
	table.insert(rnddestructiontable[name],ptr)		
end

function RandomField(tabl)
	local i=math.random(#tabl)
	local v=tabl[i]
	return i,v
end

function ForeachNamedObject(name,func,...)
	if scripttable[name] then
		for i,v in ipairs(scripttable[name]) do
			func(v,...)
		end
	else
		print("WARNING: object group named "..name.." is not defined\n")
	end
end

function DoTriggerScript(funcname)
	if scripttable[funcname] then
		local co=coroutine.create(scripttable[funcname])
		coroutine.resume(co)
	else
		print("ERROR:function "..funcname.." not found!\n")
	end
end

function Wait(seconds)
	local co=coroutine.running()
	_Wait(co,seconds*30)
	coroutine.yield(co)
end

function _Resume(co)
	coroutine.resume(co)
end

function table.shuffle(tt)
	local n=#tt
 
	while n>=2 do
		local k=math.random(n)
		tt[n],tt[k]=tt[k],tt[n]
		n=n-1
	end
	return tt
end

function string.starts(String,Start)
   return string.sub(String,1,string.len(Start))==Start
end

function CreateObject(x,y,a,name)
	return objectlist[name].createfunction(x,y,a,name)
end


function table.find2(tbl,fn)
	local returntable={}
	for k,v in pairs(tbl) do
		if fn(v) then
			table.insert(returntable,v)
		end
	end
	return returntable
end

function table.contains(tbl,val)
	for k,v in pairs(tbl) do
		if v==val then return true end
	end
	return false
end

function WordWrap(str, limit, indent, indent1)
	indent = indent or ""
	indent1 = indent1 or indent
	limit = limit or 72
	local here = 1-#indent1
	return indent1..str:gsub("(%s+)()(%S+)()",
							function(sp, st, word, fi)
								if fi-here > limit then
									here = st - #indent
									return "\n"..indent..word
								end
							end)
end

function Reflow(str, limit, indent, indent1)
	
	return (str:gsub("%s*\n%s+", "\n")
             :gsub("%s%s+", " ")
             :gsub("[^\n]+",
					function(line)
						return WordWrap(line, limit, indent, indent1)
					end))
end

for k,v in pairs(storytable) do
	storytable[k]=Reflow(v,60)
end

function BeginIntro()
	DisableHUD()
	DisableInput()
	HidePlayer()
end

function EndIntro()
	EnableInput()
	EnableHUD()
end

function StandardIntro()
	PlaySound("teleporter")
	BeginIntro()
	pl=player.GetPlayer()
	local x,y=pl:GetPosition()
	for i=0,50,1.2 do
		Distort(x,y,math.random(-i*3,i*3),math.random(-i*3,i*3),i/8,0)
		Distort(x,y,math.random(-i*3,i*3),math.random(-i*3,i*3),i/8,1)
		Distort(x,y,math.random(-i*3,i*3),math.random(-i*3,i*3),i/8,2)
		Wait(0)
	end
	for i=0,3,1 do
		DistortFlash(2)
		Distort(x,y,math.random(-i*300,i*300),math.random(-i*300,i*300),2+i*2,0)
		Distort(x,y,math.random(-i*300,i*300),math.random(-i*300,i*300),2+i*2,1)
		Distort(x,y,math.random(-i*300,i*300),math.random(-i*300,i*300),2+i*2,2)
		Wait(0.2)
	end
	ShowPlayer()
	EndIntro()
	for i=0,7,1 do
		Distort(x,y,math.random(-100,100),math.random(-100,100),3/2,2)
		Wait(0.1+math.random()*0.3)
	end
	Wait(1.5)
	if levelnames[levelname] then ShowSmallMessage(levelname..": "..levelnames[levelname]) end

end

function StandardOutro()
	DisableInput()
	pl=player.GetPlayer()
	local x,y=pl:GetPosition()
	Wait(0.25)
	
	PlaySound("teleporter_l6pp")
	HidePlayer()
	DisableHUD()
	Distort(x,y,math.random(-900,900),math.random(-900,900),8,0)
	Distort(x,y,math.random(-900,900),math.random(-900,900),8,1)
	Distort(x,y,math.random(-900,900),math.random(-900,900),8,2)
	DistortFlash(3)
	for i=0,7,1 do
		Distort(x,y,math.random(-100,100),math.random(-100,100),3/2,2)
		Wait(0.1+math.random()*0.3)
	end

	for darkness=0,1.1,0.04 do
		Wait(0)
		SetDarkness(darkness)
	end
	
end

function EmergencyEffect()
	DisableInput()
	pl=player.GetPlayer()
	local x,y=pl:GetPosition()
	HidePlayer()
	DisableHUD()
	DisableInput()
	Wait(0.25)
	PlaySound("teleporter_l6pp")
	Distort(x,y,math.random(-900,900),math.random(-900,900),8,0)
	Distort(x,y,math.random(-900,900),math.random(-900,900),8,1)
	Distort(x,y,math.random(-900,900),math.random(-900,900),8,2)
	DistortFlash(3)
	ShowPlayer()
	EnableHUD()
	EnableInput()
	for i=0,7,1 do
		Distort(x,y,math.random(-100,100),math.random(-100,100),3/2,2)
		Wait(0.1+math.random()*0.3)
	end
end

function FinalTeleport()
	StandardOutro()
	Wait(0.2)

	if levelendtexts[levelname] then
		ShowMessage(levelendtexts[levelname]) 
	end
	Wait(0)
	AddCompletedLevel()
	menu.SetState("mainmenu")
	menu.DisableGameState()
end

function TeleportToLevel(level)
	StandardOutro()
	Wait(0.2)

	if levelendtexts[levelname] then
		ShowMessage(levelendtexts[levelname]) 
	end
	Wait(0)
	AddCompletedLevel()
	LoadLevel(level,1)
end

function ShowMessageDelay(message)
	DisableInput()
	Wait(0.3)
	ShowMessage(message)
	EnableInput()
end
LoadSettings()
