{-# LANGUAGE OverloadedStrings #-}
module Eventloop.Module.Websocket.Keyboard.Keyboard
    ( setupKeyboardModuleConfiguration
    , keyboardModuleIdentifier
    , keyboardInitializer
    , keyboardEventRetriever
    , keyboardEventSender
    ) where

import Data.Aeson
import Data.Maybe
import Control.Applicative
import Control.Concurrent.MVar
import Control.Concurrent.SafePrint
import qualified Data.ByteString.Lazy.Char8 as BL

import Eventloop.Types.Common
import Eventloop.Types.Events
import Eventloop.Types.System
import Eventloop.Module.Websocket.Keyboard.Types
import Eventloop.Utility.Config
import Eventloop.Utility.Websockets


setupKeyboardModuleConfiguration :: EventloopSetupModuleConfiguration
setupKeyboardModuleConfiguration = ( EventloopSetupModuleConfiguration 
                                        keyboardModuleIdentifier
                                        (Just keyboardInitializer)
                                        (Just keyboardEventRetriever)
                                        Nothing
                                        Nothing
                                        (Just keyboardEventSender)
                                        Nothing
                                      )

                                      
keyboardModuleIdentifier :: EventloopModuleIdentifier
keyboardModuleIdentifier = "keyboard"

                  
instance FromJSON Keyboard where
    parseJSON (Object v) = Key <$> v .: "key"

    
keyboardInitializer :: Initializer
keyboardInitializer sharedConst sharedIO
    = do
        (clientSocket, clientConn, serverSock) <- setupWebsocketConnection iNADDR_ANY  keyboardPort
        safePrintLn (safePrintToken sharedConst) "Keyboard connection successfull"
        return (sharedConst, sharedIO, KeyboardConstants clientSocket clientConn serverSock, NoState)

                            
keyboardEventRetriever :: EventRetriever
keyboardEventRetriever sharedConst sharedIOT ioConst ioStateT
    = do
        isConnected <- isConnected sock
        case isConnected of
            False -> return []
            True -> do
                messageM <- takeMessage safePrintToken_ sock conn
                case messageM of
                    Nothing -> return []
                    (Just message) -> return [InKeyboard $ messageToKeyboardIn message]
    where
        sock = clientSocket ioConst
        conn = clientConnection ioConst
        safePrintToken_ = safePrintToken sharedConst


messageToKeyboardIn :: Message -> Keyboard
messageToKeyboardIn message = fromJust.decode $ BL.pack message


keyboardEventSender :: EventSender
keyboardEventSender sharedConst sharedIOT ioConst ioStateT Stop
    = do
        closeWebsocketConnection safePrintToken_ serverSock clientSock conn
    where
        serverSock = serverSocket ioConst
        clientSock = clientSocket ioConst
        conn = clientConnection ioConst
        safePrintToken_ = safePrintToken sharedConst

keyboardTeardown :: Teardown
keyboardTeardown sharedConst sharedIO ioConst ioState
    = do
        destroyWebsocketConnection serverSock clientSock
        return sharedIO
    where
        serverSock = serverSocket ioConst
        clientSock = clientSocket ioConst
        conn = clientConnection ioConst