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

module Mischief.ECS.Components.Bundle where

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}) =
  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)}

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 ErasedComponent) -> BundleData ErasedComponent
forall e. Set (BundleElement e) -> BundleData e
BundleData (Set (BundleElement ErasedComponent) -> BundleData ErasedComponent)
-> Set (BundleElement ErasedComponent)
-> BundleData ErasedComponent
forall a b. (a -> b) -> a -> b
$ (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