{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE KindSignatures #-}

-- |
-- Module      : Aztecs.ECS.World.Archetype.Internal
-- Copyright   : (c) Matt Hunzinger, 2025
-- License     : BSD-style (see the LICENSE file in the distribution)
--
-- Maintainer  : matt@hunzinger.me
-- Stability   : provisional
-- Portability : non-portable (GHC extensions)
module Aztecs.ECS.World.Archetype.Internal (Archetype (..), empty) where

import Aztecs.ECS.Entity (EntityID)
import Aztecs.ECS.World.Storage.Dynamic (DynamicStorage)
import Data.IntMap (IntMap)
import qualified Data.IntMap as IntMap
import Data.Kind (Type)
import Data.Set (Set)
import qualified Data.Set as Set
import GHC.Generics

-- | Archetype of entities and components.
-- An archetype is guranteed to contain one of each stored component per entity.
data Archetype (m :: Type -> Type) = Archetype
  { -- | Component storages.
    forall (m :: * -> *). Archetype m -> IntMap DynamicStorage
storages :: !(IntMap DynamicStorage),
    -- | Entities stored in this archetype.
    forall (m :: * -> *). Archetype m -> Set EntityID
entities :: !(Set EntityID)
  }
  deriving (Int -> Archetype m -> ShowS
[Archetype m] -> ShowS
Archetype m -> String
(Int -> Archetype m -> ShowS)
-> (Archetype m -> String)
-> ([Archetype m] -> ShowS)
-> Show (Archetype m)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall (m :: * -> *). Int -> Archetype m -> ShowS
forall (m :: * -> *). [Archetype m] -> ShowS
forall (m :: * -> *). Archetype m -> String
$cshowsPrec :: forall (m :: * -> *). Int -> Archetype m -> ShowS
showsPrec :: Int -> Archetype m -> ShowS
$cshow :: forall (m :: * -> *). Archetype m -> String
show :: Archetype m -> String
$cshowList :: forall (m :: * -> *). [Archetype m] -> ShowS
showList :: [Archetype m] -> ShowS
Show, (forall x. Archetype m -> Rep (Archetype m) x)
-> (forall x. Rep (Archetype m) x -> Archetype m)
-> Generic (Archetype m)
forall x. Rep (Archetype m) x -> Archetype m
forall x. Archetype m -> Rep (Archetype m) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (m :: * -> *) x. Rep (Archetype m) x -> Archetype m
forall (m :: * -> *) x. Archetype m -> Rep (Archetype m) x
$cfrom :: forall (m :: * -> *) x. Archetype m -> Rep (Archetype m) x
from :: forall x. Archetype m -> Rep (Archetype m) x
$cto :: forall (m :: * -> *) x. Rep (Archetype m) x -> Archetype m
to :: forall x. Rep (Archetype m) x -> Archetype m
Generic)

instance Semigroup (Archetype m) where
  Archetype m
a <> :: Archetype m -> Archetype m -> Archetype m
<> Archetype m
b = Archetype {storages :: IntMap DynamicStorage
storages = Archetype m -> IntMap DynamicStorage
forall (m :: * -> *). Archetype m -> IntMap DynamicStorage
storages Archetype m
a IntMap DynamicStorage
-> IntMap DynamicStorage -> IntMap DynamicStorage
forall a. Semigroup a => a -> a -> a
<> Archetype m -> IntMap DynamicStorage
forall (m :: * -> *). Archetype m -> IntMap DynamicStorage
storages Archetype m
b, entities :: Set EntityID
entities = Archetype m -> Set EntityID
forall (m :: * -> *). Archetype m -> Set EntityID
entities Archetype m
a Set EntityID -> Set EntityID -> Set EntityID
forall a. Semigroup a => a -> a -> a
<> Archetype m -> Set EntityID
forall (m :: * -> *). Archetype m -> Set EntityID
entities Archetype m
b}

instance Monoid (Archetype m) where
  mempty :: Archetype m
mempty = Archetype m
forall (m :: * -> *). Archetype m
empty

-- | Empty archetype.
empty :: Archetype m
empty :: forall (m :: * -> *). Archetype m
empty = Archetype {storages :: IntMap DynamicStorage
storages = IntMap DynamicStorage
forall a. IntMap a
IntMap.empty, entities :: Set EntityID
entities = Set EntityID
forall a. Set a
Set.empty}