content: -- |
  -- Module      :  HGE2D.Physical
  -- Copyright   :  (c) 2016 Martin Buck
  -- License     :  see LICENSE
  --
  -- Containing functions for PhysicalObjects
  
  module HGE2D.Physical where
  
  import HGE2D.Types
  import HGE2D.Datas
  import HGE2D.Classes
  import HGE2D.Instances ()
  
  --------------------------------------------------------------------------------
  
  ---TODO not fully implemented
  ---TODO rename
  ---TODO rename class to HasPhysicalObject
  
  -- | Applies physics to a physical object. E.g. velocity changing position, acceleration changing velocity ...
  applyPhysics :: (IsPhysicalObject a) => Millisecond -> a -> a
  applyPhysics ms x = setPhys newPo x
    where
      newPo = (applyVel . applyAcc . applyRotVel . applyRotAcc . applyDrag . applyRotDrag) (getPhys x) ---TODO more consistent order acc > vel > abs
  
      applyVel po = moveBy (dX, dY) po ---TODO define more general for reuse
        where
          dX = (fromIntegral ms) * (fst $ physicalVel po)
          dY = (fromIntegral ms) * (snd $ physicalVel po)
  
      applyAcc po = po { physicalVel = (vX, vY) } ---TODO see above
        where
          vX = (fst $ physicalVel po) + (fromIntegral ms) * (fst $ physicalAcc po)
          vY = (snd $ physicalVel po) + (fromIntegral ms) * (snd $ physicalAcc po)
  
      applyRotVel po = po { physicalRot = fixedRot } ---TODO see above
        where
          fixedRot | newRot > 2.0 * pi = newRot - 2.0 * pi
                   | newRot < 0        = newRot + 2.0 * pi
                   | otherwise         = newRot
          newRot = (physicalRot po)  + dRot
          dRot = (fromIntegral ms) * (physicalRotSpeed po)
  
      applyRotAcc po = po { physicalRotSpeed = newRotSpeed } ---TODO see above
        where
          newRotSpeed = (physicalRotAcceleration po) + dRotSpeed
          dRotSpeed = (fromIntegral ms) * (physicalRotAcceleration po)
  
      applyDrag = id ---TODO
      applyRotDrag = id ---TODO
  