--Funktsioonid, mida kutsutakse c++ poole pealt.

-------------------------------------------------
--STATISTIKAFUNKTSIOONID
-------------------------------------------------

function GetRandomDeathText()
	return deathtexts[math.random(#deathtexts)]
end

function StatsClear(scope)
	if scope=="level" then
		levelstats=CreateStatTable()
	elseif scope=="game" then
		gamestats=CreateStatTable()
	elseif scope=="all" then
		progress=CreateStatTable()
	end
end

function StatsSelectTable(scope)
	local tbl
	if scope=="level" then
		tbl=levelstats
	elseif scope=="game" then
		tbl=gamestats
	elseif scope=="all" then
		tbl=progress
	end
	return tbl
end

function _StatsAddMisc(db,fieldname,count)
	local v=db[fieldname]
	if not v then v=0 end
	db[fieldname]=v+count
end

function StatsAddMisc(fieldname,count)
	_StatsAddMisc(levelstats,fieldname,count)
	_StatsAddMisc(gamestats,fieldname,count)
	_StatsAddMisc(progress,fieldname,count)
end

function CreateStatTable()
	local tbl={}
	SetDefault(tbl,0)
	tbl.discoveredenemies={}
	tbl.discovereditems={}
	tbl.discoveredcombinations={}
	tbl.killedbyenemy={}
	tbl.story={}
	tbl.levels={}
	return tbl
end

local ammonames=
{
	[0]="auammo",
	[1]="ppammo",
	[2]="pyammo",
	[3]="rifle ammo",
	[4]="nailammo",
	[5]="laserammo",
	[6]="hvammo",
	[7]="expammo",
	[8]="teslaammo",
	[9]="revolverammo",
	[10]="cannonammo",
}

local fieldnames=
{
	"timescompleted",
	"avgtime",
	"endhealth",
	"secrets",
	"endarmor",
	"nline",
	"auammo",
	"ppammo",
	"pyammo",
	"rifle ammo",
	"nailammo",
	"laserammo",
	"hvammo",
	"expammo",
	"teslaammo",
	"cannonammo",
	"revolverammo",
}

function CreateLevelTable()
	local tbl={}
	tbl.items={}
	SetDefault(tbl.items,0)
	for k,v in pairs(itemtable) do
		tbl.items[k]=0
	end
	tbl.endhealth=0
	tbl.endarmor=0
	tbl.avgtime=0
	tbl.secrets=0
	tbl.timescompleted=0
	tbl.timesdead=0

	for i=0,10 do
		tbl[ammonames[i]]=0
	end
	return tbl
end

function AddCompletedLevel()
	if type(progress.levels)=="number" then progress.levels={} end
	if not progress.levels[levelname] then
		progress.levels[levelname]=CreateLevelTable()
	end
	
	local pl=player.GetPlayer()
	local tbl=progress.levels[levelname]

	local items=pl:GetInventory()
	
	for k,v in pairs(items) do
		tbl.items[v]=tbl.items[v]+1
	end
	
	tbl.endhealth=tbl.endhealth+pl:GetHealth()
	tbl.endarmor=tbl.endarmor+pl:GetArmor()
	tbl.avgtime=tbl.avgtime+levelstats.framesplayed
	tbl.secrets=tbl.secrets+levelstats.secretsfound
	tbl.timescompleted=tbl.timescompleted+1

	for i=0,10 do
		tbl[ammonames[i]]=tbl[ammonames[i]]+pl:GetAmmo(i)
	end
end

function AddFailedLevel()
	if type(progress.failedlevels)=="number" then progress.failedlevels={} end
	if not progress.failedlevels[levelname] then
		progress.failedlevels[levelname]=CreateLevelTable()
	end
	
	local pl=player.GetPlayer()
	local tbl=progress.failedlevels[levelname]

	local items=pl:GetInventory()
	
	for k,v in pairs(items) do
		tbl.items[v]=tbl.items[v]+1
	end
	
	tbl.endhealth=tbl.endhealth+pl:GetHealth()
	tbl.endarmor=tbl.endarmor+pl:GetArmor()
	tbl.avgtime=tbl.avgtime+levelstats.framesplayed
	tbl.secrets=tbl.secrets+levelstats.secretsfound
	tbl.timescompleted=tbl.timescompleted+1
	
	for i=0,10 do
		tbl[ammonames[i]]=tbl[ammonames[i]]+pl:GetAmmo(i)
	end
end


function PrintTestingStats(tbl,file)
	local sortfn=function (a, b) return a.name:upper() < b.name:upper() end
	local levels={}
	
	for k,v in pairs(progress.levels) do
		v.name=k
		table.insert(levels,v)
	end
	table.sort(levels,sortfn)

	file:write("null,")

	for k2,v2 in ipairs(levels) do
		file:write(v2.name..",")
	end
	file:write("\n")
	
	local sorteditemnames={}
	for k,v in pairs(itemtable) do 
		table.insert(sorteditemnames,k)
	end
	table.sort(sorteditemnames,function(a,b) return a:upper() < b:upper() end)
	
	for k,v in ipairs(fieldnames) do
		if v~="nline" then
			file:write(v..",")
			for k2,v2 in ipairs(levels) do
				file:write(string.format("%f,",v2[v]/v2["timescompleted"]))			
			end
		end
		file:write("\n")
	end

	file:write("\n")
	for k,v in ipairs(sorteditemnames) do
		file:write(v..",")
		for k2,v2 in ipairs(levels) do
			file:write(string.format("%f,",v2.items[v]/v2["timescompleted"]))			
		end
		file:write("\n")
	end
	file:write("\n")
end

function StatsRegisterKill(monstername)
	AddStat(levelstats,"discoveredenemies",monstername)
	AddStat(gamestats,"discoveredenemies",monstername)
	AddStat(progress,"discoveredenemies",monstername)
end

function PrintProgress()
	print(table.tostring(progress))
end
function StatsRegisterStory(label)
	AddStat(progress,"story",label)
end

function StatsRegisterItem(itemname)
	AddStat(progress,"discovereditems",itemname)
	AddStat(levelstats,"discovereditems",itemname)
end

function StatsRegisterCombination(itemname)
	AddStat(progress,"discoveredcombinations",itemname)
end


function StatsGetKillString(scope)
	local tbl=StatsSelectTable(scope)
	local str=""
	for k,v in pairs(tbl.discoveredenemies) do
		if enemyhelptable[k] then
			str=str..string.format("%-20s:%d\n",enemyhelptable[k].shortname,v)
		else
			print("Enemy named "..k.." not found\n")
		--			str=str..string.format("%-20s:%d\n",k,v)
		end
	end
	return str
end

function GetOutroText(levelname)
	return levelendtexts[levelname] or ""
end
function StatsGetString(scope)
	local tbl=StatsSelectTable(scope)
	local str=""
	str=str..string.format("Time                :%s\n"    ,FormatTime(tbl.framesplayed/30))
	str=str..string.format("Accuracy            :%.2f%%\n",(tbl.bulletshit/tbl.bulletsshot)*100)
	str=str..string.format("Items combined      :%d\n" ,tbl.itemscombined)
	if scope=="all" then
		str=str..string.format("Secrets found       :%d\n" ,tbl.secretsfound)
	else
		str=str..string.format("Secrets found       :%d/%d\n" ,tbl.secretsfound,tbl.secretsgenerated)
	end
	str=str.."\nKILLS:\n"
	str=str..StatsGetKillString(scope)
	return str
end

-------------------------------------------------
--ENTSYKLOPEEDIA RENDERDAMINE
-------------------------------------------------

function RenderScrollBar(x1,x2,starty,maxy)
	local y1=-starty/maxy*240
	local y2=(-starty+240)/maxy*240
	DrawRect(x1,y1,x2,y2,1,0.1,0.1,0.1,0.5)
end

function RenderItemHelp(starty)
	local y=37
	local sortfn=function (a, b) return a.invtext:upper() < b.invtext:upper() end
	local sorteditemtable={}
	for k,v in pairs(itemtable) do
		v.key=k
		table.insert(sorteditemtable,v)
	end
	table.sort(sorteditemtable,sortfn)

	local spritescale=7*4/9
	local spriteoffsetx=13+7*2
	local spriteoffsety=7*2-7
	for i,v in ipairs(sorteditemtable) do
		local isdiscovered=progress.discovereditems[v.key]
		--kirjeldus
		if isdiscovered then
			SetColor(v.r,v.g,v.b,1)
			DrawText(54,starty+y,v.invtext)
			SetColor(1,1,1,1)
			DrawText(56,starty+y+7,v.longtext)
			DrawRect(13,starty+y-7,13+7*4,starty+y+7*4-7,1,0.1,0.1,0.1,0.5)
			
			DrawSprite(v.sprite,spriteoffsetx,starty+y+spriteoffsety,
			0,v.frame,spritescale,spritescale)
		else
			SetColor(32/255,32/255,32/255,1)
			DrawText(54,starty+y,Encrypt(v.invtext))
			DrawText(56,starty+y+7,Encrypt(v.longtext))
			DrawRect(13,starty+y-7,13+7*4,starty+y+7*4-7,1,0.1,0.1,0.1,0.5)
			DrawSprite("spr_asjad",spriteoffsetx,starty+y+spriteoffsety,
			0,48,spritescale,spritescale)
		end
		y=y+7*3
		--retseptid
		--leia sobivad retseptid:
		key=v.key
		local recipes=table.find2(recipetable,function(r) return r.result==key end)
		local recipes2=table.find2(recipetable,function(r) return table.contains(r.ingredients,key)end)
		--et retseptid, kus asi on resultaat oleksid eespool ja alles peale seda tuleksid muud.
		for i2,v2 in pairs(recipes2) do
			table.insert(recipes,v2)
		end
		--joonista
		for i2,v2 in ipairs(recipes) do
			local result=itemtable[v2.result]
			y=y+7
			local x=56
			local first=true
			local combtable={}
			if progress.discoveredcombinations[v2.result] then
				for k3,v3 in pairs(v2.ingredients) do
					local foundintable=false
					for k4,v4 in pairs(combtable) do
						if v4.name==v3 then
							v4.count=v4.count+1
							foundintable=true
							break
						end
					end
					if foundintable==false then
						table.insert(combtable,{name=v3,count=1})
					end
				end
				for k3,v3 in pairs(combtable) do
					local part=itemtable[v3.name]
					if not first then
						SetColor(1,1,1,1)
						DrawText(x,starty+y,"+")
						x=x+4
					end
					first=false
					SetColor(part.r,part.g,part.b,1)
					if v3.count>1 then
						SetColor(1,1,1,1)
						DrawText(x,starty+y,v3.count.."x")
						x=x+8
						SetColor(part.r,part.g,part.b,1)
						DrawText(x,starty+y,part.invtext)
					else
						DrawText(x,starty+y,part.invtext)
					end
					x=x+40
				end
				SetColor(1,1,1,1)
				DrawText(x,starty+y,"->")
				x=x+8
				SetColor(result.r,result.g,result.b,1)
				DrawText(x,starty+y,result.invtext)
			else
				local cnctable={}
				for k3,v3 in pairs(v2.ingredients) do
					local part=itemtable[v3]
					table.insert(cnctable,part.invtext)
					table.insert(cnctable,"+")
					SetColor(32/255,32/255,32/255,1)
					DrawText(56,starty+y,Encrypt(table.concat(cnctable)))
				end
			end
		end
		y=y+7*3
	end
	return y
end


function DrawArmorText(x,y,armor)
	local text="NONE"
	local r=0.56
	local g=0.56
	local b=0.56
	if armor>0 then   text="LIGHT"  r=0.4  g=0.47 b=0.33 end
	if armor>80 then  text="MEDIUM" r=0.85 g=0.6  b=0.25 end
	if armor>999 then text="HEAVY"  r=0.9  g=0.41 b=0.45 end
	SetColor(r,g,b,1)
	DrawText(x+7*4,y,text)
	SetColor(1,1,1,1)
	DrawText(x,y,"Armor:")
end

function RenderEnemyHelp(starty)
	local y=30
	local sortfn=function (a, b) return a.key:upper() < b.key:upper() end
	local sortedenemytable={}
	for k,v in pairs(enemyhelptable) do
		v.key=k
		table.insert(sortedenemytable,v)
	end
	table.sort(sortedenemytable,sortfn)

	local spritescale=7*4/30
	local spriteoffsetx=13+7*2
	local spriteoffsety=7*2-7

	local anythingshown=false
	for i,v in ipairs(sortedenemytable) do
		if progress.discoveredenemies[v.key] then
			anythingshown=true
			DrawRect(13,starty+y-7,13+7*4,starty+y+7*4-7,1,0.1,0.1,0.1,0.5)
			DrawSprite("spr_kollide_display_pildid",spriteoffsetx,starty+y+spriteoffsety,0,v.frame,
			spritescale,spritescale)

			DrawText(53,starty+y,v.officialname)
			y=y+7
			DrawText(56,starty+y,"\"" .. v.shortname .. "\"")
			y=y+7
		--	DrawText(56,starty+y,"Health: "..monsterstats[v.key].health)
			y=y+7
			DrawArmorText(56,starty+y,monsterstats[v.key].armor)
			y=y+7			
			SetColor(1,1,1,1)
			DrawText(56,starty+y,v.description)
			if not v.texth then
				_,v.texth=TextSize(v.description)
			end
			y=y+v.texth+7*2
		else
			_=nil
		end
	end

	if not anythingshown then
		DrawText(7,starty+y,"Nothing to show yet. Press [esc] to close")
		return 240
	end
	return y
end

currentstory=1
viewlist=true
function RenderStoryHelp(starty)
	local y=30
	local y2=25
	local sortfn=function (a, b) return a.title:upper() < b.title:upper() end
	local sortedstorytable={}
	if not viewlist and input.AnyKeyPressed() then
		viewlist=true
		input.ResetASCII()
		input.ResetKey("use")
		input.ResetKey2("escape")
		input.ResetKey2("enter")
	end

	for k,v in pairs(storytable) do
		if progress.story[k] then 
			table.insert(sortedstorytable,{title=k,text=v}) 
		end
	end
	table.sort(sortedstorytable,sortfn)

	if #sortedstorytable==0 then
		DrawText(7,starty+y,"Nothing to show yet. Press [esc] to close")
		return 240
	end

	if (input.KeyPressed("enter")or input.KeyPressed2(settings.keys.use)) and #sortedstorytable>0 then
		viewlist=false
	end

	if viewlist then
		for i,v in ipairs(sortedstorytable) do
			if currentstory==i then 
				local gray2=63/255
				DrawRect(2+2,starty+y2-1,5+2+v.title:len()*4,starty+y2+7,1,gray2,gray2,gray2,1)		--heledam kast
				DrawRect(3,starty+y2-1,5,starty+y2+7,1,107/255,145/255,250/255,1) --sinine joon
				SetColor(1,1,1,1) 
			else 
				SetColor(0.5,0.5,0.5,1) 
			end
			DrawText(5+2,starty+y2,v.title)
			y2=y2+8
		end
		currentstory=ModifyChoiceWrap(currentstory,"down","up",#sortedstorytable,1)
		currentstory=ModifyChoiceWrap2(currentstory,settings.keys.down,settings.keys.up,#sortedstorytable,1)
	else
		SetColor(1,1,1,1)
		local v=sortedstorytable[currentstory]
		if v then
			DrawText(7,25,v.title)
			DrawText(7,44,v.text)
		end
	end
	return 240
end


function SetProgressmt()
	if not progress then
		console.Print("ERROR:loading player progress failed!\n")
		StatsClear("all")
	end
	SetDefault(progress,0)
	local newitem=function(t,key,value)
		rawset(t, key, value)
		ShowSmallMessage("ITEM DATABASE UPDATED")
	end
	local newenemy=function(t,key,value)
		rawset(t, key, value)
		ShowSmallMessage("MONSTER DATABASE UPDATED")
	end
	local newstory=function(t,key,value)
		rawset(t, key, value)
		ShowSmallMessage("TEXT DATABASE UPDATED")
	end

	setmetatable(progress.discovereditems,{__newindex=newitem})
	setmetatable(progress.discoveredcombinations,{__newindex=newitem})
	setmetatable(progress.discoveredenemies,{__newindex=newenemy})
	setmetatable(progress.story,{__newindex=newstory})
end

function RegisterObject(obj,tablename)
	if not scripttable[tablename] then
		scripttable[tablename]={}
	end
	table.insert(scripttable[tablename],obj)
	obj:SetName(tablename)
end
	
function UnRegisterObject(object,tablename)
	local tbl=scripttable[tablename]
	for k,v in ipairs(tbl) do
		if v.pointer==object.pointer then
			table.remove(tbl,k)
			break
		end		
	end
end

function SaveSettings()
	local file=io.open("settings.lua","w")
	local settingstable=table.tostring(settings)
	file:write("settings="..settingstable)
	file:close()
	
	local file = io.open("stats.csv","w")
	PrintTestingStats(progress.levels,file)
	PrintTestingStats(progress.failedlevels,file)
	file:close()
end

function LoadSettings()
	local fn,err=loadfile("settings.lua")
	if not fn then
		print("Error loading settings: "..err)
		settings={}
	else
		fn()
	end
end

function GetMaxItemsInStack(itemtype)
	if not itemtable[itemtype] then return 1 end
	if not itemtable[itemtype].stack then return 1 end
	return itemtable[itemtype].stack
end

function godmode(onoff)
	local pl=player.GetPlayer()
	pl:SetInvulnerable(onoff)
end

function ItemFound(itemname)
	return progress.discovereditems[itemname] or 0
end