
local demo_dir = gh_utils.get_demo_dir()
local lib_dir = gh_utils.get_lib_dir() 		


function new_polygon()
  local polygon = {
    vertex_color_prog = 0,
    attrib_size = 16, -- vec4 = 16 bytes
    num_vertex_attribs = 2, -- position + color
    vertex_size = 0, -- num_vertex_attribs * attrib_size,
    num_vertices = 0,
    vb_buffer_size = 0, 
    buffer_offset_bytes = 0,
    vb_buffer_ptr = 0,
    vbid = 0,
    color = {r=1,g=1,b=1,a=1},
    transformation={posx=0, posy=0, angle=0},
  }
  return polygon
end  


function polygon_init_shader(polygon)

  local vs_gl3= [[
  #version 150
  in vec4 Position; 
  in vec4 Color; 
  out vec4 v_color; 
  uniform mat4 ViewProjectionMatrix;
  uniform mat4 ModelMatrix;
  void main() 
  { 
    vec4 P = ModelMatrix * vec4(Position.x, Position.y, 0.0, 1.0);		
    gl_Position = ViewProjectionMatrix * vec4(P.xyz, 1.0);		
    v_color = Color; 
  } 
  ]]

  local ps_gl3= [[
  #version 150
  in vec4 v_color; 
  uniform vec4 color;
  out vec4 FragColor; 
  void main() 
  { 
    FragColor = v_color * color; 
    //FragColor = vec4(1.0); 
  }
  ]]


  polygon.vertex_color_prog = gh_gpu_program.create_v2("vertex_color_prog", vs_gl3, ps_gl3)
  gh_gpu_program.uniform4f(polygon.vertex_color_prog, "color", polygon.color.r, polygon.color.g, polygon.color.b, polygon.color.a)

  gh_gpu_program.bind(polygon.vertex_color_prog) -- required for get_vertex_attrib_location()
  gh_gpu_program.bind(0)
end


function polygon_create_vb(polygon, numverts)

  polygon.attrib_size = 16 -- vec4 = 16 bytes
  polygon.num_vertex_attribs = 2 -- position + color
  polygon.vertex_size = polygon.num_vertex_attribs * polygon.attrib_size
  polygon.num_vertices = numverts


  polygon.vb_buffer_size = numverts * polygon.vertex_size 

  polygon.buffer_offset_bytes = 0
  polygon.vb_buffer_ptr = 0


  polygon.vbid = gh_vb.create(polygon.vb_buffer_size, polygon.num_vertex_attribs)

  -- Position attrib
  local vertex_attrib_index = 0
  local loc = gh_gpu_program.get_vertex_attrib_location(polygon.vertex_color_prog, "Position")
  local attrib_location = loc
  local attrib_type = 1 -- float => 1 ; integer => 2
  local dim = 4 -- vec4
  local stride = polygon.vertex_size
  local offset = 0 -- position
  gh_vb.set_vertex_attrib_data(polygon.vbid, vertex_attrib_index, attrib_location, attrib_type, dim, stride, offset)


  -- Color attrib
  vertex_attrib_index = 1
  loc = gh_gpu_program.get_vertex_attrib_location(polygon.vertex_color_prog, "Color")
  attrib_location = loc
  attrib_type = 1 -- float => 1 ; integer => 2
  dim = 4 -- vec4
  stride = polygon.vertex_size
  offset = polygon.attrib_size -- color
  gh_vb.set_vertex_attrib_data(polygon.vbid, vertex_attrib_index, attrib_location, attrib_type, dim, stride, offset)

end




function polygon_begin(polygon)
  gh_vb.bind(polygon.vbid)
  local bufsize = 0
  polygon.vb_buffer_ptr, bufsize = gh_vb.map(polygon.vbid, "GL_WRITE_ONLY")
  polygon.buffer_offset_bytes = 0
end

function polygon_end(polygon)
  polygon.vb_buffer_ptr = 0
  polygon.buffer_offset_bytes = 0
  gh_vb.unmap(polygon.vbid)
  gh_vb.unbind(polygon.vbid)
end




function polygon_update_vb(polygon, vertices)

  local nverts = #vertices
  print("polygon_update_vb - nverts: " .. nverts)

  polygon_create_vb(polygon, nverts)

  polygon_begin(polygon)

  polygon.buffer_offset_bytes = 0

  for i=1, polygon.num_vertices do

    local vertex = vertices[i]
    -- position
    gh_utils.buffer_write_4f(polygon.vb_buffer_ptr, polygon.buffer_offset_bytes, vertex.x, vertex.y, 0.0, 1.0)
    polygon.buffer_offset_bytes = polygon.buffer_offset_bytes + polygon.attrib_size
    -- color
    gh_utils.buffer_write_4f(polygon.vb_buffer_ptr, polygon.buffer_offset_bytes, 1, 1, 1, 1)
    polygon.buffer_offset_bytes = polygon.buffer_offset_bytes + polygon.attrib_size
  end

  polygon_end(polygon)
end


function polygon_init(polygon, vertices_list)
  polygon_init_shader(polygon)
  polygon_update_vb(polygon, vertices_list)
end


function polygon_color(polygon, r, g, b, a)
  polygon.color.r = r
  polygon.color.g = g
  polygon.color.b = b
  polygon.color.a = a
end


function polygon_draw(polygon, camera, wireframe, rendering_scale, world_y_offset)

  gh_gpu_program.bind(polygon.vertex_color_prog)
  gh_gpu_program.gpu_uniform4f(polygon.vertex_color_prog, "color", polygon.color.r, polygon.color.g, polygon.color.b, polygon.color.a)
  gh_gpu_program.gpu_uniform_camera_matrices_v2(polygon.vertex_color_prog, camera, "", "", "ViewProjectionMatrix")
  
  local TRANSFORM_ORDER_TRS = 0
  local TRANSFORM_ORDER_RTS = 1
  local TRANSFORM_ORDER_TSR = 2
  local TRANSFORM_ORDER_RST = 3
  local transform_order = TRANSFORM_ORDER_TRS
  gh_gpu_program.gpu_uniform_transform_matrix_v1(polygon.vertex_color_prog, "ModelMatrix", polygon1.transformation.posx*rendering_scale, polygon1.transformation.posy*rendering_scale+world_y_offset, 0.0,    0.0, 0.0, polygon1.transformation.angle,   rendering_scale, rendering_scale, 1.0, transform_order)
  

  gh_vb.bind(polygon.vbid)
  
  local PRIMITIVE_TRIANGLE = 0
  local PRIMITIVE_TRIANGLE_STRIP = 1
  local PRIMITIVE_TRIANGLE_FAN = 9
  local PRIMITIVE_LINE = 2
  local PRIMITIVE_LINE_STRIP = 3
  local PRIMITIVE_LINE_LOOP = 4

  -- if (wireframe == 1) then
  --   gh_renderer.draw_primitives(PRIMITIVE_LINE_LOOP, polygon.num_vertices, 0)
  -- else
  --   gh_renderer.draw_primitives(PRIMITIVE_TRIANGLE_FAN, polygon.num_vertices, 0)
  -- end

  gh_renderer.draw_primitives(PRIMITIVE_TRIANGLE_FAN, polygon.num_vertices, 0)
 
  gh_vb.unbind(polygon.vbid)
  
end
