{-# OPTIONS_GHC -Wno-redundant-constraints #-}

module Mischief.ECS.Components.Bundle where

import Data.Bifunctor qualified
import Data.Set qualified as Set
import Data.Typeable
import Mischief.ECS.Collectable (Collectable (collect))
import Mischief.ECS.Components

newtype ProcessedBundleData = ProcessedBundleData {ProcessedBundleData -> [ProcessedBundleElement]
elements :: [ProcessedBundleElement]}

data ProcessedBundleElement = ProcessedBundleElement {ProcessedBundleElement -> ComponentId
id :: ComponentId, ProcessedBundleElement -> ComponentData
component :: ComponentData}

addComponentToBundleData :: forall c. (Component c) => c -> BundleData ErasedComponent -> BundleData ErasedComponent
addComponentToBundleData :: forall c.
Component c =>
c -> BundleData ErasedComponent -> BundleData ErasedComponent
addComponentToBundleData c
c (BundleData {Set (BundleElement ErasedComponent)
elements :: Set (BundleElement ErasedComponent)
elements :: forall e. BundleData e -> Set (BundleElement e)
elements, Set (BundleElement ErasedComponent)
resources :: Set (BundleElement ErasedComponent)
resources :: forall e. BundleData e -> Set (BundleElement e)
resources, Set (Entity, BundleData ErasedComponent)
external :: Set (Entity, BundleData ErasedComponent)
external :: forall e. BundleData e -> Set (Entity, BundleData e)
external}) =
  let rep :: ComponentRep
rep = ComponentType -> ComponentRep
ComponentRep (ComponentType -> ComponentRep) -> ComponentType -> ComponentRep
forall a b. (a -> b) -> a -> b
$ Proxy c -> ComponentType
forall c. Component c => Proxy c -> ComponentType
ComponentType (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @c)
      component :: ErasedComponent
component = c -> ErasedComponent
forall c. Component c => c -> ErasedComponent
ErasedComponent c
c
      element :: BundleElement ErasedComponent
element = BundleElement {ComponentRep
rep :: ComponentRep
rep :: ComponentRep
rep, ErasedComponent
component :: ErasedComponent
component :: ErasedComponent
component}
   in BundleData {elements :: Set (BundleElement ErasedComponent)
elements = Set (BundleElement ErasedComponent)
-> Set (BundleElement ErasedComponent)
-> Set (BundleElement ErasedComponent)
forall a. Ord a => Set a -> Set a -> Set a
Set.union Set (BundleElement ErasedComponent)
elements (BundleElement ErasedComponent
-> Set (BundleElement ErasedComponent)
forall a. a -> Set a
Set.singleton BundleElement ErasedComponent
element), Set (BundleElement ErasedComponent)
resources :: Set (BundleElement ErasedComponent)
resources :: Set (BundleElement ErasedComponent)
resources, Set (Entity, BundleData ErasedComponent)
external :: Set (Entity, BundleData ErasedComponent)
external :: Set (Entity, BundleData ErasedComponent)
external}

instance Eq ProcessedBundleElement where
  (==) :: ProcessedBundleElement -> ProcessedBundleElement -> Bool
  == :: ProcessedBundleElement -> ProcessedBundleElement -> Bool
(==) ProcessedBundleElement {id :: ProcessedBundleElement -> ComponentId
id = ComponentId
id1} ProcessedBundleElement {id :: ProcessedBundleElement -> ComponentId
id = ComponentId
id2} = ComponentId
id1 ComponentId -> ComponentId -> Bool
forall a. Eq a => a -> a -> Bool
== ComponentId
id2

instance Ord ProcessedBundleElement where
  compare :: ProcessedBundleElement -> ProcessedBundleElement -> Ordering
  compare :: ProcessedBundleElement -> ProcessedBundleElement -> Ordering
compare ProcessedBundleElement {id :: ProcessedBundleElement -> ComponentId
id = ComponentId
id1} ProcessedBundleElement {id :: ProcessedBundleElement -> ComponentId
id = ComponentId
id2} = ComponentId -> ComponentId -> Ordering
forall a. Ord a => a -> a -> Ordering
compare ComponentId
id1 ComponentId
id2

type Bundle b = Collectable b (BundleData ErasedComponent)

bundleData :: (Bundle b) => b -> BundleData ErasedComponent
bundleData :: forall b. Bundle b => b -> BundleData ErasedComponent
bundleData = b -> BundleData ErasedComponent
forall v storage. Collectable v storage => v -> storage
collect

type BundleEq b = Collectable b (BundleData ErasedComponentEq)

bundleDataEq :: (BundleEq b) => b -> BundleData ErasedComponentEq
bundleDataEq :: forall b. BundleEq b => b -> BundleData ErasedComponentEq
bundleDataEq = b -> BundleData ErasedComponentEq
forall v storage. Collectable v storage => v -> storage
collect

bundleEqToSimple :: BundleData ErasedComponentEq -> BundleData ErasedComponent
bundleEqToSimple :: BundleData ErasedComponentEq -> BundleData ErasedComponent
bundleEqToSimple BundleData {Set (BundleElement ErasedComponentEq)
elements :: forall e. BundleData e -> Set (BundleElement e)
elements :: Set (BundleElement ErasedComponentEq)
elements, Set (BundleElement ErasedComponentEq)
resources :: forall e. BundleData e -> Set (BundleElement e)
resources :: Set (BundleElement ErasedComponentEq)
resources, Set (Entity, BundleData ErasedComponentEq)
external :: forall e. BundleData e -> Set (Entity, BundleData e)
external :: Set (Entity, BundleData ErasedComponentEq)
external} =
  Set (BundleElement ErasedComponent)
-> Set (BundleElement ErasedComponent)
-> Set (Entity, BundleData ErasedComponent)
-> BundleData ErasedComponent
forall e.
Set (BundleElement e)
-> Set (BundleElement e)
-> Set (Entity, BundleData e)
-> BundleData e
BundleData
    ((BundleElement ErasedComponentEq -> BundleElement ErasedComponent)
-> Set (BundleElement ErasedComponentEq)
-> Set (BundleElement ErasedComponent)
forall b a. Ord b => (a -> b) -> Set a -> Set b
Set.map (\BundleElement {ComponentRep
rep :: forall e. BundleElement e -> ComponentRep
rep :: ComponentRep
rep, component :: forall e. BundleElement e -> e
component = ErasedComponentEq (c
a :: s)} -> BundleElement {ComponentRep
rep :: ComponentRep
rep :: ComponentRep
rep, component :: ErasedComponent
component = c -> ErasedComponent
forall c. Component c => c -> ErasedComponent
ErasedComponent c
a}) Set (BundleElement ErasedComponentEq)
elements)
    ((BundleElement ErasedComponentEq -> BundleElement ErasedComponent)
-> Set (BundleElement ErasedComponentEq)
-> Set (BundleElement ErasedComponent)
forall b a. Ord b => (a -> b) -> Set a -> Set b
Set.map (\BundleElement {ComponentRep
rep :: forall e. BundleElement e -> ComponentRep
rep :: ComponentRep
rep, component :: forall e. BundleElement e -> e
component = ErasedComponentEq (c
a :: s)} -> BundleElement {ComponentRep
rep :: ComponentRep
rep :: ComponentRep
rep, component :: ErasedComponent
component = c -> ErasedComponent
forall c. Component c => c -> ErasedComponent
ErasedComponent c
a}) Set (BundleElement ErasedComponentEq)
resources)
    (((Entity, BundleData ErasedComponentEq)
 -> (Entity, BundleData ErasedComponent))
-> Set (Entity, BundleData ErasedComponentEq)
-> Set (Entity, BundleData ErasedComponent)
forall b a. Ord b => (a -> b) -> Set a -> Set b
Set.map ((BundleData ErasedComponentEq -> BundleData ErasedComponent)
-> (Entity, BundleData ErasedComponentEq)
-> (Entity, BundleData ErasedComponent)
forall b c a. (b -> c) -> (a, b) -> (a, c)
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
Data.Bifunctor.second BundleData ErasedComponentEq -> BundleData ErasedComponent
bundleEqToSimple) Set (Entity, BundleData ErasedComponentEq)
external)