{-# LINE 1 "System/Linux/Input/Event.hsc" #-}
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LINE 2 "System/Linux/Input/Event.hsc" #-}

module System.Linux.Input.Event ( -- * Events
                                  Event(..)
                                , hReadEvent
                                , module System.Linux.Input.Event.Constants
                                ) where

import Data.Word
import Data.Int
import Data.ByteString as BS
import Data.ByteString.Internal
import Data.Time.Clock

import Foreign.Storable
import Foreign.Ptr
import Foreign.ForeignPtr
import Foreign.C.Types

import System.IO

import System.Linux.Input.Event.Constants


{-# LINE 25 "System/Linux/Input/Event.hsc" #-}

-- | An Event
data Event = SyncEvent { evTimestamp :: DiffTime
                       , evSyncCode :: SyncType }
           | KeyEvent { evTimestamp :: DiffTime
                      , evKeyCode :: Key }
           | RelEvent { evTimestamp :: DiffTime
                      , evRelAxis :: RelAxis
                      , evValue :: Int32 }
           | AbsEvent { evTimestamp :: DiffTime
                      , evAbsAxis :: AbsAxis
                      , evValue :: Int32 }
           | MscEvent { evTimestamp :: DiffTime }
           | SwEvent { evTimestamp :: DiffTime }
           | LedEvent { evTimestamp :: DiffTime }
           | SndEvent { evTimestamp :: DiffTime }
           | RepEvent { evTimestamp :: DiffTime }
           | FfEvent { evTimestamp :: DiffTime }
           | FfStatusEvent { evTimestamp :: DiffTime }
             deriving (Show, Eq)

instance Storable Event where
  sizeOf _ = ((16))
{-# LINE 48 "System/Linux/Input/Event.hsc" #-}
  alignment = sizeOf
  peek ptr = do let time = ((\hsc_ptr -> hsc_ptr `plusPtr` 0)) ptr
{-# LINE 50 "System/Linux/Input/Event.hsc" #-}
                sec <- ((\hsc_ptr -> peekByteOff hsc_ptr 0)) time
{-# LINE 51 "System/Linux/Input/Event.hsc" #-}
                usec <- ((\hsc_ptr -> peekByteOff hsc_ptr 4)) time
{-# LINE 52 "System/Linux/Input/Event.hsc" #-}
                _type <- ((\hsc_ptr -> peekByteOff hsc_ptr 8)) ptr :: IO Word16
{-# LINE 53 "System/Linux/Input/Event.hsc" #-}
                code <- ((\hsc_ptr -> peekByteOff hsc_ptr 10)) ptr :: IO Word16
{-# LINE 54 "System/Linux/Input/Event.hsc" #-}
                value <- ((\hsc_ptr -> peekByteOff hsc_ptr 12)) ptr :: IO Int32
{-# LINE 55 "System/Linux/Input/Event.hsc" #-}
                let t = 1000000000000*fromIntegral (sec::Int) + 1000000*fromIntegral (usec::Int)
                return $ case _type of
                     (0)     -> SyncEvent { evTimestamp = picosecondsToDiffTime t
{-# LINE 58 "System/Linux/Input/Event.hsc" #-}
                                                      , evSyncCode = SyncType code }
                     (1)     -> KeyEvent { evTimestamp = picosecondsToDiffTime t
{-# LINE 60 "System/Linux/Input/Event.hsc" #-}
                                                     , evKeyCode = Key code }
                     (2)     -> RelEvent { evTimestamp = picosecondsToDiffTime t
{-# LINE 62 "System/Linux/Input/Event.hsc" #-}
                                                     , evRelAxis = RelAxis code
                                                     , evValue = value }
                     (3)     -> AbsEvent { evTimestamp = picosecondsToDiffTime t
{-# LINE 65 "System/Linux/Input/Event.hsc" #-}
                                                     , evAbsAxis = AbsAxis code
                                                     , evValue = value }
                     (4)     -> MscEvent { evTimestamp = picosecondsToDiffTime t }
{-# LINE 68 "System/Linux/Input/Event.hsc" #-}
                     (5)     -> SwEvent { evTimestamp = picosecondsToDiffTime t }
{-# LINE 69 "System/Linux/Input/Event.hsc" #-}
                     (17)     -> LedEvent { evTimestamp = picosecondsToDiffTime t }
{-# LINE 70 "System/Linux/Input/Event.hsc" #-}
                     (18)     -> SndEvent { evTimestamp = picosecondsToDiffTime t }
{-# LINE 71 "System/Linux/Input/Event.hsc" #-}
                     (20)     -> RepEvent { evTimestamp = picosecondsToDiffTime t }
{-# LINE 72 "System/Linux/Input/Event.hsc" #-}
                     (21)      -> FfEvent { evTimestamp = picosecondsToDiffTime t }
{-# LINE 73 "System/Linux/Input/Event.hsc" #-}
                     (23) -> FfStatusEvent { evTimestamp = picosecondsToDiffTime t }
{-# LINE 74 "System/Linux/Input/Event.hsc" #-}
                     otherwise  -> error $ "unknown event type: " ++ show _type

  poke = undefined

-- | Read an event
hReadEvent :: Handle -> IO (Maybe Event)
hReadEvent h = do
    a <- hGet h $ sizeOf (undefined::Event)
    case a of
         _ | BS.null a  -> return Nothing
         _ | otherwise  -> getEvent a >>= return . Just

getEvent :: ByteString -> IO Event
getEvent bs = do
    let (fptr, off, len) = toForeignPtr bs
    withForeignPtr fptr $ peek . castPtr