--{-# LANGUAGE TupleSections #-}
module Dodge.Room.SensorDoor where
import Dodge.Annotation.Data
import Dodge.Cleat
import Dodge.LevelGen.Data
import Dodge.PlacementSpot
import Dodge.Placement.Instance.Terminal
import Dodge.Terminal
import Dodge.Data
import Dodge.Tree
import Dodge.Wire
--import Dodge.RoomLink
import Dodge.Room.Door
import Dodge.Room.Ngon
import Dodge.Room.Procedural
import Dodge.Room.Corridor
import Dodge.Room.Link
import Dodge.Placement.Instance
import Geometry
import LensHelp
import RandomHelp

import qualified Data.Set as S
import Data.Maybe
--import Data.Tree

-- TODO fix case where the sensor created by sensInsideDoor blocks another door
-- for roomRectAutoLinks-- make the locked door a center door?
sensorRoom :: RandomGen g => DamageType -> Int -> State g (Tree Room)
sensorRoom senseType n = do
    rm <- takeOne [roomNgon 8 200, roomRectAutoLinks 200 200]
    cenroom <- shuffleLinks $ sensInsideDoor senseType n rm
    return $ treePost 
        [ door
        , cenroom & rmLinkEff .~ f
        , triggerDoorRoom n
        , cleatOnward door
        ]
  where
    f _ _ 0 rl rm = rm & rmLinks %~ map (g (_rlPos rl) (_rlDir rl))
    f _ _ _ _ rm = rm
    g p d rl
        | isclose = rl & rlType . at BlockedLink ?~ ()
        | otherwise = rl
      where
        p' = p +.+ rotateV d (V2 0 (negate 100))
        isclose = dist (_rlPos rl) p' < 30

sensorRoomRunPast :: RandomGen g => DamageType -> Int -> State g MTRS
sensorRoomRunPast dt n = do
    t <- sensorRoom dt n
    rToOnward "sensorRoomRunPast" $ t & applyToSubforest [0] 
        (++
            [treePost 
                [ door & rmConnectsTo .~ (\s -> S.member InLink s && not (S.member BlockedLink s))
                , cleatLabel n corridor ]
            ]
        ) 

sensAboveDoor :: DamageType -> Float -> PlacementSpot -> Placement
sensAboveDoor sensetype wth ps = extTrigLitPos 
    (atFstLnkOutShiftBy (\(p,a) -> (p +.+ rotateV a (V2 18.5 (-2.5)), a)))
    ( \tp -> Just $ damageSensor sensetype wth (upf $ fromJust $ _plMID tp) ps )
  where
    upf trid mc w | _sensAmount (_mcSensor mc) > 900 = w & triggers . ix trid .~ const True
        | otherwise = w

sensInsideDoor :: DamageType -> Int -> Room -> Room
sensInsideDoor senseType outplid rm = rm
    & rmName .++~ take 4 (show senseType)
    & rmPmnts .++~ 
        [ psPt atFstLnkOut . PutForeground $ floorWire (V2 20 0) (V2 20 (-100))
        , psPt atFstLnkOut . PutForeground $ floorWire (V2 0 (-100)) (V2 20 (-100))
        , psPt atFstLnkOut . PutForeground $ verticalWire (V2 20 0) 0 80
        , putTerminal terminalColor (basicTerminal & tmScrollCommands .:~ damageCodeCommand)
            & plSpot .~ rprBoolShift isUnusedLnk (shiftInBy 10)
        ]
    & rmOutPmnt .~ [OutPlacement (sensAboveDoor senseType 10 (atFstLnkOutShiftInward 100)) outplid]
