module Dodge.Creature.SentinelAI
    where
import Dodge.Data
import Dodge.Base.Collide
import Dodge.Creature.Test
import Dodge.Creature.Volition
import Dodge.Creature.ReaderUpdate
import Dodge.Creature.Strategy
import Dodge.Creature.Action
--import Dodge.Creature.ChooseTarget
import Dodge.Creature.Perception
--import Dodge.Creature.State
--import Dodge.Creature.State.Data
import Geometry.Data
--import Picture
--import Dodge.RandomHelp

import Data.Maybe
--import qualified Data.IntMap.Strict as IM
import Control.Lens
import Control.Monad
import Control.Monad.Reader

sentinelAI :: Creature -> Reader World Creature
sentinelAI = sentinelExtraWatchUpdate
    [ (crHasTargetLOS
      , \ _ cr -> StrategyActions (ShootAt (fromJust $ tcid cr)) 
        [ DoActionIf 
                (not . crIsAiming) 
                (drawWeapon `DoActionThen` (50 `WaitThen` NoAction))
            `DoActionThen` lostest
            `DoActionWhile` advanceShoot 
            `DoActionThen` 75 
            `DoReplicate` advanceShoot 
            `DoActionThen` DoImpulses [ChangeStrategy WatchAndWait]
        , AimAt { _targetID = fromJust $ tcid cr , _targetSeenAt = V2 0 0 }
        ]
      )
    ] 
    >=> reloadOverrideR
  where
    advanceShoot = DoImpulses [UseItem, MoveForward 3]
    tcid cr = _crID <$> _targetCr (_crIntention cr)
    lostest (w,cr) = maybe False (\cid -> canSee (_crID cr) cid w) (tcid cr)

sentinelFireType
    :: (Int -> Action)
    -> Creature
    -> Reader World Creature
sentinelFireType f = performActionsR
    >=>  watchUpdateStratR
      [ (crHasTargetLOS, \_ _ -> StrategyActions (ShootAt 0) 
            [ drawwp `DoActionThen` f 0 `DoActionThen` DoImpulses [ChangeStrategy WatchAndWait]
            , aiming
            ]
        )
      , (crAwayFromPost, goToPostStrat)
      ] 
    >=> perceptionUpdate [0]
    >=> doStrategyActionsR
    >=> reloadOverrideR
    >=> targetYouWhenCognizantR
    >=> overrideInternalRRR
        (\cr -> (&&) <$> crHasTargetR cr <*> crStratConMatchesR (GetTo (V2 0 0)) cr)
        (pure . (crActionPlan . crStrategy .~ WatchAndWait))
  where
    drawwp = DoActionIfElse NoAction crIsAiming (DoActionThen drawWeapon (WaitThen 50 NoAction))
    aiming = AimAt
        { _targetID = 0
        , _targetSeenAt = V2 0 0 -- hack
        }

sentinelExtraWatchUpdate
    :: [((World, Creature) -> Bool , World -> Creature -> Strategy)]
    -> Creature
    -> Reader World Creature
sentinelExtraWatchUpdate xs = performActionsR
    >=>  watchUpdateStratR
        ( xs ++ [(crAwayFromPost, goToPostStrat)] )
    >=> perceptionUpdate [0]
    >=> doStrategyActionsR
    >=> targetYouWhenCognizantR
    >=> overrideInternalRRR
        (\cr -> (&&) <$> crHasTargetR cr <*> crStratConMatchesR (GetTo (V2 0 0)) cr)
        (pure . (crActionPlan . crStrategy .~ WatchAndWait))

shootAtAdvance :: Int -> [Action]
shootAtAdvance tcid =
    [ DoActionIfElse NoAction crIsAiming (DoActionThen drawWeapon (WaitThen 50 NoAction))
      `DoActionThen`
        lostest `DoActionWhile`
        advanceShoot `DoActionThen`
        75 `DoReplicate` 
        advanceShoot `DoActionThen`
        DoImpulses [ChangeStrategy WatchAndWait]
    , AimAt
        { _targetID = tcid
        , _targetSeenAt = V2 0 0 -- hack
        }
    ]
  where
    lostest (w,cr') = canSee (_crID cr') tcid w 
    advanceShoot = ImpulsesList [[UseItem, MoveForward 3]]

shootAtWhileContinueTime :: Int -> World -> Creature -> Strategy
shootAtWhileContinueTime tcid _ _ = StrategyActions (ShootAt tcid)
    [ DoActionIfElse NoAction crIsAiming (DoActionThen drawWeapon (WaitThen 50 NoAction))
      `DoActionThen`
        lostest `DoActionWhile`
        advanceShoot `DoActionThen`
        75 `DoReplicate` 
        advanceShoot `DoActionThen`
        DoImpulses [ChangeStrategy WatchAndWait]
    , AimAt
        { _targetID = tcid
        , _targetSeenAt = V2 0 0 -- hack
        }
    ]
  where
    lostest (w,cr') = canSee (_crID cr') tcid w 
    advanceShoot = ImpulsesList [[UseItem, MoveForward 3]]
