module Dodge.Zone.Update 
    ( updateZoning
    ) where
import Dodge.Data.Zoning
import StreamingHelp
import qualified Streaming.Prelude as S
import qualified Data.IntMap.Strict as IM
import Geometry
import LensHelp

updateZoning :: Monoid (t a) => (a -> t a -> t a) -> a -> Zoning t a -> Zoning t a
{-# INLINE updateZoning #-}
updateZoning f obj zn = runIdentity (S.fold_ doinsert zn id (_znFunc zn (_znSize zn) obj))
  where
    doinsert znobs vxy = insertInZoneWith vxy (\_ -> f obj) (f obj mempty) znobs

insertInZoneWith
    :: Int2
    -> (t a -> t a -> t a) -- ^ Combining function
    -> t a            -- ^ Value to insert
    -> Zoning t a 
    -> Zoning t a
{-# INLINE insertInZoneWith #-}
insertInZoneWith (V2 x y) fun obj = over znObjects $ IM.insertWith f x $ IM.singleton y obj
  where
    f _ = IM.insertWith fun y obj
