svg_root = "badHotel_/assets/svg_assets/"
draworder = {}
runningCoroutines = {};

keyPressSubs = {}
function blud.key.pressedSubscribe(fn, object)
  table.insert(keyPressSubs, {fn, object})
end

-- utility for getting around tables
function findNode(rootNode, name)
  if rootNode.name == name then
    return rootNode
  else
    if type(rootNode) == "table" then
      for i, v in ipairs(rootNode) do
        found = findNode(v, name)
        if(found ~= false) then
          return found
        end
      end
    end
  end
  return false
end
scf = SteamCloudFile()
bg = bludGraphics();
bg:setBackground(30, 30, 30)
local loadStart = os.time()

dofile(blud.bundle_root .. "/badHotel_/imports.lua")
print("imports load time: ", os.time() - loadStart)

function buildScreenInfo()
  r_scale = 1
  ipad = ''
  if bg:getWidth() > 320 then
    r_scale = 2
  end
  if bg:getWidth() > 640 then
    ipad = '_ipad'
  end
  if bg:getWidth() > 768 then
    r_scale = 4
  end
  -- determine the ipad rect that fits within the display area
  -- if we are displaying in a landscape window
  if bg:getWidth() > bg:getHeight() then
    local screenRatio = 768/1024
    local heightRatio = bg:getHeight()/768
    letterboxWidth = bg:getHeight()*screenRatio
    r_scale = heightRatio*2
  end
  if bg:getWidth() > 320 then
    retina = true
  end
  if player then
    -- blank the background, so it gets reloaded
    player.currentBg = ""
  end
  if bludG then
    bludG:buildScreenInfo()
  end
end

sheetsToLoad = {{name="tiles", t='png'}, {name="enemies", t='png'}}
sheets = {}
sprites = {}

function loadSprites()
  spriteLoader = dofile(blud.bundle_root ..  "/badHotel_/setupSprites.lua")
  -- player.currentWorld = worlds[1]
  -- PlayState.setupUnderBg()
  for i,v in ipairs(sheetsToLoad) do
    sheets[v.name], sprites[v.name] = spriteLoader(v.name, v.t)
    if v.name == "enemies" then
      sheets[v.name]:setBlendMode(1)
    elseif v.t == 'png' then
      sheets[v.name]:setBlendMode(1)
    end
  end
  mainbg = {}
  -- setup the circle used for anti aliasing
  local svgObject = ObjectGroup()
  svgObject:setSheet(sheets['tiles'])
  svgObject:setCircle(sprites['tiles']['circleBlur.png'])
end

function playEffect(effect)
  pd:startList("fromOF")
  pd:addSymbol("sounds")
  pd:addSymbol(effect)
  pd:finish("fromOF")
end
function math.randomRange(min, max)
  return min + (math.random() * (max - min))
end
function math.round(num, idp)
  local mult = 10^(idp or 0)
  return math.floor(num * mult + 0.5) / mult
end

circle = bludImage()
circle:load(blud.bundle_root .. "/badHotel_/assets/circle.png")
line = bludLine(circle, 2);
LineBatch = class(function(o)
  o:clear()
  o.r = 0
  o.g = 0
  o.b = 0
end)
function LineBatch:setColor(r, g, b)
  self.r = r
  self.g = g
  self.b = b
end
function LineBatch:clear()
  self.batch = {}
end
function LineBatch:addLine(x1, y1, x2, y2)
  table.insert(self.batch, {x1=x1, y1=y1, x2=x2, y2=y2})
end
function LineBatch:draw()
  bg:setColor(self.r, self.g, self.b)
  for i, v in pairs(self.batch) do
    line:drawLine(v.x1, v.y1, v.x2, v.y2)
  end
end
lb = LineBatch();

TextBatch = class(LineBatch, function(o)
  LineBatch.init(o)
  o.smallBatch = {}
end)
function TextBatch:clear()
  LineBatch.clear(self)
  self.smallBatch = {}
