{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{- |
  Module      : Haskengl
  Description : 4D side project
  Copyright   : Andromeda 2025
  License     : WTFPL
  Maintainer  : Matrix @Andromeda:tchncs.de
  Stability   : Experimental
 -}
module Haskengl.Main (main) where

import Relude
import Relude.Monad (forever)

import Control.Concurrent (threadDelay)

import Haskengl.Internal.Bindings.GLFW (Window, getTime)
import Haskengl.Internal.IO.Window     (openWindow)
import Haskengl.Internal.IO.View       (view)
import Haskengl.Internal.Update        (update)
import Haskengl.Internal.Types         (Model(..), DisplayableObjects)

-- | Starts game
main :: IO ()
main =
  do
    (window, objects) <- openWindow "window :)"
    putTextLn "initialized window"
    _ <- loop window update view $ Model { objects = objects }
    return ()

-- | Elm-like 'gameloop'
loop
  :: Window -- ^ The window to display on
  -> (Model -> Model) -- ^ Update function
  -> (Window -> Model -> IO ()) -- ^ View function
  -> Model -- ^ Model
  -> IO ()
loop window update view model =
  do
    Just frameStart <- getTime
    let model' = update model
    view window model'
    Just frameEnd <- getTime
    let
      dt = frameEnd - frameStart :: Double
      target = 1 / 60 :: Double
    when (dt < target) $ threadDelay $ floor $ (target - dt) * 1000
    loop window update view model'
