unittest = {}
dofile("constants.lua")
dofile("app.lua")
dofile("configs.lua")

app.initGarbageCollect()

-- GLOBALS
window = {width = 0, height = 0}

dofile("lib/lib.lua")
dofile("state.lua")
dofile("system.lua")
dofile("sprites.lua")
dofile("defs/color_defs.lua")
dofile("states/musicstate.lua")
dofile("states/gamestate.lua")
dofile("states/menustate.lua")
dofile("states/inputstate.lua")

dofile("systems/systems.lua")

dofile("classes/classes.lua")

math.initRandom()

dofile("strict.lua")

local function mainInit()
	for index, func in pairs(unittest) do
		func()
	end
	-- parse commandLine
	cmdLine.parse()
	
	-- init app
	app.init()
	
	-- init window
	window.init()

	-- init canvas
	canvas.setToWindow()
	
	--init tiles
	entities.init()
	items.init_rules()
	rule_entities.init()
	tiles.init()

	sprites.init()

	-- init fonts
	fonts.init()
	
	-- init render helpers
	video.initHelpers()
	
	-- init configs
	if DEFAULT_CONFIG then
		config.load(_args.config or "config", DEFAULT_CONFIG, _config)
	end
	
	if DEFAULT_DEBUG then
		config.load(_args.debugConfig or "debug", DEFAULT_DEBUG, DEBUG)
	end

	-- init token
	if not _config.token then
		_config.token = string.randomText(10)
	end
	
	local inputState = states.add(InputState:new(), "input")
	states.protect("input")
	states.hide("input")
	inputs.init()

	-- init sound
	audio.setOpenAlDistanceModel(6)
	audio.setGlobalRolloffFactor(1)
	audio.setSoundListenerOrientation(0, 0, 1, 0, -1, 0)
	
	-- init music
	local musicState = states.add(MusicState:new(), "music")
	states.protect("music")
	states.hide("music")
	
	-- init app starting point
	states.add(MenuState:new(), "menu")
	--Or use game directly?
	--states.add(GameState:new(), "game")
end

hook.add("gameInit", mainInit)

local function mainUpdate(time)
	if debug.enterUpdate(time) then
		app.collectGarbage(time)
		return
	end
	
	app.update(time)	
		
	debug.enterGc()

	app.collectGarbage(time)
	
	debug.exitUpdate(time)
end

hook.add("frameUpdate", mainUpdate)

local function mainRender()
	debug.enterRender()
	
	app.render()
	
	if app.started then
		debug.exitRender()
	end
	
	app.postRender()
end

hook.add("frameRender", mainRender)

local function keyCharacter(byte)
	if debug.keyCharacter(byte) then
		return
	end
	
	states.keyCharacter(byte)
end

hook.add("keyCharacter", keyCharacter)

local function keyPressed(key)
	--[[ ]] if debug then
	--[[ ]] 	debug.keyPressed(key)
	--[[ ]] end
	
	states.keyPressed(key)	
end

hook.add("keyPress", keyPressed)

local function mouseClick(x, y, button, clickCount)
	--[[ ]] if debug then
	--[[ ]] 	debug.mouseClicked(button)
	--[[ ]] end
	states.mouseClick(x, y, button, clickCount)
end

hook.add("mouseButton", mouseClick)

local function mainClose()
	
	config.saveAll()
	
	states.destroyAllForced()
	
	debug.onClose()
end

hook.add("gameClose", mainClose)

local function joyButtonPressed(joy, btn)
	--[[ ]] if debug then
	--[[ ]] 	debug.joyPressed(button)
	--[[ ]] end
	states.joyPressed(joy, btn)
end

hook.add("joystickButtonPressed", joyButtonPressed)

local function joyButtonReleased(joy, btn)
	states.joyReleased(joy, btn)
end

hook.add("joystickButtonReleased", joyButtonReleased)
