module Dodge.Creature.YourControl
    ( yourControl
    ) where
import Dodge.Data
import Dodge.Base.Coordinate
import Dodge.Creature.Impulse.Movement
import Dodge.Creature.Test
import Dodge.Update.UsingInput
import Dodge.InputFocus
--import Dodge.Config.KeyConfig
import Geometry

import Control.Lens
import qualified SDL
--import qualified Data.Set as S
import qualified Data.Map.Strict as M
--import qualified Data.IntMap.Strict as IM
--import Data.Maybe
{- | The AI equivalent for your control. -}
yourControl :: Creature -> World -> World
yourControl cr w 
    | inTermFocus w = w
    | otherwise = w
        & creatures . ix (_crID cr) %~ 
            (wasdWithAiming w (_mvSpeed $ _crMvType cr) . mouseActionsCr (_mouseButtons w))
        & updateUsingInput

-- note the order of operation, setting the posture first--this prevents the twist fire bug

{- | Turn key presses into creature movement.  -}
wasdWithAiming 
    :: World
    -> Float    -- ^ Base speed
    -> Creature 
    -> Creature
wasdWithAiming w speed cr
    | isAiming  = addAnyTwist $ set crDir mouseDir $ theMovement cr
    | crIsReloading cr && SDL.ButtonRight `M.member` _mouseButtons w
                = addAnyTwist $ set crDir (mouseDir + anytwist) $ theMovement cr
    | otherwise = theMovement $ theTurn $ removeTwist cr
  where 
    twistamount = 1.6
    removeTwist cr' = cr' 
        & crDir   +~ _crTwist cr' 
        & crTwist .~ 0
    anytwist = case cr ^? crInv . ix (crSel cr) . itUse . useAim . aimStance of
        Just TwoHandTwist -> twistamount * pi
        _ -> 0
    addAnyTwist = crTwist .~ anytwist
    theMovement
        | movDir == V2 0 0 = id
        | otherwise = crMvAbsolute (speed *.* movAbs) . set crMvDir dir
    theTurn cr' = creatureTurnTowardDir (_crMvDir cr') 0.2 cr'
    movDir = wasdDir w
    dir = _cameraRot w + argV movDir
    movAbs   = rotateV (_cameraRot w) $ normalizeV movDir
    isAiming = _posture (_crStance cr) == Aiming
    mouseDir = case cr ^? crInv . ix (crSel cr) . itScope . scopePos of
        Just _ -> argV $ mouseWorldPos w -.- _crPos cr
        _ -> argV (_mousePos w) + _cameraRot w

wasdM :: SDL.Scancode -> Point2
wasdM scancode = case scancode of
    SDL.ScancodeW -> V2   0    1
    SDL.ScancodeS -> V2   0  (-1)
    SDL.ScancodeD -> V2   1    0
    SDL.ScancodeA -> V2 (-1)   0
    _             -> V2   0    0

wasdDir :: World -> Point2
wasdDir = foldr ((+.+) . wasdM) (V2 0 0) . _keys

{- | Set posture according to mouse presses. -}
mouseActionsCr :: M.Map SDL.MouseButton Bool -> Creature -> Creature
mouseActionsCr pkeys cr
    | rbPressed && cr ^?! crInvSel . iselAction == NoInvSelAction
                = cr & crStance . posture .~ Aiming
    | otherwise = cr & crStance . posture .~ AtEase
  where 
    rbPressed = SDL.ButtonRight `M.member` pkeys
