module Eventloop.System.InitializationThread

    ( startInitializing

    ) where



import Control.Exception

import Control.Concurrent.STM

import Data.List



import Eventloop.Types.Exception

import Eventloop.Types.System





startInitializing :: EventloopSystemConfiguration progstateT

                  -> IO (EventloopSystemConfiguration progstateT)

startInitializing systemConfig

    = do

        sharedIO <- readTVarIO sharedIOT_

        (sharedConst', sharedIO', moduleConfigs_') <- initializeModules sharedConst sharedIO moduleConfigs_

        atomically $ writeTVar sharedIOT_ sharedIO'

        return systemConfig{moduleConfigs = reverse $ moduleConfigs_', sharedIOConstants = sharedConst'}

    where

        sharedConst = sharedIOConstants systemConfig

        sharedIOT_ = sharedIOStateT systemConfig

        moduleConfigs_ = reverse $ moduleConfigs systemConfig





initializeModules :: SharedIOConstants

                  -> SharedIOState

                  -> [EventloopModuleConfiguration]

                  -> IO (SharedIOConstants, SharedIOState, [EventloopModuleConfiguration])

initializeModules sharedConst sharedIO [] = return (sharedConst, sharedIO, [])

initializeModules sharedConst sharedIO (moduleConfig:configs)

    = do

        (sharedConst', sharedIO', moduleConfig') <- initializeModule sharedConst sharedIO moduleConfig

        (sharedConst'', sharedIO'', configs') <- initializeModules sharedConst' sharedIO' configs

        return (sharedConst'', sharedIO'', moduleConfig':configs')





initializeModule :: SharedIOConstants

                 -> SharedIOState

                 -> EventloopModuleConfiguration

                 -> IO (SharedIOConstants, SharedIOState, EventloopModuleConfiguration)

initializeModule sharedConst sharedIO moduleConfig

    = case (initializerM moduleConfig) of

        Nothing            -> return (sharedConst, sharedIO, moduleConfig)

        (Just initializer) -> handle

            ( \exception ->

                throwIO (InitializationException moduleId_ exception)

            )

            ( do

                ioState <- readTVarIO ioStateT_

                (sharedConst', sharedIO', ioConst', ioState') <- initializer sharedConst sharedIO

                atomically $ writeTVar ioStateT_ ioState'

                return (sharedConst', sharedIO', moduleConfig {ioConstants = ioConst'})

            )

    where

        moduleId_ = moduleId moduleConfig

        ioConst = ioConstants moduleConfig

        ioStateT_ = ioStateT moduleConfig