local consts = require 'constants'

local normalMapper = love.graphics.newShader
[[
extern Image tex_nrm;
extern float lightX;
extern float lightY;

vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) {
   vec4 light_dir = normalize(vec4(lightX, lightY, 1.0, 1.0));

   vec4 pixel = Texel(texture, texture_coords);
   vec4 normal = Texel(tex_nrm, texture_coords);

   float l = max(dot(light_dir, normalize(normal)), 0.0);
   vec3 col = vec3(pixel) * pow(l, 4.0);
   return vec4(col, 1.0);
}
]]

function drawAll(state)

   -- create a canvas to blit to
   love.graphics.setCanvas(state.canvas)

   -- draw the board background
   for x = 0, consts.boardWidth - 1 do
      for y = 0, consts.boardHeight - 1 do
         if state.board:lookup(x, y) then
            love.graphics.draw(state.spritesheet,
                               state.board:lookup(x, y):draw(x, y, state.t))
         end
      end
   end

   -- draw the entities
   for x = 0, consts.boardWidth - 1 do
      for y = 0, consts.boardHeight - 1 do
         -- if an entity is in this space, draw it
         local e = state.board:lookupEntity(x, y)
         if e and e[1] and e[1].behind then
            love.graphics.draw(state.spritesheet,
                               e[1]:draw(x, y, state.t))
         end
      end
   end

   -- draw the entities
   for x = 0, consts.boardWidth - 1 do
      for y = 0, consts.boardHeight - 1 do
         -- if the character is in this space, draw it first
         -- XXX: extend this to mobile entities in general
         local sX, sY = state.char:gameTopCoords()
         if sX == x and sY == y then
            love.graphics.draw(state.spritesheet,
                               state.char:draw(state.t))
         end

         -- if an entity is in this space, draw it
         local es = state.board:lookupEntity(x, y) or {}
         for i, e in pairs(es) do
            if e and not e.behind then
               love.graphics.draw(state.spritesheet,
                                  e:draw(x, y, state.t))
            end
         end

      end
   end

   -- if we've got dialogue up, then show that, too
   -- XXX: factor this out!
   if state.message then
      local w = consts.boardWidth * consts.tileSize
      local h = consts.boardHeight * consts.tileSize / 2
      love.graphics.setColor(0, 0, 0)
      love.graphics.rectangle('fill', 6, 6 + h, w - 12, h - 12)
      love.graphics.setColor(255, 255, 255)
      love.graphics.rectangle('fill', 8, 8 + h, w - 16, h - 16)
      love.graphics.setColor(0, 0, 0)
      love.graphics.print(state.message, 12, h + 12)
      love.graphics.setColor(255, 255, 255)
   end

   -- now the same, but with normals
   love.graphics.setCanvas(state.normals)

   -- draw the board background
   for x = 0, consts.boardWidth - 1 do
      for y = 0, consts.boardHeight - 1 do
         if state.board:lookup(x, y) then
            love.graphics.draw(state.spriteNormals,
                               state.board:lookup(x, y):draw(x, y, state.t))
         end
      end
   end

   -- draw the entities
   for x = 0, consts.boardWidth - 1 do
      for y = 0, consts.boardHeight - 1 do
         -- if an entity is in this space, draw it
         local e = state.board:lookupEntity(x, y)
         if e and e[1] and e[1].behind then
            love.graphics.draw(state.spriteNormals,
                               e[1]:draw(x, y, state.t))
         end
      end
   end

   -- draw the entities
   for x = 0, consts.boardWidth - 1 do
      for y = 0, consts.boardHeight - 1 do
         -- if the character is in this space, draw it first
         -- XXX: extend this to mobile entities in general
         local sX, sY = state.char:gameTopCoords()
         if sX == x and sY == y then
            love.graphics.draw(state.spriteNormals,
                               state.char:draw(state.t))
         end

         -- if an entity is in this space, draw it
         local es = state.board:lookupEntity(x, y) or {}
         for i, e in pairs(es) do
            if e and not e.behind then
               love.graphics.draw(state.spriteNormals,
                                  e:draw(x, y, state.t))
            end
         end

      end
   end

   -- print the debug message

   love.graphics.setCanvas()
   -- blank out the screen
   love.graphics.setColor(255, 255, 255)
   love.graphics.rectangle('fill', 0, 0,
                           love.graphics.getWidth(),
                           love.graphics.getHeight())

   love.graphics.setColor(255, 255, 255)

   love.graphics.setShader(normalMapper)
   normalMapper:send('tex_nrm', state.normals)
   normalMapper:send('lightX', 0.5 + (0.5 * math.sin(state.t / 50)))
   normalMapper:send('lightY', 0.5 + (0.5 * math.cos(state.t / 50)))
   -- blit the smaller canvas back onto the larger screen
   love.graphics.draw(state.canvas, 0, 0, 0, consts.scale, consts.scale)
   love.graphics.setShader()

end

return { drawAll = drawAll }
