{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}

module Data.Aztecs.Access where

import Control.Monad.IO.Class (MonadIO)
import Control.Monad.State (MonadState (..), StateT (..))
import Data.Aztecs.Core (Component (..), EntityID)
import Data.Aztecs.World (World)
import qualified Data.Aztecs.World as W
import Data.Data (Typeable)

newtype Access m a = Access {forall (m :: * -> *) a. Access m a -> StateT World m a
unAccess :: StateT World m a}
  deriving ((forall a b. (a -> b) -> Access m a -> Access m b)
-> (forall a b. a -> Access m b -> Access m a)
-> Functor (Access m)
forall a b. a -> Access m b -> Access m a
forall a b. (a -> b) -> Access m a -> Access m b
forall (m :: * -> *) a b.
Functor m =>
a -> Access m b -> Access m a
forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> Access m a -> Access m b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> Access m a -> Access m b
fmap :: forall a b. (a -> b) -> Access m a -> Access m b
$c<$ :: forall (m :: * -> *) a b.
Functor m =>
a -> Access m b -> Access m a
<$ :: forall a b. a -> Access m b -> Access m a
Functor, Functor (Access m)
Functor (Access m) =>
(forall a. a -> Access m a)
-> (forall a b. Access m (a -> b) -> Access m a -> Access m b)
-> (forall a b c.
    (a -> b -> c) -> Access m a -> Access m b -> Access m c)
-> (forall a b. Access m a -> Access m b -> Access m b)
-> (forall a b. Access m a -> Access m b -> Access m a)
-> Applicative (Access m)
forall a. a -> Access m a
forall a b. Access m a -> Access m b -> Access m a
forall a b. Access m a -> Access m b -> Access m b
forall a b. Access m (a -> b) -> Access m a -> Access m b
forall a b c.
(a -> b -> c) -> Access m a -> Access m b -> Access m c
forall (m :: * -> *). Monad m => Functor (Access m)
forall (m :: * -> *) a. Monad m => a -> Access m a
forall (m :: * -> *) a b.
Monad m =>
Access m a -> Access m b -> Access m a
forall (m :: * -> *) a b.
Monad m =>
Access m a -> Access m b -> Access m b
forall (m :: * -> *) a b.
Monad m =>
Access m (a -> b) -> Access m a -> Access m b
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> c) -> Access m a -> Access m b -> Access m c
forall (f :: * -> *).
Functor f =>
(forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
$cpure :: forall (m :: * -> *) a. Monad m => a -> Access m a
pure :: forall a. a -> Access m a
$c<*> :: forall (m :: * -> *) a b.
Monad m =>
Access m (a -> b) -> Access m a -> Access m b
<*> :: forall a b. Access m (a -> b) -> Access m a -> Access m b
$cliftA2 :: forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> c) -> Access m a -> Access m b -> Access m c
liftA2 :: forall a b c.
(a -> b -> c) -> Access m a -> Access m b -> Access m c
$c*> :: forall (m :: * -> *) a b.
Monad m =>
Access m a -> Access m b -> Access m b
*> :: forall a b. Access m a -> Access m b -> Access m b
$c<* :: forall (m :: * -> *) a b.
Monad m =>
Access m a -> Access m b -> Access m a
<* :: forall a b. Access m a -> Access m b -> Access m a
Applicative, Applicative (Access m)
Applicative (Access m) =>
(forall a b. Access m a -> (a -> Access m b) -> Access m b)
-> (forall a b. Access m a -> Access m b -> Access m b)
-> (forall a. a -> Access m a)
-> Monad (Access m)
forall a. a -> Access m a
forall a b. Access m a -> Access m b -> Access m b
forall a b. Access m a -> (a -> Access m b) -> Access m b
forall (m :: * -> *). Monad m => Applicative (Access m)
forall (m :: * -> *) a. Monad m => a -> Access m a
forall (m :: * -> *) a b.
Monad m =>
Access m a -> Access m b -> Access m b
forall (m :: * -> *) a b.
Monad m =>
Access m a -> (a -> Access m b) -> Access m b
forall (m :: * -> *).
Applicative m =>
(forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
$c>>= :: forall (m :: * -> *) a b.
Monad m =>
Access m a -> (a -> Access m b) -> Access m b
>>= :: forall a b. Access m a -> (a -> Access m b) -> Access m b
$c>> :: forall (m :: * -> *) a b.
Monad m =>
Access m a -> Access m b -> Access m b
>> :: forall a b. Access m a -> Access m b -> Access m b
$creturn :: forall (m :: * -> *) a. Monad m => a -> Access m a
return :: forall a. a -> Access m a
Monad, Monad (Access m)
Monad (Access m) =>
(forall a. IO a -> Access m a) -> MonadIO (Access m)
forall a. IO a -> Access m a
forall (m :: * -> *).
Monad m =>
(forall a. IO a -> m a) -> MonadIO m
forall (m :: * -> *). MonadIO m => Monad (Access m)
forall (m :: * -> *) a. MonadIO m => IO a -> Access m a
$cliftIO :: forall (m :: * -> *) a. MonadIO m => IO a -> Access m a
liftIO :: forall a. IO a -> Access m a
MonadIO)

runAccess :: Access m a -> World -> m (a, World)
runAccess :: forall (m :: * -> *) a. Access m a -> World -> m (a, World)
runAccess Access m a
a = StateT World m a -> World -> m (a, World)
forall s (m :: * -> *) a. StateT s m a -> s -> m (a, s)
runStateT (Access m a -> StateT World m a
forall (m :: * -> *) a. Access m a -> StateT World m a
unAccess Access m a
a)

spawn :: (Monad m, Component a, Typeable (StorageT a)) => a -> Access m EntityID
spawn :: forall (m :: * -> *) a.
(Monad m, Component a, Typeable (StorageT a)) =>
a -> Access m EntityID
spawn a
c = StateT World m EntityID -> Access m EntityID
forall (m :: * -> *) a. StateT World m a -> Access m a
Access (StateT World m EntityID -> Access m EntityID)
-> StateT World m EntityID -> Access m EntityID
forall a b. (a -> b) -> a -> b
$ do
  World
w <- StateT World m World
forall s (m :: * -> *). MonadState s m => m s
get
  let (EntityID
e, World
w') = a -> World -> (EntityID, World)
forall a.
(Component a, Typeable (StorageT a)) =>
a -> World -> (EntityID, World)
W.spawn a
c World
w
  World -> StateT World m ()
forall s (m :: * -> *). MonadState s m => s -> m ()
put World
w'
  EntityID -> StateT World m EntityID
forall a. a -> StateT World m a
forall (m :: * -> *) a. Monad m => a -> m a
return EntityID
e

insert :: (Monad m, Component a, Typeable (StorageT a)) => EntityID -> a -> Access m ()
insert :: forall (m :: * -> *) a.
(Monad m, Component a, Typeable (StorageT a)) =>
EntityID -> a -> Access m ()
insert EntityID
e a
c = StateT World m () -> Access m ()
forall (m :: * -> *) a. StateT World m a -> Access m a
Access (StateT World m () -> Access m ())
-> StateT World m () -> Access m ()
forall a b. (a -> b) -> a -> b
$ do
  World
w <- StateT World m World
forall s (m :: * -> *). MonadState s m => m s
get
  let w' :: World
w' = EntityID -> a -> World -> World
forall a.
(Component a, Typeable (StorageT a)) =>
EntityID -> a -> World -> World
W.insert EntityID
e a
c World
w
  World -> StateT World m ()
forall s (m :: * -> *). MonadState s m => s -> m ()
put World
w'