jin.filesystem.init()
jin.filesystem.mount(jin.cwd)

-------------------------------------------------------------------------
-- Config game
-------------------------------------------------------------------------

jin.config  = {} 
if jin.filesystem.exist("config.lua") then 
  xpcall(function()jin.config = require "config" end, function()end)  
end
jin.config.width    = jin.config.width    or 580 
jin.config.height   = jin.config.height   or 450 
jin.config.vsync    = jin.config.vsync    or true
jin.config.title    = jin.config.title    or ("jin v" .. jin.version)
jin.config.resizable  = jin.config.resizable  or false 
jin.config.fullscreen = jin.config.fullscreen or false
jin.config.fps    = jin.config.fps    or 60
jin.config.icon     = jin.config.icon     or ""

-------------------------------------------------------------------------
-- Default game loop
-------------------------------------------------------------------------

local function call(func, ...)
  if func then 
    return func(...)
  end
end

function jin.core.run()
  jin.graphics.reset()
  call(jin.core.onLoad)
  local dt = 0
  while jin.core.running() do
    for _, e in pairs(jin.event.poll()) do 
      if e.type == "KeyDown" then 
        jin.keyboard.set(e.key, true) 
      elseif e.type == "KeyUp" then 
        jin.keyboard.set(e.key, false)
      end
      call(jin.core.onEvent, e)
    end
    jin.time.step()
    dt = jin.time.getDelta()
    call(jin.core.onUpdate, dt)
    -- Screen is always cleared with full black
    jin.graphics.setClearColor(0, 0, 0, 0xff)
    jin.graphics.clear()    
    call(jin.core.onDraw)
    jin.graphics.present()
    jin.time.sleep(0.001)
  end
  call(jin.core.onQuit)
end

-------------------------------------------------------------------------
-- Boot game
-------------------------------------------------------------------------

-- Display error message.
local function onError(msg) 
  local err = "Error occurred:\n" .. msg .. "\n" .. debug.traceback()
  jin.log.error(err)
  jin.graphics.showWindow()
  jin.graphics.reset()
  jin.graphics.setClearColor(100, 100, 100, 255)
  jin.graphics.clear()
  jin.graphics.print(err, 5, 5)
  jin.graphics.present()
  while jin.core.running() do 
    for _, e in pairs(jin.event.poll()) do 
      if e.type == "Quit" then 
        jin.core.stop()
      end
    end
    jin.time.sleep(0.001)
  end
end

-- No game screen.
local function noGame()
  jin.graphics.showWindow()
  jin.graphics.reset()
  jin.graphics.setClearColor(100, 100, 100, 255)
  jin.graphics.clear()
  jin.graphics.print("No Game", 5, 5) 
  jin.graphics.present()
  while jin.core.running() do 
    for _, e in pairs(jin.event.poll()) do 
      if e.type == "Quit" then 
        jin.core.stop()
      end
    end
    jin.time.sleep(0.001)
  end
end

local function boot() 
  if jin.filesystem.exist("main.lua") then 
    call(function() 
      require"main" 
      jin.core.run()
    end)
  else
    noGame()
  end
end

-------------------------------------------------------------------------
-- Initialize sub systems
-------------------------------------------------------------------------

jin.audio.init()

jin.graphics.init(jin.config)

-------------------------------------------------------------------------
-- Start game
-------------------------------------------------------------------------

xpcall(boot, onError)

-------------------------------------------------------------------------
-- Destroy sub-systems
-------------------------------------------------------------------------

jin.graphics.destroy()

jin.audio.destroy()

-------------------------------------------------------------------------
-- Quit game
-------------------------------------------------------------------------

jin.core.quit()