end

function TextBatch:addText(output, x, y, ...)
  local arg = {...}
  small = arg[1]
  width = arg[2]
  line_height = arg[3]
  if small then
    table.insert(self.smallBatch, {output=output, x=x, y=y, r=self.r, g=self.g, b=self.b, w=width, line_height=line_height})
  else
    table.insert(self.batch, {output=output, x=x, y=y, r=self.r, g=self.g, b=self.b, w=width, line_height=line_height})
  end
end

function TextBatch:draw()
  for i, v in pairs(self.batch) do
    bg:setColor(v.r, v.g, v.b)
  end
  for i, v in pairs(self.smallBatch) do
    bg:setColor(v.r, v.g, v.b)
  end
end
function TextBatch:getHeight(text, width, lh, ...)
  local arg = {...}
  small = arg[1]
  if small then
  else
  end
  return nil
end
tb = TextBatch();


PI = 3.14159265
DEG_TO_RAD = 1/360*2*PI

-- reverse pacman
-- system data structure
--    * grid size
-- level data structure
--    * all below have 
--      * position (Vec2)
--      * velocity (Vec2)
--      * moveTo(Vec2)
--    * enemies
--    * players
--    * pellets
--    * goals

function lerp(start, stop, amt)
  return start + (stop-start) * amt;
end
if bludG == nil then
  bludG = bludGlobal()
  -- bludG:startRecording()
end
sounds = SoundBank()
--bb = bludShapeBatch(2000, 2);
--bbt = bludShapeBatch(2000, 2);

particles = ParticleSystems();


output = ""

score = 0

heightGridSize = 17


if pd == nil then
  pd = bludPd();
  local pdCount = 0
  pd.updateCallback = function()
    if pd:getBangs() > 0 then
      if mainState and mainState.substate and mainState.substate.sync then mainState.substate:sync() end
    end
    pd:clearBangs()
  end
end

function connectToGameKit()
  gk = bludGK();
  gk:connect(function()
    -- attempt to shoot off a leaderboard update
    if player then
      player.leaderboards:reportScores()
    end
  end);
end
if scf:isSteamConnected() then
  steamStats = SteamAchievements()
end
function drawRect(x, y, w, h, r, g, b)
  local c = {x, y, w, h}
  if not retina then for i,v in ipairs(c) do c[i] = v/2 end end
  local tl = {c[1], c[2]}
  local tr = {c[1]+c[3], c[2]}
  local bl = {c[1], c[2]+c[4]}
  local br = {c[1]+c[3], c[2]+c[4]}
  sheet:addCornerTile(sprites['tile']["white.png"], tl[1],tl[2], tr[1],tr[2], br[1],br[2], bl[1],bl[2], 4, r,g,b,255)
end
function gridQuantize(x, y)
  x = math.floor(x/hgridSize)*hgridSize
  y = math.floor(y/vgridSize)*vgridSize
  return x, y
end

if not analytics and bludAnalytics then
  analytics = bludAnalytics()
end

if not gk then
  --connectToGameKit()
end
render = bludRenderer();
player = PlayerModel();
retina = true;
loadSprites();
render:setSpriteSheet(sheets['tiles'])
render:setSpriteSheet(sheets['enemies'])
if SteamCloudFile and scf:isSteamConnected() then
  scf = SteamCloudFile()
  saveData = scf:getString("storage.lua");
  if saveData and loadstring(saveData) then
    saveData = assert(loadstring(saveData))();
    if saveData then
      player:loadFrom(saveData)
    end
  else
    print("couldn't find file")
  end
else
  saveData = persistence.load(blud.doc_root .. "storage.lua");
  if saveData then
    player:loadFrom(saveData)
  else
    print("couldn't find file")
  end
end

if not fullscreen[player["fullscreen"]+1][2] then
  bg:setWindowShape(resolutionOptions[player["resolution"]+1][2][1], resolutionOptions[player["resolution"]+1][2][2])
