content: module Player.Gun.All.Revolver.Util
      ( RevolverShotType(..)
      , loadRevolverSprite
      , calculatePlayerAimBody
      ) where
  
  import Control.Monad.IO.Class (MonadIO)
  import Data.Maybe             (fromMaybe)
  import qualified Data.Map as M
  import qualified Data.Vector as V
  
  import Configs.All.PlayerGun.Revolver
  import FileCache
  import Player.AimBody
  import Player.Gun.FireDrawAngle
  import Player.Gun.FireDrawState.LegsState
  import Util
  import Window.Graphics
  
  data RevolverShotType
      = RevolverNormalShotType
      | RevolverContinuousShotType
  
  loadRevolverSprite :: (FileCache m, GraphicsRead m, MonadIO m) => FileName -> m Sprite
  loadRevolverSprite fileName = loadPackSprite $ PackResourceFilePath "data/player/player-guns.pack" fileName
  
  calculatePlayerAimBody :: RevolverConfig -> CalculatePlayerAimBody
  calculatePlayerAimBody cfg fireDrawAngle playerPos angle playerDir legsState = PlayerAimBody
      { _headAngle       = headAngle
      , _neckPos         = neckPos
      , _torsoAngle      = torsoAngle
      , _leadShoulderPos = leadShoulderPos
      , _rearShoulderPos = rearShoulderPos
      , _hipsPos         = hipsPos
      , _leadArmAngle    = leadArmAngle
      , _rearArmAngle    = rearArmAngle
      , _aimDir          = calculateAimAngleDir angle
      }
      where
          torsoNeckOffset        = fromMaybe zeroPos2 (fireDrawAngle `M.lookup` _torsoNeckOffsets cfg)
          rearShoulderHipsOffset = fromMaybe zeroPos2 (fireDrawAngle `M.lookup` _rearShoulderHipsOffsets cfg)
          leadShoulderHipsOffset = fromMaybe zeroPos2 (fireDrawAngle `M.lookup` _leadShoulderHipsOffsets cfg)
  
          legsHipsOffset = fromMaybe zeroPos2 $ do
              offsets <- _status (legsState :: LegsState) `M.lookup` _legsHipsOffsets cfg
              let
                  legsSpr = _sprite (legsState :: LegsState)
                  idx     = _int (_frameIndex legsSpr) `mod` V.length offsets
              offsets V.!? idx
  
          angleDelta   = gunFireDrawAngleDelta angle playerDir fireDrawAngle
          headAngle    = angleDelta * _headAngleMultiplier cfg
          torsoAngle   = angleDelta * _torsoAngleMultiplier cfg
          leadArmAngle = angleDelta * _leadArmAngleMultiplier cfg
          rearArmAngle = angleDelta * _rearArmAngleMultiplier cfg
  
          hipsPos         = playerPos `vecAdd` vecFlip legsHipsOffset playerDir
          neckOffset      = vecFlipRotate torsoNeckOffset playerDir torsoAngle
          neckPos         = hipsPos `vecAdd` neckOffset
          rearShoulderPos = hipsPos `vecAdd` vecFlipRotate rearShoulderHipsOffset playerDir torsoAngle
          leadShoulderPos = hipsPos `vecAdd` vecFlipRotate leadShoulderHipsOffset playerDir torsoAngle
  