module Data.GI.CodeGen.OverloadedSignals
    ( genObjectSignals
    , genInterfaceSignals
    ) where

#if !MIN_VERSION_base(4,8,0)
import Control.Applicative ((<$>))
#endif
import Control.Monad (when)

#if !MIN_VERSION_base(4,11,0)
import Data.Monoid ((<>))
#endif
import qualified Data.Text as T

import Data.GI.CodeGen.API
import Data.GI.CodeGen.Code
import Data.GI.CodeGen.Inheritance (fullObjectSignalList, fullInterfaceSignalList)
import Data.GI.CodeGen.GObject (apiIsGObject)
import Data.GI.CodeGen.SymbolNaming (upperName, hyphensToCamelCase,
                                     signalInfoName)
import Data.GI.CodeGen.Util (lcFirst)

-- | Signal instances for (GObject-derived) objects.
genObjectSignals :: Name -> Object -> CodeGen e ()
genObjectSignals :: forall e. Name -> Object -> CodeGen e ()
genObjectSignals Name
n Object
o = do
  let name :: Text
name = Name -> Text
upperName Name
n
  Bool
isGO <- Name -> API -> CodeGen e Bool
forall e. Name -> API -> CodeGen e Bool
apiIsGObject Name
n (Object -> API
APIObject Object
o)
  Bool -> CodeGen e () -> CodeGen e ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
isGO (CodeGen e () -> CodeGen e ()) -> CodeGen e () -> CodeGen e ()
forall a b. (a -> b) -> a -> b
$ do
       [Text]
infos <- Name -> Object -> CodeGen e [(Name, Signal)]
forall e. Name -> Object -> CodeGen e [(Name, Signal)]
fullObjectSignalList Name
n Object
o CodeGen e [(Name, Signal)]
-> ([(Name, Signal)]
    -> ReaderT
         CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) [Text])
-> ReaderT
     CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) [Text]
forall a b.
ReaderT CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) a
-> (a
    -> ReaderT
         CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) b)
-> ReaderT
     CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=
                ((Name, Signal)
 -> ReaderT
      CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text)
-> [(Name, Signal)]
-> ReaderT
     CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) [Text]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (\(Name
owner, Signal
signal) -> do
                      Text
si <- Name
-> Signal
-> ReaderT
     CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text
forall e. Name -> Signal -> CodeGen e Text
signalInfoName Name
owner Signal
signal
                      Text
-> ReaderT
     CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text
forall a.
a
-> ReaderT
     CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) a
forall (m :: * -> *) a. Monad m => a -> m a
return (Text
 -> ReaderT
      CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text)
-> Text
-> ReaderT
     CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text
forall a b. (a -> b) -> a -> b
$ Text
"'(\"" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (Text -> Text
lcFirst (Text -> Text) -> (Signal -> Text) -> Signal -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
hyphensToCamelCase (Text -> Text) -> (Signal -> Text) -> Signal -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Signal -> Text
sigName) Signal
signal
                                 Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\", " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
si Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")")
       CodeGen e () -> CodeGen e ()
forall e a. CodeGen e a -> CodeGen e a
group (CodeGen e () -> CodeGen e ()) -> CodeGen e () -> CodeGen e ()
forall a b. (a -> b) -> a -> b
$ do
         let signalListType :: Text
signalListType = Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"SignalList"
         Text -> CodeGen e ()
forall e. Text -> CodeGen e ()
line (Text -> CodeGen e ()) -> Text -> CodeGen e ()
forall a b. (a -> b) -> a -> b
$ Text
"type instance O.SignalList " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" = " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
signalListType
         Text -> CodeGen e ()
forall e. Text -> CodeGen e ()
line (Text -> CodeGen e ()) -> Text -> CodeGen e ()
forall a b. (a -> b) -> a -> b
$ Text
"type " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
signalListType Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" = ('[ "
                  Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> [Text] -> Text
T.intercalate Text
", " [Text]
infos Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"] :: [(Symbol, *)])"

-- | Signal instances for interfaces.
genInterfaceSignals :: Name -> Interface -> CodeGen e ()
genInterfaceSignals :: forall e. Name -> Interface -> CodeGen e ()
genInterfaceSignals Name
n Interface
iface = do
  let name :: Text
name = Name -> Text
upperName Name
n
  [Text]
infos <- Name -> Interface -> CodeGen e [(Name, Signal)]
forall e. Name -> Interface -> CodeGen e [(Name, Signal)]
fullInterfaceSignalList Name
n Interface
iface CodeGen e [(Name, Signal)]
-> ([(Name, Signal)]
    -> ReaderT
         CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) [Text])
-> ReaderT
     CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) [Text]
forall a b.
ReaderT CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) a
-> (a
    -> ReaderT
         CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) b)
-> ReaderT
     CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=
           ((Name, Signal)
 -> ReaderT
      CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text)
-> [(Name, Signal)]
-> ReaderT
     CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) [Text]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (\(Name
owner, Signal
signal) -> do
                   Text
si <- Name
-> Signal
-> ReaderT
     CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text
forall e. Name -> Signal -> CodeGen e Text
signalInfoName Name
owner Signal
signal
                   Text
-> ReaderT
     CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text
forall a.
a
-> ReaderT
     CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) a
forall (m :: * -> *) a. Monad m => a -> m a
return (Text
 -> ReaderT
      CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text)
-> Text
-> ReaderT
     CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text
forall a b. (a -> b) -> a -> b
$ Text
"'(\"" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (Text -> Text
lcFirst (Text -> Text) -> (Signal -> Text) -> Signal -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
hyphensToCamelCase (Text -> Text) -> (Signal -> Text) -> Signal -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Signal -> Text
sigName) Signal
signal
                              Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\", " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
si Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")")
  CodeGen e () -> CodeGen e ()
forall e a. CodeGen e a -> CodeGen e a
group (CodeGen e () -> CodeGen e ()) -> CodeGen e () -> CodeGen e ()
forall a b. (a -> b) -> a -> b
$ do
    let signalListType :: Text
signalListType = Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"SignalList"
    Text -> CodeGen e ()
forall e. Text -> CodeGen e ()
line (Text -> CodeGen e ()) -> Text -> CodeGen e ()
forall a b. (a -> b) -> a -> b
$ Text
"type instance O.SignalList " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" = " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
signalListType
    Text -> CodeGen e ()
forall e. Text -> CodeGen e ()
line (Text -> CodeGen e ()) -> Text -> CodeGen e ()
forall a b. (a -> b) -> a -> b
$ Text
"type " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
signalListType Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" = ('[ "
             Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> [Text] -> Text
T.intercalate Text
", " [Text]
infos Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"] :: [(Symbol, *)])"