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

module Mischief.Assets.Asset
  ( Asset (..),
    OnLoad (..),
    setAssetSource,
    load,
    load_,
    loadRec,
    loadRec_,
    reload,
    retrieve,
    asset,
    assetRec,
    asset',
    Mischief.Assets.Asset.store,
    Mischief.Assets.Asset.save,
    saveEntity,
    Loaded,
    Loading,
    AssetType,
    decodeRef,
    Rec,
    addRec,
  )
where

import Control.Monad (void)
import Data.Set qualified as Set
import Data.Text (Text)
import Mischief.Assets.Internal.Asset
import Mischief.Assets.Internal.Path
import Mischief.ECS

load :: forall a. ((Loadable a ~ True), Asset a, Bundle a) => Text -> System Entity
load :: forall a.
(Loadable a ~ 'True, Asset a, Bundle a) =>
Text -> System Entity
load = forall a. (Asset a, Bundle a) => Text -> System Entity
loadByRelPath @a

load_ :: forall a. ((Loadable a ~ True), Asset a, Bundle a) => Text -> System ()
load_ :: forall a.
(Loadable a ~ 'True, Asset a, Bundle a) =>
Text -> System ()
load_ = System Entity -> System ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (System Entity -> System ())
-> (Text -> System Entity) -> Text -> System ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a.
(Loadable a ~ 'True, Asset a, Bundle a) =>
Text -> System Entity
load @a

loadRec :: forall a. ((Loadable a ~ True), Asset a, Bundle a) => Text -> System Entity
loadRec :: forall a.
(Loadable a ~ 'True, Asset a, Bundle a) =>
Text -> System Entity
loadRec Text
t = do
  e <- forall a. (Asset a, Bundle a) => Text -> System Entity
loadByRelPath @a Text
t
  insert LoadRec e
  pure e

loadRec_ :: forall a. ((Loadable a ~ True), Asset a, Bundle a) => Text -> System ()
loadRec_ :: forall a.
(Loadable a ~ 'True, Asset a, Bundle a) =>
Text -> System ()
loadRec_ Text
t = do
  e <- forall a. (Asset a, Bundle a) => Text -> System Entity
loadByRelPath @a Text
t
  insert LoadRec e

reload :: forall a. ((Loadable a ~ True), Asset a, Bundle a) => Text -> System Entity
reload :: forall a.
(Loadable a ~ 'True, Asset a, Bundle a) =>
Text -> System Entity
reload = forall a. (Asset a, Bundle a) => Text -> System Entity
reloadByRelPath @a

assetRec :: forall a. AssetRef a -> System (Maybe a)
assetRec :: forall a. AssetRef a -> System (Maybe a)
assetRec AssetRef a
a = AssetRef a -> Bool -> Set TypeRep -> System (Maybe a)
forall a. AssetRef a -> Bool -> Set TypeRep -> System (Maybe a)
getAsset AssetRef a
a Bool
True Set TypeRep
forall a. Set a
Set.empty

asset :: forall a. AssetRef a -> System (Maybe a)
asset :: forall a. AssetRef a -> System (Maybe a)
asset AssetRef a
a = AssetRef a -> Bool -> Set TypeRep -> System (Maybe a)
forall a. AssetRef a -> Bool -> Set TypeRep -> System (Maybe a)
getAsset AssetRef a
a Bool
False Set TypeRep
forall a. Set a
Set.empty

asset' :: forall a. AssetRef a -> System (Maybe a)
asset' :: forall a. AssetRef a -> System (Maybe a)
asset' = AssetRef a -> System (Maybe a)
forall a w (m :: * -> *).
MonadSystem w m =>
AssetRef a -> m (Maybe a)
getAsset'

retrieve :: forall a. AssetRef a -> System (Maybe Entity)
retrieve :: forall a. AssetRef a -> System (Maybe Entity)
retrieve = forall a. AssetRef a -> System (Maybe Entity)
getRefEntity @a

retrieve' :: forall a. AssetRef a -> System (Maybe Entity)
retrieve' :: forall a. AssetRef a -> System (Maybe Entity)
retrieve' = forall a w (m :: * -> *).
MonadSystem w m =>
AssetRef a -> m (Maybe Entity)
getRefEntity' @a

store :: (Asset a, Bundle a) => Text -> a -> System Entity
store :: forall a. (Asset a, Bundle a) => Text -> a -> System Entity
store = Text -> a -> System Entity
forall a. (Asset a, Bundle a) => Text -> a -> System Entity
Mischief.Assets.Internal.Asset.store

save :: forall a. (Asset a, Saveable a ~ True, Bundle a) => Text -> System ()
save :: forall a.
(Asset a, Saveable a ~ 'True, Bundle a) =>
Text -> System ()
save Text
path = do
  e <- forall a. AssetRef a -> System (Maybe Entity)
retrieve' @a (Text -> AssetRef a
forall a. (Asset a, Bundle a) => Text -> AssetRef a
Ref Text
path)
  case e of
    Maybe Entity
Nothing -> Text -> System ()
forall w (m :: * -> *).
(HasCallStack, MonadSystem w m) =>
Text -> m ()
warn Text
"Attempted to save an asset which isn't stored"
    Just Entity
e -> forall a. Asset a => Entity -> System ()
Mischief.Assets.Internal.Asset.save @a Entity
e

saveEntity :: forall a. (Asset a, Saveable a ~ True) => Entity -> System ()
saveEntity :: forall a. (Asset a, Saveable a ~ 'True) => Entity -> System ()
saveEntity = forall a. Asset a => Entity -> System ()
Mischief.Assets.Internal.Asset.save @a