import vk/[ vk_core
     , vulkan
     , swapchain
     , graphics_pipeline
     , pipeline_record
     , buffer
     , vulkan_record
     , vulkan_frame
     ]

, wain/[ waindow
         , waindow_object
         , keyboard
         , mouse
         , monitor
         , waindow_utils
         ]

, times 
, glm
, camera
, utils/etc
, os
, math
,bitops
, input/[ inputTys
          ]

, strUtils

, memory/[ utils
         ]

import scene/[scene_controller
                     , scene_record 
                     , main_scenes
                     ]
                     
import std/tables 

when defined windows: 
 import winim/lean

when defined linux: 
 import platforms/unix/x11/xcb

proc main() =
 var
   the_waindow = a_waindow()
   vk_record = setup_vulkan(the_waindow[])
   scene_record = a_scene_record( the_main_scene = Test_Area
                                                       )
 
 proc key_relay( the_waindow: var Waindow
                        , key: WAIN_Key
                        , action: int
                        ) {.closure.} =
  
  if is_down WAIN_Key.Q: 
   the_waindow.quit = true

  if key == WAIN_Key.F and
     action == ord Key_Action.Press: discard #the_waindow.toggle_full_screen
  
  if key == WAIN_Key.Escape and
     action == ord Key_Action.Press: the_waindow.quit = true
      
  
 proc mouse_key_relay( the_waindow: var Waindow
                                     , key: MouseButton
                                     , action: MouseBtnAction
                                     ){.closure.} = 
  discard
  #echo action
   
 proc window_mapped_relay ( the_waindow: var Waindow
                     , width: int
                     , height: int
                     ) {.closure.} = discard

 proc window_closed_relay (  the_waindow: var Waindow
                                            ) {.closure.} = 
  the_waindow.quit = true
 
 proc window_resize_relay( the_waindow: var Waindow
                                           , width: int
                                           , height: int
                                           ) {.closure.} = 
  
  # Simple fix for 1:1 pixel aspect ratio.
    # if vk_record.current_viewport.width > vk_record.current_viewport.height:
    #  vk_record.current_viewport.x += 0.5 * (vk_record.current_viewport.width - vk_record.current_viewport.height)
    #  vk_record.current_viewport.width = vk_record.current_viewport.height
        # elif vk_record.current_viewport.height > vk_record.current_viewport.width:
    #  vk_record.current_viewport.y += 0.5f * (vk_record.current_viewport.height - vk_record.current_viewport.width);
    #  vk_record.current_viewport.height = vk_record.current_viewport.width

  #window_resize( the_waindow, vk_record) 

#[   rebuild( vk_record.vk_device 
         , vk_record.frame_buffers
         , scene_record.current_scene.render_pass
         , vk_record.swapchain
         , scene_record.current_scene.depth_stencil
         , vk_record.gpu.memory_properties
         )  ]#
  
  discard vkDeviceWaitIdle vk_record.vk_device
  
  vk_record.readyFrame = true
 
 set_key_relay(  the_waindow[]
                       , key_relay
                       )
 
 set_mouse_relay( the_waindow[]
                            , mouse_key_relay
                            )
 
 
 set_window_resize_relay( the_waindow[]
                                          ,  window_resize_relay
                                          )
 set_window_mapped_relay( the_waindow[], window_mapped_relay)
 set_window_closed_relay(the_waindow[], window_closed_relay)

 var
 
  dt = 0.0
  updateLimit = 1.0 / 144.0
  ft,t = 0.0
  currTime = 0.0
  frames = 0
  updates = 0
  accum = 0.0
  nowTime = 0.0
  cpuframeTimer: TimeInterval
  gpuframeTimer: TimeInterval
  lastFPS: float
  fps: string = "???"
  presentInfo = VkPresentInfoKHR( sType: VK_STRUCTURE_TYPE_PRESENT_INFO_KHR
                                , pNext: nil
                                , swapchainCount: 1
                                , pSwapchains: addr vk_record.swapchain.handle
                                )
  lastTime = cpuTime()
  timer = lastTime
  pipeline_record = Pipeline_Record()


 load( scene_record
        , vk_record 
        )
 
 while not the_waindow.quit:
  events the_waindow[]
  
  nowTime = cpuTime()
  dt += (nowTime - lastTime) / updateLimit
  lastTime = nowTime
  
  input(scene_record
          , vk_record  
          )

  while dt > 1.0:
   update( scene_record
              , vk_record
              , fps
              )
   updates += 1
   dt -= 1
  
  draw( vk_record
          , scene_record
          , pipeline_record
          )
  frames += 1
  
  if cpuTime() - timer  > 1.0: 
   timer += 1
   #fps = $frames & " | " & $updates 
  # echo frames, " | ",updates
   updates = 0
   frames = 0  
  
 #discard vkDeviceWaitIdle vk_record.vk_device
 
main()