-- |
-- Module      :  Games.ECS
-- Description : Re-exports the public API.
-- Copyright   :  (C) 2020 Sophie Taylor
-- License     :  AGPL-3.0-or-later
-- Maintainer  :  Sophie Taylor <sophie@spacekitteh.moe>
-- Stability   :  experimental
-- Portability: GHC
--
-- This is the top-level interface to OhhECS. A brief tutorial should probably go here.
--
-- @
--   
--  import GHC.Generics
--  import Control.Lens
--    
--  data Position = Position Int Int
--    deriving stock (Generic, Eq, Show)
--      
--  instance Num Position where
--   (Position a b) + (Position c d) = Position (a + c) (b + d)
--   (*) = undefined
--   abs = undefined
--   signum = undefined
--   fromInteger = undefined
--   negate = undefined
--     
--  instance 'Component' Position where
--    type 'CanonicalName' Position = "position"
--      
--  'makeHasComponentClass' ''Position
--    
--  data GameWorld s where
--    GameWorld ::
--      'EntRefField' s ->
--      'AComponent' "position" s Position ->
--      GameWorld s
--   deriving stock (Generic)     
--  deriving instance Show (GameWorld Individual)
--  deriving instance Show (GameWorld Storing)
--  deriving instance Eq (GameWorld Individual)
--  deriving instance Eq (GameWorld Storing)    
--  'makeWorld' ''GameWorld   
--   
--  data MovementSystem = MovementSystem deriving (Eq, Show, Generic)
--    
--  instance (UsingPosition worldType Individual, Monad m) => 'System' \"MovementSystem\" MovementSystem worldType m where
--    type 'ComponentFilters' \"MovementSystem\" MovementSystem worldType m = (UsingPosition worldType Individual)   
--    'runSystem' world = traverseOf ('entitiesWith' (withPosition)) processCritter world
--      where
--        processCritter :: worldType 'Individual' -> m (worldType 'Individual')
--        processCritter oldCritter = do
--          let newCritter = oldCritter & position .~ (Position 1 0)
--          pure newCritter
--            
--  someEntity :: GameWorld 'Individual'
--  someEntity = ('createNewEntityWithRef' ('EntRef' 123))  & addPosition .~ Position 4 5
--    
--  myWorld :: GameWorld 'Storing'
--  myWorld = newWorld & 'storeEntity' someEntity
--    
--  changed :: IO (GameWorld 'Storing')
--  changed = 'runSystem' @\"MovementSystem\" myWorld
--
-- @
--

module Games.ECS
  ( module Games.ECS,
    module Games.ECS.Util.Misc,
    module Games.ECS.Component,
    module Games.ECS.Serialisation,
    module Games.ECS.Component.Store,
    module Games.ECS.Component.TH,
    module Games.ECS.World,
    module Games.ECS.World.TH,
    module Games.ECS.Entity,
    module Games.ECS.SaveLoad,
    module Games.ECS.System,
    module Games.ECS.Slot,
    module Games.ECS.Prototype,
    module Games.ECS.Prototype.PrototypeID,
    module Games.ECS.Prototype.SpawnedFromPrototype,
    module Games.ECS.MessageQueue,
  )
where

import Control.Lens (IndexedTraversal')
import Games.ECS.Component
import Games.ECS.Component.Store
import Games.ECS.Component.TH
import Games.ECS.Entity
import Games.ECS.MessageQueue
import Games.ECS.Prototype
import Games.ECS.Prototype.PrototypeID
import Games.ECS.Prototype.SpawnedFromPrototype    
import Games.ECS.SaveLoad
import Games.ECS.Serialisation
import Games.ECS.Slot
import Games.ECS.System
import Games.ECS.Util.Misc
import Games.ECS.World
import Games.ECS.World.TH

-- | A filter over entities in a world is just an `IndexedTraversal'` that preserves the selection predicate.
type EntityFilter worldType = IndexedTraversal' Entity (worldType Storing) (worldType Individual)


-- $setup
-- >>> :{   

-- :}