_G.dt = 0
_G.time = 0
_G.realTime = 0
_G.timeScale = 1
_G.coroutines = {}
_G.print = function(msg)
	if msg == nil then
		_G.log.DLOG("nil\n")
	elseif type(msg) == "table" then
		_G.log.DLOG("table\n")
	else
		_G.log.DLOG(msg .. "\n")
	end
end

local timeStep = 0.01

print("Clock: " .. os.time())
math.randomseed(os.time())

print("Foo foo")
if _G.rootFolder ~= nil then
	local dofile_orig = _G.dofile
	_G.dofile = function(path)
		--print("Fixed dofile from path " .. _G.rootFolder .. path)
		return dofile_orig(_G.rootFolder .. path)
	end
	local loadfile_orig = _G.loadfile
	_G.loadfile = function(path)
		return loadfile_orig(_G.rootFolder .. path)
	end
else
	_G.rootFolder = ""
end

function _G.load()
	local path = _G.rootFolder .. "persistence"
	print("Try to open file " .. path .. " for reading")
	local f = io.open(path, "r")
	print("Loading persistence from " .. path)
	if f ~= nil then
		print("Found persistence")
		io.close(f)
		print("Dofile persistence")
		_G.persistence = dofile("persistence")
	end
	if _G.persistence == nil then
		print("Persistence was not found, create new one")
		_G.persistence = {}
	end
end
_G.load()

dofile("serializer.lua")
dofile("config.lua")
dofile("utils.lua")
dofile("keys.lua")
dofile("physics.lua")
dofile("input.lua")
--if _G.rootFolder == nil or _G.rootFolder == "" then _G.filemanager = dofile("filemanager.lua") end
local remainingDt = 0
--local lastUpdate = 0
local lastFPSReset = 0
local framesDuringThisSecond = 0
_G.framesPerSecond = 0
local levelToLoad

levelToLoad = "game.lua"

world = {}

local function updateCoroutines(entity)
	for k,v in pairs(entity) do
		if type(v) == "thread" then
			--setmetatable(_G, {__index = entity, __newindex = entity })
			local ok, errorMsg = coroutine.resume(v)
			if not ok then
				if errorMsg ~= "cannot resume dead coroutine" then
				  	print("Error in co-routine: " .. errorMsg)
				end
				entity[k] = nil
			end
		elseif (type(v) == "table") then
			updateCoroutines(v)
		end
	end
end

function _G.init()
	if levelToLoad ~= nil then
		print("Load level from init: " .. levelToLoad)
		local file = assert(loadfile("assets/scripts/" .. levelToLoad))
		local c = coroutine.create(file)
		table.insert(coroutines, c)
		updateCoroutines(coroutines)
		levelToLoad = nil
	end
end

_G.random = math.random()

function _G.update(dt)
	_G.random = math.random()
	--print(dt)
	--dt = math.min(dt, 0.1)
	_G.realTime = _G.realTime + dt
	local physicsDt = dt + remainingDt
	physicsDt = math.min(physicsDt, 0.1)
	_G.dt = dt * _G.timeScale
	_G.time = _G.time + _G.dt
	_G.lastUpdate = _G.realTime
	--print("DT: " .. dt)
	if _G.filemanager ~= nil then _G.filemanager.update() end
	if levelToLoad ~= nil then
		print("Load level in update: " .. levelToLoad)
		local file = assert(loadfile("assets/scripts/" .. levelToLoad))
		table.insert(coroutines, coroutine.create(file))
		levelToLoad = nil
	end

	framesDuringThisSecond = framesDuringThisSecond + 1
	if _G.realTime > lastFPSReset + 1 then
		_G.framesPerSecond = framesDuringThisSecond
		print("FPS: " .. _G.framesPerSecond .. " / " .. _G.realTime)
		framesDuringThisSecond = 0
		lastFPSReset = _G.realTime
	end

	if type(_G.world) == "table" then
		--while physicsDt * _G.timeScale - timeStep >= timeStep do
		--	physics.update(world, timeStep)
		--	--updateFixedUpdates(world, timeStep)
		--	--car:onFixedUpdate(timeStep)
		--	physicsDt = physicsDt - timeStep
		--end
		--cops:onUpdate()
		--car[1][1]:onUpdate()
		--print("Remaining: " .. remainingDt)
		--updateInputAcceleration(dt)
		--print("Dt: " .. _G.dt)
		updateCoroutines(coroutines)
		updateCoroutines(_G.world)
	end

	remainingDt = physicsDt
	--print(remainingDt)
	--gr_recompileShader("assets/shaders/pt2.vs", "assets/shaders/pt.ps")
end

function _G.save()
	--print("Saving to " .. _G.rootFolder .. "persistence")
	local f = assert(io.open(_G.rootFolder .. "persistence", "w"))
	--print("Dumping data")
	f:write(_G.DataDumper(_G.persistence))
	--print("Close file")
	f:close()
	--print("Save finished")
end

local function updateFixedUpdates(entity, dt)
	for k,v in pairs(entity) do
		if k == "onFixedUpdate" and type(v) == "function" then
			v(entity, dt);
		elseif (type(v) == "table") then
			updateFixedUpdates(v, dt)
		end
	end
end

function _G.loadLevel(level)
	levelToLoad = level
end
