module Eventloop.Types.System where



import Control.Concurrent

import Control.Concurrent.ExceptionCollection

import Control.Concurrent.MVar

import Control.Concurrent.Thread

import Control.Concurrent.SafePrint

import Control.Concurrent.STM

import Control.Concurrent.Datastructures.BlockingConcurrentQueue

import Control.Exception

import Data.Maybe



import Eventloop.Module.Websocket.Keyboard.Types

import Eventloop.Module.Websocket.Mouse.Types

import Eventloop.Module.Websocket.Canvas.Types

import Eventloop.Module.File.Types

import Eventloop.Module.StatefulGraphics.Types

import Eventloop.Module.StdIn.Types

import Eventloop.Module.StdOut.Types

import Eventloop.Module.Timer.Types



import Eventloop.Types.Common

import Eventloop.Types.Events

import Eventloop.Types.Exception

import Eventloop.Utility.Websockets





type Initializer = SharedIOConstants -> SharedIOState -> IO (SharedIOConstants, SharedIOState, IOConstants, IOState)

type EventRetriever = SharedIOConstants -> TVar SharedIOState -> IOConstants -> TVar IOState -> IO [In]

type PreProcessor = SharedIOConstants -> TVar SharedIOState -> IOConstants -> TVar IOState -> In -> IO [In]

type PostProcessor = SharedIOConstants -> TVar SharedIOState -> IOConstants -> TVar IOState -> Out -> IO [Out]

type EventSender = SharedIOConstants -> TVar SharedIOState -> IOConstants -> TVar IOState -> Out -> IO ()

type Teardown = SharedIOConstants -> SharedIOState -> IOConstants -> IOState -> IO SharedIOState



type OutEventRouter = Out -> EventloopModuleIdentifier



type InEventQueue = BlockingConcurrentQueue In

type OutEventQueue = BlockingConcurrentQueue Out

type SenderEventQueue = BlockingConcurrentQueue Out



-- System Configurations

data EventloopModuleConfiguration

    = EventloopModuleConfiguration { moduleId :: EventloopModuleIdentifier

                                   , ioConstants :: IOConstants

                                   , ioStateT :: TVar IOState

                                   , initializerM :: Maybe Initializer

                                   , retrieverM :: Maybe EventRetriever

                                   , preprocessorM :: Maybe PreProcessor

                                   , postprocessorM :: Maybe PostProcessor

                                   , senderConfigM :: Maybe EventloopModuleSenderConfiguration

                                   , teardownM :: Maybe Teardown

                                   }

    

    

data EventloopModuleSenderConfiguration 

    = EventloopModuleSenderConfiguration { sender :: EventSender

                                         , senderEventQueue :: BlockingConcurrentQueue Out

                                         }



                                         

data EventloopConfiguration progstateT

    = EventloopConfiguration { progstateT :: TVar progstateT

                             , eventloopFunc :: progstateT -> In -> (progstateT, [Out])

                             , inEventQueue :: InEventQueue

                             , outEventQueue :: OutEventQueue

                             }

                               



data EventloopSystemConfiguration progstateT

    = EventloopSystemConfiguration { eventloopConfig :: EventloopConfiguration progstateT

                                   , moduleConfigs :: [EventloopModuleConfiguration]

                                   , sharedIOConstants :: SharedIOConstants

                                   , sharedIOStateT :: TVar SharedIOState

                                   , systemThreadId :: ThreadId

                                   , retrieverThreadsM :: MVar [Thread]

                                   , outRouterThreadM :: MVar Thread

                                   , senderThreadsM :: MVar [Thread]

                                   , exceptions :: ExceptionCollection SomeException

                                   , isStoppingM :: MVar Bool

                                   }

                        

-- Setup Configurations

data EventloopSetupConfiguration progstateT

    = EventloopSetupConfiguration { beginProgstate :: progstateT

                                  , eventloopF :: progstateT -> In -> (progstateT, [Out])

                                  , setupModuleConfigurations :: [EventloopSetupModuleConfiguration]

                                  }

         

         

data EventloopSetupModuleConfiguration

    = EventloopSetupModuleConfiguration { moduleIdentifier :: EventloopModuleIdentifier

                                        , initializerF :: Maybe Initializer

                                        , eventRetrieverF :: Maybe EventRetriever

                                        , preprocessorF :: Maybe PreProcessor

                                        , postprocessorF :: Maybe PostProcessor

                                        , eventSenderF :: Maybe EventSender

                                        , teardownF :: Maybe Teardown

                                        }

         

         

-- Shared IO State

data SharedIOConstants = SharedIOConstants { safePrintToken :: SafePrintToken

                                           , measureText :: CanvasText -> IO ScreenDimensions

                                           }

data SharedIOState = SharedIOState {}

         

-- Modules IO State

data IOConstants = MouseConstants { clientSocket         :: ClientSocket

                                  , clientConnection     :: Connection

                                  , serverSocket         :: ServerSocket

                                  }

                 | KeyboardConstants { clientSocket     :: ClientSocket

                                     , clientConnection :: Connection

                                     , serverSocket     :: ServerSocket

                                     }

                 | CanvasConstants { canvasSystemReceiveBuffer :: CanvasSystemReceiveBuffer

                                   , clientSocket              :: ClientSocket

                                   , clientConnection          :: Connection

                                   , serverSocket              :: ServerSocket

                                   }

                 | StdInConstants { stdInInQueue :: BlockingConcurrentQueue StdInIn

                                  }

                 | TimerConstants { tickInQueue :: BlockingConcurrentQueue TimerIn

                                  }

                 | FileConstants { fileInQueue :: BlockingConcurrentQueue FileIn

                                 }

                 | NoConstants

                 deriving Show



data IOState = TimerState { startedIntervalTimers      :: [StartedTimer]

                          , startedTimers              :: [StartedTimer]

                          }

             | FileState { opened :: [OpenFile]

                         }

             | StatefulGraphicsState { states :: GraphicsStates

                                     }

             | NoState