module Dodge.WorldEvent.HitEffect
    ( destroyOnImpact
    , doFlameDam
    , noEff
    , penWalls
    ) where
import Dodge.Data
import Geometry

import Data.Bifunctor
import Control.Lens

type HitCreatureEffect   = Particle -> Point2 -> Creature   -> World -> World
type HitWallEffect       = Particle -> Point2 -> Wall       -> World -> World

--passThroughAll 
--    :: HitCreatureEffect 
--    -> HitWallEffect 
--    -> HitForceFieldEffect 
--    -> Particle 
--    -> [(Point2, Either3 Creature Wall ForceField)] -- ^ hit things
--    -> World 
--    -> (World, Maybe Particle)
--passThroughAll _ _ _ pt _ w = (w, mvPt)
--  where 
--    mvPt = Just $ pt & btTrail' .~ (newP : trl)
--                     & btTimer' %~ (\t -> t - 1)
--                     & btPassThrough' .~ Nothing
--    trl = _btTrail' pt
--    newP = head trl +.+ _btVel' pt

destroyOnImpact 
    :: HitCreatureEffect 
    -> HitWallEffect 
    -> Particle 
    -> [(Point2, Either Creature Wall)] 
    -> World 
    -> (World, Maybe Particle)
destroyOnImpact crEff wlEff pt hitThings w = case hitThings of
        []              -> (              w, mvPt pt)
        ((p,Left  cr):_) -> (crEff pt p cr w, destroyAt p pt)
        ((p,Right wl):_) -> (wlEff pt p wl w, destroyAt p pt)

mvPt :: Particle -> Maybe Particle
mvPt pt = Just $ pt
    & btTrail' %~ f
    & btTimer' -~ 1
    & btPassThrough' .~ Nothing
  where
    f trl = head trl +.+ _btVel' pt : trl

destroyAt :: Point2 -> Particle -> Maybe Particle
destroyAt hitp pt = Just $ pt 
    & btTrail' %~ (hitp :)
    & btTimer' %~ (\t -> min 3 (t-1))

penWalls 
    :: HitCreatureEffect 
    -> HitWallEffect 
    -> Particle 
    -> [(Point2, Either Creature Wall)] 
    -> World 
    -> (World, Maybe Particle)
penWalls crEff wlEff pt hitThings w = case hitThings of
        []              -> (              w, mvPt pt)
        ((p,Left cr):_) -> (crEff pt p cr w, destroyAt p pt)
        ((p,Right wl):hs) | _wlFireThrough wl 
                        -> first (wlEff pt p wl) $ penWalls crEff wlEff pt hs w
        ((p,Right wl):_) -> (wlEff pt p wl w, destroyAt p pt)

doFlameDam :: Int -> Particle -> Point2 -> Creature -> World -> World
doFlameDam amount pt p cr = creatures . ix (_crID cr) . crState . crDamage %~
    (Flaming amount sp p ep :)
  where 
    sp = _btPos' pt
    ep = sp +.+ _btVel' pt

noEff :: a -> b -> c -> d -> d
noEff _ _ _ = id
