{.experimental: "codeReordering".}
{.deadCodeElim: on.}


# TODO: when mutual dependencies are avaliable 
# uncomment the scene var so we can auto-add shapes to 
# the current scene again.

import ../vk/[ vulkan
             , vkTypes
             , vulkan_record
             , buffer
             , vulkan_utils 
             , pipeline_record
             , vk_core
             ]

, ../camera
, shape_types

, vmath

import ../vk/vkm/vkmat as vkm
import sequtils 

import shape_primitives 

import std/[ bitops 
           , tables 
           ]
type
 ShapeKind* = enum
  Tri, Quad, Penta, Hexa, Hepta, Octa, Ngon, Circle, Cube

 Shape_Object = object of RootObj
  camera*: Camera
  camera_kind*: Camera_Kind = Camera_Kind.Perspective
  id*: int
  kind*: ShapeKind
  isTextured: bool
  name*: string
  pipelineCache*: VkPipelineCache
  #graphicsPipeline*: GraphicsPipeline
  # render_pass*: VkRenderPass
  indexCount*: uint32
#  stVertexBuffer*: Buffer
#  stIndexBuffer*:  Buffer
  ubo*: UBO
  changed*: bool
  indices*: seq[uint32]
  vertices*: seq[float32]
  vertSize*: uint32
  indSize*: uint32
  hollow*: bool
  theSize*: Vec2
  #push_constants*: Shape_Pushes
  #using_pipelines*: seq[Graphics_Pipeline_Enum]
  moving*: bool 
  master_vertex_buffer_offset*: Natural

 Shape* = ref object of Shape_Object

proc a_shape*( vulkan_record: var Vulkan_Record
                        , current_enitity_id: int  
                        #, s: var Scene # TODO: DO NOT DELET 
                        , sides: Natural
                        , name: string
                        , the_size: Vec2
                        , being_color: Vec4 = vec4(1.0, 0.0, 0.0, 1.0)
                        , deshn_color: Vec4 = vec4(1.0, 0.0, 0.0, 1.0)
                        , camera_type: Camera_Kind = Ortho
                        , hollow: bool = false
                        # TODO: custom vertices and indices 
                        # , vertices: seq[seq[seq[float32]
                        # , indices seq[float32]
                        ): Shape = 
 
 result = Shape( name: name
               , hollow: hollow
               , id: current_enitity_id
               , the_size: the_size
               , camera_kind: camera_type 
#[                , camera: a_camera ( (float  vulkan_record.swapchain.current_extent.width) / 
                                                  (float vulkan_record.swapchain.current_extent.height)
                                                ) ]#
               )

 case sides
 of 3: 
  result.kind = Tri
  result.indices = toSeq triIndexBuffer
  result.vertices = triVertBuffer
  
 of 4: 
  result.kind = Quad
  result.indices = toSeq quadIndexBuffer 
  result.vertices = quadVertBuffer

 of 5: 
  result.kind = Penta
  result.indices = toSeq pentaIndexBuffer 
  result.vertices = pentaVertBuffer
 
 of 6: 
  result.kind = Hexa
  result.indices = toSeq hexaIndexBuffer 
  result.vertices = hexaVertBuffer
 
 of 7: 
  result.kind = Hepta
  result.indices = toSeq heptaIndexBuffer 
  result.vertices = heptaVertBuffer
 
 else:
  if sides > 8: quit "sides > 8, currently not handled"
  else: quit "ERROR[Constructing Shape]: " & $name  & ", with " & $sides & " sides NOT supported yet, try: 3..8 sides"
            
 result.indSize = result.indices.len.uint32 * uint32.sizeof.uint32
 result.vertSize = result.vertices.len.uint32  * Vertex.sizeof.uint32

 
 suballocate_vertex_buffer( vulkan_record 
                          , cast[pointer](addr result.vertices)
                          )
 
 suballocate_index_buffer( vulkan_record
                          , cast[pointer](addr result.indices)
                          )
 
 suballocate_uniform_buffer( vulkan_record
                           , cast[pointer](addr result.ubo)
                           )