{-# LANGUAGE ForeignFunctionInterface #-}

module Graphics.UI.AppIndicator.Types (
  AppIndicator (..),
  AppIndicatorClass,
  unAppIndicator,
  mkAppIndicator,
  toAppIndicator,
  gTypeAppIndicator,
  castToAppIndicator
) where

import           Foreign.ForeignPtr        (ForeignPtr, castForeignPtr)
import           Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
import           Graphics.UI.GtkInternals  (objectUnrefFromMainloop)
import           System.Glib.FFI           (CULong (..), FinalizerPtr)
import           System.Glib.GObject       (GObject (..), GObjectClass,
                                            toGObject, unGObject,
                                            unsafeCastGObject)
import           System.Glib.GType         (GType, typeInstanceIsA)

castTo :: (GObjectClass obj, GObjectClass obj') => GType -> String
                                                -> (obj -> obj')
castTo gtype objTypeName obj =
  case toGObject obj of
    gobj@(GObject objFPtr)
      | typeInstanceIsA ((unsafeForeignPtrToPtr.castForeignPtr) objFPtr) gtype
                  -> unsafeCastGObject gobj
      | otherwise -> error $ "Cannot cast object to " ++ objTypeName

newtype AppIndicator = AppIndicator (ForeignPtr AppIndicator) deriving (Eq,Ord)

unAppIndicator :: AppIndicator -> ForeignPtr AppIndicator
unAppIndicator (AppIndicator o) = o

mkAppIndicator :: (ForeignPtr AppIndicator -> AppIndicator, FinalizerPtr a)
mkAppIndicator = (AppIndicator, objectUnrefFromMainloop)

class GObjectClass o => AppIndicatorClass o

instance AppIndicatorClass AppIndicator
instance GObjectClass AppIndicator where
  toGObject = GObject . castForeignPtr . unAppIndicator
  unsafeCastGObject = AppIndicator . castForeignPtr . unGObject

toAppIndicator :: AppIndicatorClass o => o -> AppIndicator
toAppIndicator = unsafeCastGObject . toGObject

gTypeAppIndicator :: GType
gTypeAppIndicator = app_indicator_get_type

foreign import ccall unsafe "app_indicator_get_type"
  app_indicator_get_type :: CULong

castToAppIndicator :: GObjectClass obj => obj -> AppIndicator
castToAppIndicator = castTo gTypeAppIndicator "AppIndicator"