local dkjson = require( "lib.dkjson" )
local love = assert( love )
local shader = require( "shaders.flat" )
local mat = require( "mat4" )

local attributeNames = {
  POSITION = "VertexPosition",
  NORMAL = "VertexNormal",
}

local types = {
  ["SCALAR"] = 1,
  ["VEC3"] = 3,
}

local componentTypes = {
  [5121] = "byte",
  [5123] = "unorm16",
  [5126] = "float",
}

local elementComponentTypes = {
  [5123] = "uint16",
  [5126] = "uint32",
}

local asset
local buffer
do
  local fd = assert( love.filesystem.newFileData( "models/building.gltf" ) )
  asset = dkjson.decode( fd:getString() )
  buffer = love.filesystem.newFileData( "models/building.bin" )
end

--load all the bufferViews
local bufferViews = {}
for i, view in pairs( asset.bufferViews ) do
  bufferViews[i] = love.data.newByteData( buffer, view.byteOffset, view.byteLength )
end

local function attributeFormat( attributeName, accessor )
  return {attributeNames[attributeName], componentTypes[accessor.componentType], types[accessor.type] }
end

local function lgMesh( primitive )
  assert( not( primitive.mode ) ) --triangles only

  local finalMesh
  for name, accIdx in pairs( primitive.attributes ) do
    local acc = asset.accessors[accIdx+1]

    local mesh = love.graphics.newMesh(
      {attributeFormat(name, acc)}, --vertexformat
      acc.count,
      "triangles",
      "static"
    )

    local bfv = bufferViews[1+acc.bufferView]
    mesh:setVertices( bfv )

    if finalMesh then
      finalMesh:attachAttribute( attributeNames[name], mesh )
    else
      finalMesh = mesh
    end

  end


  do
    local acc = asset.accessors[1+primitive.indices]
    local bfv = bufferViews[1+acc.bufferView]
    finalMesh:setVertexMap(bfv, elementComponentTypes[acc.componentType] )
  end
  return finalMesh
end

local obj = {}
local mesh = lgMesh( asset.meshes[1].primitives[1] )
local id = mat.TRS(2,2,2,0,0,0,0,2,0)

function obj.draw( view, proj, light )
  love.graphics.setMeshCullMode( "none" )
  shader:send( "view", "column", view )
  shader:send( "proj", "column", proj )
  shader:send( "light", light )
  love.graphics.setShader( shader )
  love.graphics.setColor( 0.05,0.05,0.1,1.0 )
  shader:send( "mdl", "column", id )
  love.graphics.draw( mesh )
end

return obj