{-# LANGUAGE  UndecidableInstances #-}
module IHP.ServerSideComponent.Controller.ComponentsController where

import IHP.ControllerPrelude
import IHP.ServerSideComponent.Types as SSC
import IHP.ServerSideComponent.ControllerFunctions as SSC

import qualified Data.Aeson as Aeson
import qualified IHP.Log as Log

instance (Component component controller, FromJSON controller) => WSApp (ComponentsController component) where
    initialState :: ComponentsController component
initialState = ComponentsController component
forall {k} (components :: k). ComponentsController components
ComponentsController

    run :: (?state::IORef (ComponentsController component),
 ?context::ControllerContext,
 ?applicationContext::ApplicationContext,
 ?modelContext::ModelContext, ?connection::Connection) =>
IO ()
run = do
        let component
state :: component = component
forall state action. Component state action => state
SSC.initialState
        IORef (ComponentInstance component)
instanceRef <- ComponentInstance component
-> IO (IORef (ComponentInstance component))
forall a. a -> IO (IORef a)
newIORef (ComponentInstance { component
state :: component
$sel:state:ComponentInstance :: component
state })
        let ?instanceRef = ?instanceRef::IORef (ComponentInstance component)
IORef (ComponentInstance component)
instanceRef

        component
nextState <- component -> IO component
forall state action.
(Component state action,
 ?instanceRef::IORef (ComponentInstance state),
 ?connection::Connection, ?context::ControllerContext,
 ?modelContext::ModelContext) =>
state -> IO state
componentDidMount component
state
        component -> IO ()
forall state action.
(?instanceRef::IORef (ComponentInstance state),
 ?connection::Connection, Component state action,
 ?context::ControllerContext) =>
state -> IO ()
SSC.setState component
nextState

        IO () -> IO ()
forall (f :: * -> *) a b. Applicative f => f a -> f b
forever do
            LByteString
actionPayload :: LByteString <- IO LByteString
forall a. (?connection::Connection, WebSocketsData a) => IO a
receiveData

            let theAction :: Either String controller
theAction = forall a. FromJSON a => LByteString -> Either String a
Aeson.eitherDecode @controller LByteString
actionPayload

            case Either String controller
theAction of
                Right controller
theAction -> do
                    component
currentState <- IO component
forall state.
(?instanceRef::IORef (ComponentInstance state)) =>
IO state
SSC.getState

                    component
nextState <- component -> controller -> IO component
forall state action.
(Component state action,
 ?instanceRef::IORef (ComponentInstance state),
 ?connection::Connection, ?context::ControllerContext,
 ?modelContext::ModelContext) =>
state -> action -> IO state
SSC.action component
currentState controller
theAction
                    component -> IO ()
forall state action.
(?instanceRef::IORef (ComponentInstance state),
 ?connection::Connection, Component state action,
 ?context::ControllerContext) =>
state -> IO ()
SSC.setState component
nextState
                Left String
error -> do
                    Text -> IO ()
forall context string.
(?context::context, LoggingProvider context, ToLogStr string) =>
string -> IO ()
Log.error (Text
"Failed Parsing Server Side Component Message As JSON" :: Text)
                    LByteString -> IO ()
forall context string.
(?context::context, LoggingProvider context, ToLogStr string) =>
string -> IO ()
Log.error LByteString
actionPayload
                    String -> IO ()
forall context string.
(?context::context, LoggingProvider context, ToLogStr string) =>
string -> IO ()
Log.error String
error