module Dodge.Item.Weapon.Grenade
    where
import Dodge.Data
import Dodge.Data.SoundOrigin
import Dodge.Item.Data
import Dodge.Base
import Dodge.Zone
import Dodge.Picture.Layer
import Dodge.SoundLogic
import Dodge.SoundLogic.LoadSound
import Dodge.Item.Attachment.Data
import Dodge.Item.Draw
import Dodge.Default.Shell
--import Dodge.Default
import Picture
import Geometry
import ShapePicture
import Shape

import Control.Lens
import qualified Data.IntMap.Strict as IM
--import System.Random

moveGrenade 
    :: Int      -- ^ Timer
    -> Float    -- ^ Direction
    -> Int      -- ^ Projectile id
    -> World 
    -> World
moveGrenade 0 _ pID w = over projectiles (IM.delete pID) 
    $ explosion (_pjPos (_projectiles w IM.! pID)) 
    w
  where
    pj = _projectiles w IM.! pID
    explosion = _pjPayload pj
moveGrenade time dir pID w = case hitWl of
    Just (p,_) -> soundStart (Tap 0) p tapQuietS Nothing updatedWorld
    _      -> updatedWorld
  where 
    updatedWorld = updateV $ set (projectiles . ix pID . pjPos) finalPos
                            $ set (projectiles .ix pID. pjDraw) 
                    (\ _ -> onLayer PtLayer $ uncurryV translate newPos 
                                     $ rotate dir $ _spPicture $ grenadePic time)
                        $ set (projectiles .ix pID.pjUpdate) (\_ -> moveGrenade (time-1) dir pID) w
    pj     = _projectiles w IM.! pID
    oldPos = _pjPos pj
    newPos = _pjVel pj +.+ oldPos
    hitWl  = collideCircWalls'' oldPos newPos 4 $ wallsNearPoint newPos w
    finalPos = maybe newPos fst hitWl
    setV v = set (projectiles .ix pID.pjVel) v
    updateV = maybe id (setV . snd) hitWl


grenadePic :: Int -> SPic
grenadePic x = (,) emptySH $ pictures 
    [ color (dark $ dark green) $ circleSolid 5
    , color green $ arc (degToRad $ (179 * fromIntegral x / 50) - 180 ) 
                        (degToRad $ 180 - (179 * fromIntegral x / 50) ) 
                        5
    , translate (-2) 2 $ rotate (pi*0.5) 
        $ scale 0.05 0.05 $ color green $ text $ show $ 1 + quot x 20 
    ]

throwGrenade 
    :: (Point2 -> World -> World)   -- ^ Payload
    -> Creature
    -> World 
    -> World
throwGrenade explosion cr w = setWp $ removePict $ over projectiles addG w
  where 
    n = _crID cr
    addG = IM.insert i $ defaultShell 
        { _pjPos = p
        , _pjStartPos = p
        , _pjVel = v
        , _pjDraw = \_ -> onLayer PtLayer $ uncurryV translate p $ _spPicture $ grenadePic 0
        , _pjID = i
        , _pjUpdate = \_ -> moveGrenade fuseTime dir i
        , _pjPayload = explosion
        }
    j = _crInvSel cr
    removePict = set (creatures . ix n . crInv . ix j . itEquipPict) $ \ _ _ -> (,) emptySH blank
    i = newProjectileKey w
    --(_, g) = randomR (-grenadeAccA,grenadeAccA::Float) (_randGen w)
    --(_, _) = randomR (1 - 2*grenadeAccL,1+grenadeAccL::Float) g
    v' = 1 / (fromIntegral fuseTime * _cameraZoom w) *.* rotateV (_cameraRot w) ( _mousePos w)
    v | magV v' > 6 = 6 *.* normalizeV v'
      | otherwise   = v'
    p' = _crPos cr +.+ rotateV (_crDir cr) (V2 (_crRad cr) 0)
    p | circOnSomeWall p' 4 w = _crPos cr +.+ rotateV (_crDir cr) (V2 (_crRad cr-4) 0)
      | otherwise             = p'
    dir = argV v 
    setWp :: World -> World
    setWp w' = w' & creatures . ix n . crInv . ix j . itEffect .~ throwArmReset 20
    fuseTime = _itFuseTime $ _itAttachment $ _crInv cr IM.! j

throwArmReset :: Int -> ItEffect
throwArmReset x = ItInvEffect {_itInvEffect = f ,_itEffectCounter = x }
  where 
    f _ cr i = creatures . ix (_crID cr) . crInv %~ IM.adjust counterDown i
    counterDown it 
        | _itEffectCounter (_itEffect it) == 0 = it 
            & itHammer .~ HammerUp 
            & itEquipPict .~ pictureWeaponOnAim (grenadePic 50)
        | otherwise = it & itEffect . itEffectCounter -~ 1
                                           
--(grenadeAccL, grenadeAccA) = (0.1, 0.1)
