{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ViewPatterns #-}
module Hadoom.Camera (Camera(..), camera, cameraQuat, cameraForward) where

import Control.Applicative
import Control.Category
import Control.Lens (alaf)
import Data.Foldable
import Data.Monoid
import Data.Profunctor
import FRP.Netwire.Move (integral)
import Linear
import Prelude hiding ((.), id)
import qualified SDL

import Control.Wire

data Camera a =
  Camera {cameraPitch :: a
         ,cameraYaw :: a}

-- | A camera in its own model space.
camera :: (Foldable f, Fractional a, HasTime t s, Monad m) => Wire s e m (f SDL.Event) (Camera a)
camera =
  dimap (alaf Sum foldMap (mouseMotion . SDL.eventPayload))
        (\(V2 (negate -> cameraYaw) (negate -> cameraPitch)) ->
           Camera {..})
        (integral 0)
  where mouseMotion ev =
          case ev of
            SDL.MouseMotionEvent{..} ->
              sensitivity *^
              (fromIntegral <$> mouseMotionEventRelMotion)
            _ -> 0
        sensitivity = 0.1

-- | Interpret a 'Camera' for its rotation quaternion.
cameraQuat :: (Epsilon a,RealFloat a) => Camera a -> Quaternion a
cameraQuat Camera{..} =
  axisAngle (V3 0 1 0) cameraYaw *
  axisAngle (V3 1 0 0) cameraPitch

-- | Determine the forward vector in world-space for a given 'Camera'.
cameraForward :: (Epsilon a, RealFloat a) => Camera a -> V3 a
cameraForward Camera{..} =
  fromQuaternion (axisAngle (V3 0 1 0) cameraYaw) !*
  V3 0 0 (-1)