end
-- setup the screen
buildScreenInfo();


mainState = WrapperState(Group());
mainState:changeState(TitleScreenState())


includeOsc = true and bludOsc
if oscRec == nil and includeOsc then
  oscRec = Receiver();
  oscSender = bludOsc();
  oscSender:setup("localhost", 9002)
  oscPrint = function(s)
    local m = bludOscMessage();
    m:setAddress("/print")
    m:addStringArg(s)
    oscSender:sendMessage(m)
  end
end


function blud.draw()
  if mainbg then
    for i,v in ipairs(mainbg) do
      v:draw(bludG.camera.scroll.x, bludG.camera.scroll.y)
    end
  end
  if not webview then
    mainState:draw();
    bludG:draw();
    -- bb:draw();
  end
  if not webview then
    --bbt:draw();
    particles:draw()
  end
end
function blud.update(t)
  if oscRec then
    oscRec:update();
  end
  for i,v in pairs(sheets) do
    v:clear()
  end
  if not webview then
    if needsVideoRemove then
      videoCompleteRemove()
      needsVideoRemove = false
    end
    Tweener:update();
    -- bb:clear();
    --bbt:clear();
    lb:clear();
    tb:clear();
    for i,v in ipairs(sheetsToLoad) do
      if sheets[v] then
        sheets[v]:update(t)
      end
    end
    mainState:update();
    bludG:update(t);
    particles:update()
    pd.updateCallback()
  end
  for i=table.maxn(runningCoroutines),1,-1 do
    local v = runningCoroutines[i]
    if coroutine.status(v) == 'suspended' then
      print('resuming')
      print(coroutine.resume(v))
    elseif coroutine.status(v) == 'dead' then
      table.remove(runningCoroutines, i);
    end
  end
  -- force the screen to the correct resolution if necessary
  if not fullscreen[player["fullscreen"]+1][2] then
    bg:setWindowShape(resolutionOptions[player["resolution"]+1][2][1], resolutionOptions[player["resolution"]+1][2][2])
  end
end

function blud.touch.down(x, y, id)
  mainState:touchDown(x, y, id)
  bludG:touchDown(x, y, id)
  if videoPlaying and videoPlayedOnce then
    videoComplete()
  end
end
function blud.touch.moved(x, y, id)
  mainState:touchMoved(x, y, id)
  bludG:touchMoved(x, y, id)
end
function blud.touch.up(x, y, id)
  mainState:touchUp(x, y, id)
  bludG:touchUp(x, y, id)
end
function blud.mouse.moved(x, y)
  mainState:mouseMoved(x, y)
end
function blud.mouse.dragged(x, y, button)
-- print(mouse dragged)
-- do nothing when initially launching
  mainState:touchMoved(x, y, button)
end
function blud.mouse.pressed(x, y, button)
  mainState:touchDown(x, y, button)
-- print(mouse pressed)
-- do nothing when initially launching
end
function blud.mouse.released(x, y, button)
  mainState:touchUp(x, y, button)
-- print(mouse released)
-- do nothing when initially launching
end
function blud.dropped(file)
  mainState:changeState(SvgTestState(file))
end
function blud.gotFocus()
  bludG.last_t = bg:getMillis()/1000
end
function blud.exit()
  if SteamCloudFile and scf:isSteamConnected() then
    local playerdata = player:saveTo({})
    scf:writeString("storage.lua", DataDumper(playerdata))
  else
    local playerdata = player:saveTo({})
    for k,v in pairs(playerdata) do
      print(k,v)
    end
    print(playerdata)
    persistence.store(blud.doc_root .. "storage.lua", playerdata);
  end
end
function blud.key.pressed(key)
 print("key pressed: " .. key)
 -- do nothing when initially launching
 for i,v in ipairs(keyPressSubs) do
   v[1](v[2], key)
 end
end
function blud.windowResized(w, h)
end
-- seed the thing
math.randomseed(bludG:seedRandom())