content: {-# LANGUAGE LambdaCase, OverloadedStrings #-}
  
  module Mud.Data.State.Util.Effect ( procEffectList
                                    , procInstaEffect ) where
  
  import           Mud.Data.Misc
  import           Mud.Data.State.MudData
  import           Mud.Data.State.Util.Get
  import           Mud.Data.State.Util.Misc
  import           Mud.Data.State.Util.Random
  import qualified Mud.Misc.Logging as L (logPla)
  import           Mud.Threads.Effect
  import           Mud.Threads.FeelingTimer
  import           Mud.Util.Misc
  
  import           Control.Lens.Operators ((.~), (&), (^.))
  import           Control.Monad (when)
  import           Data.Either (partitionEithers)
  import           Data.Monoid ((<>))
  import           Data.Text (Text)
  import           GHC.Stack (HasCallStack)
  
  logPla :: Text -> Id -> Text -> MudStack ()
  logPla = L.logPla "Mud.Data.State.Util.Effect"
  
  -- ==================================================
  
  procEffectList :: HasCallStack => Id -> EffectList -> MudStack ()
  procEffectList i (EffectList xs) = let (ies, es) = partitionEithers xs
                                     in mapM_ (procInstaEffect i) ies >> mapM_ (startEffect i) es
  
  -----
  
  procInstaEffect :: HasCallStack => Id -> InstaEffect -> MudStack ()
  procInstaEffect i ie@(InstaEffect sub val feel) = getState >>= \ms -> do
      logHelper ms
      case sub of
        EntInstaEffectFlags         -> undefined -- TODO
        (MobInstaEffectPts ptsType) -> maybeVoid (effectPts ptsType) val
        RmInstaEffectFlags          -> undefined -- TODO
        (InstaEffectOther fn)       -> getInstaEffectFun fn ms i >> startFeelingHelper FeelingNoVal feel
    where
      startFeelingHelper  = maybeVoid . flip (startFeeling i)
      effectPts ptsType   = (helper ptsType =<<) . \case EffectFixedVal  x -> return x
                                                         EffectRangedVal r -> rndmR r
      helper    ptsType x = let (getCur, getMax, setCur) = case ptsType of Hp -> (curHp, maxHp, curHp)
                                                                           Mp -> (curMp, maxHp, curMp)
                                                                           Pp -> (curPp, maxHp, curPp)
                                                                           Fp -> (curFp, maxHp, curFp)
                            in do diff <- modifyState $ \ms -> let curPts = ms^.myMobGet.getCur
                                                                   maxPts = ms^.myMobGet.getMax
                                                                   newPts = (curPts + x) `min` maxPts
                                                                   diff   = newPts - curPts
                                                               in (ms & myMobSet.setCur .~ newPts, diff)
                                  startFeelingHelper (FeelingFixedVal diff) feel
      myMobGet     = mobTbl.ind i
      myMobSet     = mobTbl.ind i
      logHelper ms = let f = logPla "procInstaEffect" i $ "applying instantaneous effect: " <> pp ie
                     in when (getType i ms == PlaType) f
  