local love = love
local gpu = require( "gpu" )
local t = {}

local canvas
local shaders = {
  matte = require( "shaders.matte" ),  
  bell = require( "shaders.bell" ),
  sky = require( "shaders.sky" ),
}

local meshes = {}
local drawLists = {}
local isDebugging = false
local tf = love.math.newTransform()
local debugTF = love.math.newTransform()

for k in pairs( shaders ) do drawLists[k] = {} end

function t.start()
  canvas = {
    love.graphics.newCanvas(),
    stencil = false,
    depth = true,
  }

  drawLists.sky = require( "models.sky" )
  shaders.sky:send( "cube", drawLists.sky.tex )
end

function t.debug()
  isDebugging = true
end

local function sky( view )
  love.graphics.push( "all" )
  love.graphics.setDepthMode( "always", false )
  love.graphics.setMeshCullMode( "none" )
  love.graphics.setShader( shaders.sky )
  local s = shaders.sky
  local rot = { view[1], view[2], view[3], {0, 0, 0, 1} }
  s:send( "view", "column", rot )
  love.graphics.draw( drawLists.sky.mesh )
  love.graphics.pop()
end

local function matte( )
  local list = drawLists.matte
  local shader = shaders.matte
  love.graphics.setShader( shader )
  for mesh in pairs( list ) do
    shader:send( "mdl", "column", meshes[mesh])
    love.graphics.draw( mesh )
  end
end

local function bell( )
  local list = drawLists.bell
  local shader = shaders.bell
  love.graphics.setShader( shader )

  for mesh in pairs( list ) do
    love.graphics.drawInstanced( mesh, 7 )
  end
end

--[[function t.setViewDirection( x, y, z )
  shaders.sky:send( "viewVec", {x, y, z} )
end]]

function t.draw( view, proj )

  if isDebugging then
  end


  love.graphics.push( "all" )
  love.graphics.setScissor( 0, 0, love.graphics.getDimensions() )
  love.graphics.setCanvas( canvas )
  love.graphics.clear()
  love.graphics.setDepthMode( "less", true )
  love.graphics.replaceTransform( tf )
  love.graphics.setMeshCullMode( "back" )

  for _, s in pairs( shaders ) do
    s:send( "view", "column", view )
    s:send( "proj", "column", proj )
  end

  sky( view )
  matte()
  bell()

  love.graphics.pop()
  love.graphics.setColor( 1, 1, 1, 1 )
  love.graphics.draw( canvas[1] )

  if isDebugging then
    isDebugging = false
    io.flush()
  end
end

function t.update( mesh, modelMatrix )
  meshes[mesh] = modelMatrix
end

function t.add( mesh, shaderName )
  shaderName = shaderName or "matte"
  meshes[mesh] = { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, {0, 0, 1, 0}, {0, 0, 0, 1} }
  drawLists[shaderName][mesh] = true
end

return t