--{-# LANGUAGE TupleSections #-}
{- |
Find which objects lie upon a line.
 -}
module Dodge.WorldEvent.ThingsHit
    ( thingsHit
    , thingHit
    , thingsHitExceptCr
    )
    where
import Dodge.Data
import Dodge.Base
import Dodge.Zone
import Geometry

--import Data.Maybe
import Data.Bifunctor
import StreamingHelp
import qualified Streaming.Prelude as S

{- List those objects that appear on a line.  -}
thingsHit
    :: Point2    -- ^ Line start point
    -> Point2    -- ^ Line end point
    -> World 
    -> StreamOf (Point2, Either Creature Wall)
thingsHit sp ep w = void $ S.mergeOn (dist sp . fst)  
    (S.map (second Left)  (crsHit sp ep w))
    (S.map (second Right) (wlsHit sp ep w))

crsHit :: Point2 -> Point2 -> World -> StreamOf (Point2, Creature)
crsHit sp ep
    | sp == ep  = const mempty
    | otherwise = sortStreamOn (dist sp . fst)
        . overlap1SegCrs sp ep
        . crsNearSeg sp ep

thingHit :: Point2 -> Point2 -> World -> Maybe (Point2, Either Creature Wall)
thingHit sp ep = runIdentity . S.head_ . thingsHit sp ep

{- List objects that appear on a line.
Can filter out a creature.  -}
thingsHitExceptCr 
    :: Maybe Int -- ^ A possible creature ID
    -> Point2    -- ^ Line start point
    -> Point2    -- ^ Line end point
    -> World 
    -> StreamOf (Point2, Either Creature Wall)
thingsHitExceptCr Nothing    sp ep = thingsHit sp ep
thingsHitExceptCr (Just cid) sp ep = S.filter crNotCid . thingsHit sp ep
  where 
    crNotCid (_,Left cr) = _crID cr /= cid
    crNotCid _ = True

wlsHit :: Point2 -> Point2 -> World -> StreamOf (Point2, Wall)
wlsHit sp ep
    | sp == ep  = const mempty
    | otherwise = sortStreamOn (dist sp . fst)
        . overlapSegWalls sp ep
        . wlsNearSeg sp ep
