{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
module Affection.Subsystems.AffectionWindow where

import Affection.Types
import Affection.Util
import Affection.MessageBus

import qualified SDL

-- | Helper function that consumes all Window-related 'SDL.EventPayload's
-- and emits appropriate 'WindowMessage's.
consumeSDLWindowEvents
  :: forall aw us. (Participant aw us, Mesg aw us ~ WindowMessage)
  => aw                               -- ^ The message system participant
  -> [SDL.EventPayload]               -- ^ Incoming events
  -> Affection us [SDL.EventPayload]  -- ^ Leftover SDL events
consumeSDLWindowEvents aw = doConsume
  where
    doConsume
      :: (Mesg aw us ~ WindowMessage)
      => [SDL.EventPayload]
      -> Affection us [SDL.EventPayload]
    doConsume [] = return []
    doConsume (e:es) = do
      ts <- getElapsedTime
      case e of
        SDL.WindowShownEvent (SDL.WindowShownEventData window) -> do
          partEmit aw (MsgWindowShow ts window)
          doConsume es
        SDL.WindowHiddenEvent (SDL.WindowHiddenEventData window) -> do
          partEmit aw (MsgWindowHide ts window)
          doConsume es
        SDL.WindowExposedEvent (SDL.WindowExposedEventData window) -> do
          partEmit aw (MsgWindowExpose ts window)
          doConsume es
        SDL.WindowMovedEvent (SDL.WindowMovedEventData window (SDL.P newPos)) -> do
          partEmit aw (MsgWindowMove ts window newPos)
          doConsume es
        SDL.WindowResizedEvent (SDL.WindowResizedEventData window newSize) -> do
          partEmit aw (MsgWindowResize ts window newSize)
          doConsume es
        SDL.WindowSizeChangedEvent (SDL.WindowSizeChangedEventData window size) -> do
          partEmit aw (MsgWindowSizeChange ts window size)
          doConsume es
        SDL.WindowMinimizedEvent (SDL.WindowMinimizedEventData window) -> do
          partEmit aw (MsgWindowMinimize ts window)
          doConsume es
        SDL.WindowMaximizedEvent (SDL.WindowMaximizedEventData window) -> do
          partEmit aw (MsgWindowMaximize ts window)
          doConsume es
        SDL.WindowRestoredEvent (SDL.WindowRestoredEventData window) -> do
          partEmit aw (MsgWindowRestore ts window)
          doConsume es
        SDL.WindowGainedMouseFocusEvent (SDL.WindowGainedMouseFocusEventData window) -> do
          partEmit aw (MsgWindowGainMouseFocus ts window)
          doConsume es
        SDL.WindowLostMouseFocusEvent (SDL.WindowLostMouseFocusEventData window) -> do
          partEmit aw (MsgWindowLoseMouseFocus ts window)
          doConsume es
        SDL.WindowGainedKeyboardFocusEvent (SDL.WindowGainedKeyboardFocusEventData window) -> do
          partEmit aw (MsgWindowGainKeyboardFocus ts window)
          doConsume es
        SDL.WindowLostKeyboardFocusEvent (SDL.WindowLostKeyboardFocusEventData window) -> do
          partEmit aw (MsgWindowLoseKeyboardFocus ts window)
          doConsume es
        SDL.WindowClosedEvent (SDL.WindowClosedEventData window) -> do
          partEmit aw (MsgWindowClose ts window)
          doConsume es
        _ -> fmap (e :) (doConsume es)