module Graphics.Gloss.Internals.Interface.Display
        (displayWithBackend)
where   
import Graphics.Gloss.Data.Color
import Graphics.Gloss.Data.Picture
import Graphics.Gloss.Data.ViewPort
import Graphics.Gloss.Data.ViewState
import Graphics.Gloss.Rendering
import Graphics.Gloss.Internals.Interface.Backend
import Graphics.Gloss.Internals.Interface.Window
import Graphics.Gloss.Internals.Interface.Common.Exit
import Graphics.Gloss.Internals.Interface.ViewState.KeyMouse
import Graphics.Gloss.Internals.Interface.ViewState.Motion
import Graphics.Gloss.Internals.Interface.ViewState.Reshape
import qualified Graphics.Gloss.Internals.Interface.Callback as Callback
import Data.IORef
import System.Mem
import Data.Functor


displayWithBackend
        :: Backend a
        => a                -- ^ Initial state of the backend.
        -> Display          -- ^ Display config.
        -> Color            -- ^ Background color.
        -> Picture          -- ^ The picture to draw.
        -> IO ()

displayWithBackend backend displayMode background picture
 =  do  viewSR          <- newIORef viewStateInit

        renderS         <- initState
        renderSR        <- newIORef renderS
        
        let renderFun backendRef = do
                port      <- viewStateViewPort <$> readIORef viewSR
                options   <- readIORef renderSR
                windowSize <- getWindowDimensions backendRef

                displayPicture 
                        windowSize
                        background
                        options
                        (viewPortScale port)
                        (applyViewPortToPicture port picture)

                -- perform GC every frame to try and avoid long pauses
                performGC

        let callbacks
             =  [ Callback.Display renderFun 

                -- Escape exits the program
                , callback_exit () 
                
                -- Viewport control with mouse
                , callback_viewState_keyMouse viewSR
                , callback_viewState_motion   viewSR
                , callback_viewState_reshape ]

        createWindow backend displayMode background callbacks