local sti = require 'engine/libs/sti'
local ui = require 'engine/ui'
local bump = require 'engine/libs/bump'

Level = class('Level')

Level.controllers = {}

function Level:init(name)
    Level:load(name)
end

function Level:update(dt)
    self.map:update(dt)

    for _, controller in ipairs(self.controllers) do
      controller.animation:update(dt)
    end
end

function Level:draw(dt)
    local translateX = 0
    local translateY = 0

    -- Draw Range culls unnecessary tiles
    self.map:setDrawRange(
        translateX,
        translateY,
        love.graphics.getWidth(),
        love.graphics.getHeight())

    self.map:draw()
    ui:draw()

    -- debugging
    -- self.map:bump_draw(self.bumpworld)
end

function Level:showMessage(message)
    ui:showMessage(message)
end

function Level:checkObjectAnimation(input)
    for _, controller in ipairs(self.controllers) do
        if controller.info.relevantInputs then
            for _, relevantInput in ipairs(controller.info.relevantInputs) do
                if relevantInput == input then
                    controller:stopAnimation()
                end
            end
        end
    end
end

function Level:checkObjectKeys(dt, input)
    if not ui.active then
        for _, controller in ipairs(self.controllers) do
          if controller.info.relevantInputs then
            for _, relevantInput in ipairs(controller.info.relevantInputs) do
              if relevantInput == input then
                controller:sendMovement(input)
                break
              end
            end
          end
        end
    else
        for _, relevantInput in ipairs(ui.relevantInputs) do
            if relevantInput == input then
                ui:sendInput(input)
            end
        end
    end
end

function Level:load(name)
    local mapName = 'levels/' .. name

    self.map = sti.new(mapName, { 'bump' })
    self.bumpworld = bump.newWorld()
    self.map:bump_init(self.bumpworld)

    Level:initObjects()
end

function Level:startAnimate(objectName, animationName)
  for _, controller in ipairs(self.controllers) do
    if controller.info.name == objectName then
      controller:startAnimation(animationName)
      break
    end
  end
end

function Level:stopAnimate(objectName)
    for _, controller in ipairs(self.controllers) do
        if controller.info.name == objectName then
            controller:stopAnimation()
            break
        end
    end
end

function Level:initObjects()
      self.controllers = {}

      self.map:addCustomLayer('object layer', 5)

      local objectLayer = self.map.layers['object layer']
      objectLayer.controllers = {}

      for _, obj in pairs(self.map.layers['objects'].objects) do
          if obj.properties.has_controller then
              local filename = 'objects/' .. obj.name .. '.lua'

              local objectinfo = love.filesystem.load(filename)()
              objectinfo.x = obj.x - Global.tilewidth / 4
              objectinfo.y = obj.y
              objectinfo.name = obj.name

              objectinfo.image = love.graphics.newImage(objectinfo.spritesheet)

              if obj.properties.collision then
                  for _, collisionObj in pairs(self.map.bump_collidables) do
                      if collisionObj.name == obj.properties.collision then
                          objectinfo.collision = collisionObj
                          break
                      end
                  end
              end

              local controller = Engine.controllers[objectinfo.controller](objectinfo, self.bumpworld)
              table.insert(self.controllers, controller)
              table.insert(objectLayer.controllers, controller)
          end
      end

      -- Draw callback for Custom Layer
      function objectLayer:draw()
          table.sort(self.controllers, function(a, b) return a.info.y < b.info.y end)

          for _, controller in pairs(self.controllers) do
            controller:draw()
          end
      end

      self.map.layers['objects'].visible = false
end

return Level
