{-|
Module      : Graphics.QML.Transient
License     : BSD3
Maintainer  : marcin.jan.mrotek@gmail.com
Stability   : experimental

Main module that exports everything needed for users of this library.
-}

module Graphics.QML.Transient 
  ( Build
  , Qml
  , React
  , qml
  , runQml
  , reacting
  , continuously
  , changes
  , member
  , addMember
  , module Graphics.QML.Transient.Marshal
  , module Graphics.QML.Transient.Method
  , module Graphics.QML.Transient.Property
  , module Graphics.QML.Transient.Signal
  , module Control.Monad.Transient
  , module GHC.Generics
  ) where

import Graphics.QML.Transient.Marshal
import Graphics.QML.Transient.Method
import Graphics.QML.Transient.Property
import Graphics.QML.Transient.Signal
import Graphics.QML.Transient.Types
import Graphics.QML.Transient.Internal
import Graphics.QML.Transient.Internal.Types

import Control.Monad.Transient

import Control.Concurrent
import Control.Monad
import Control.Monad.Reader
import Control.Monad.Writer.Lazy
import GHC.Generics
import Graphics.QML
import Transient.Base

runQml :: DocumentPath -> Build r -> IO r
-- ^Build and run a QML context object, loading a '.qml' file from the provided 'DocumentPath'.
runQml path (Build q) = do
  ((buildAction, r),ms) <- runWriterT q
  cls <- newClass ms
  ctx <- newObject cls ()
  _ <- forkIO.void 
     . runTransient 
     $ runReaderT (unpackQml buildAction) ctx
  let engineConfig = defaultEngineConfig 
       { initialDocument = path
       , contextObject   = Just $ anyObjRef ctx
       }
  runEngineLoop engineConfig 
  pure r

member :: String -> Build a -> Build a
-- ^Build and embed an object as a member with a given name.
member name (Build q) = do
  ((buildAction, r),ms) <- liftIO $ runWriterT q
  obj <- liftIO $ (`newObject` ()) =<< newClass ms
  propertyConst name obj
  Build . WriterT $ pure ((buildAction, r), [])
