{- |
  Parameters define the global context of an animation. They are set once
  before an animation is rendered and may not change during rendering.
-}
module Reanimate.Parameters
  ( Raster(..)
  , Width
  , Height
  , FPS
  , pRaster
  , pFPS
  , pWidth
  , pHeight
  , pNoExternals
  , pRootDirectory
  , setRaster
  , setFPS
  , setWidth
  , setHeight
  , setNoExternals
  , setRootDirectory
  ) where

import           Data.IORef       (IORef, newIORef, readIORef, writeIORef)
import           System.IO.Unsafe (unsafePerformIO)

-- | Width of animation in pixels.
type Width = Int
-- | Height of animation in pixels.
type Height = Int
-- | Framerate of animation in frames per second.
type FPS = Int

-- | Raster engines turn SVG images into pixels.
data Raster
  = RasterNone     -- ^ Do not use any external raster engine. Rely on the browser or ffmpeg.
  | RasterAuto     -- ^ Scan for installed raster engines and pick the fastest one.
  | RasterInkscape -- ^ Use Inkscape to raster SVG images.
  | RasterRSvg     -- ^ Use rsvg-convert to raster SVG images.
  | RasterMagick   -- ^ Use imagemagick to raster SVG images.
  deriving (Show, Eq)

{-# NOINLINE pRasterRef #-}
pRasterRef :: IORef Raster
pRasterRef = unsafePerformIO (newIORef RasterNone)

{-# NOINLINE pRaster #-}
-- | Selected raster engine.
pRaster :: Raster
pRaster = unsafePerformIO (readIORef pRasterRef)

-- | Set raster engine.
setRaster :: Raster -> IO ()
setRaster = writeIORef pRasterRef

{-# NOINLINE pFPSRef #-}
pFPSRef :: IORef FPS
pFPSRef = unsafePerformIO (newIORef 0)

{-# NOINLINE pFPS #-}
-- | Selected framerate.
pFPS :: FPS
pFPS = unsafePerformIO (readIORef pFPSRef)

-- | Set desired framerate.
setFPS :: FPS -> IO ()
setFPS = writeIORef pFPSRef

{-# NOINLINE pWidthRef #-}
pWidthRef :: IORef FPS
pWidthRef = unsafePerformIO (newIORef 0)

{-# NOINLINE pWidth #-}
-- | Width of animation in pixel.
pWidth :: Width
pWidth = unsafePerformIO (readIORef pWidthRef)

-- | Set desired width of animation in pixel.
setWidth :: Width -> IO ()
setWidth = writeIORef pWidthRef

{-# NOINLINE pHeightRef #-}
pHeightRef :: IORef FPS
pHeightRef = unsafePerformIO (newIORef 0)

{-# NOINLINE pHeight #-}
-- | Height of animation in pixel.
pHeight :: Height
pHeight = unsafePerformIO (readIORef pHeightRef)

-- | Set desired height of animation in pixel.
setHeight :: Height -> IO ()
setHeight = writeIORef pHeightRef

{-# NOINLINE pNoExternalsRef #-}
pNoExternalsRef :: IORef Bool
pNoExternalsRef = unsafePerformIO (newIORef False)

{-# NOINLINE pNoExternals #-}
-- | This parameter determined whether or not external tools are allowed.
--   If this flag is True then tools such as 'Reanimate.LaTeX.latex' and
--   'Reanimate.Blender.blender' will not be invoked.
pNoExternals :: Bool
pNoExternals = unsafePerformIO (readIORef pNoExternalsRef)

-- | Set whether external tools are allowed.
setNoExternals :: Bool -> IO ()
setNoExternals = writeIORef pNoExternalsRef

{-# NOINLINE pRootDirectoryRef #-}
pRootDirectoryRef :: IORef FilePath
pRootDirectoryRef = unsafePerformIO (newIORef (error "root directory not set"))

{-# NOINLINE pRootDirectory #-}
-- | Root directory of animation. Images and other data has to be placed
--   here if they are referenced in an SVG image.
pRootDirectory :: FilePath
pRootDirectory = unsafePerformIO (readIORef pRootDirectoryRef)

-- | Set the root animation directory.
setRootDirectory :: FilePath -> IO ()
setRootDirectory = writeIORef pRootDirectoryRef