module Termbox.Internal.Event
  ( Event (..),
    poll,
  )
where

import Data.Int (Int32)
import GHC.Generics (Generic)
import qualified Termbox.Bindings.Hs
import Termbox.Internal.Key (Key (KeyChar), parseKey)
import Termbox.Internal.Mouse (Mouse (..), MouseButton (..))
import Termbox.Internal.Pos (Pos (..))
import Termbox.Internal.Size (Size (..))
import Prelude hiding (mod)

-- | An input event.
data Event e
  = -- | Key event
    EventKey !Key
  | -- | Resize event
    EventResize !Size
  | -- | Mouse event
    EventMouse !Mouse
  | -- | User event
    EventUser !e
  deriving stock (Event e -> Event e -> Bool
(Event e -> Event e -> Bool)
-> (Event e -> Event e -> Bool) -> Eq (Event e)
forall e. Eq e => Event e -> Event e -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall e. Eq e => Event e -> Event e -> Bool
== :: Event e -> Event e -> Bool
$c/= :: forall e. Eq e => Event e -> Event e -> Bool
/= :: Event e -> Event e -> Bool
Eq, (forall x. Event e -> Rep (Event e) x)
-> (forall x. Rep (Event e) x -> Event e) -> Generic (Event e)
forall x. Rep (Event e) x -> Event e
forall x. Event e -> Rep (Event e) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall e x. Rep (Event e) x -> Event e
forall e x. Event e -> Rep (Event e) x
$cfrom :: forall e x. Event e -> Rep (Event e) x
from :: forall x. Event e -> Rep (Event e) x
$cto :: forall e x. Rep (Event e) x -> Event e
to :: forall x. Rep (Event e) x -> Event e
Generic, Int -> Event e -> ShowS
[Event e] -> ShowS
Event e -> String
(Int -> Event e -> ShowS)
-> (Event e -> String) -> ([Event e] -> ShowS) -> Show (Event e)
forall e. Show e => Int -> Event e -> ShowS
forall e. Show e => [Event e] -> ShowS
forall e. Show e => Event e -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall e. Show e => Int -> Event e -> ShowS
showsPrec :: Int -> Event e -> ShowS
$cshow :: forall e. Show e => Event e -> String
show :: Event e -> String
$cshowList :: forall e. Show e => [Event e] -> ShowS
showList :: [Event e] -> ShowS
Show)

-- | Poll for an event.
poll :: IO (Event e)
poll :: forall e. IO (Event e)
poll =
  IO (Either () (Event e))
forall e. IO (Either () (Event e))
poll_ IO (Either () (Event e))
-> (Either () (Event e) -> IO (Event e)) -> IO (Event e)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
    Left () -> IO (Event e)
forall e. IO (Event e)
poll
    Right Event e
event -> Event e -> IO (Event e)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Event e
event

poll_ :: IO (Either () (Event e))
poll_ :: forall e. IO (Either () (Event e))
poll_ = do
  Either () Tb_event
result <- IO (Either () Tb_event)
Termbox.Bindings.Hs.tb_poll_event
  Either () (Event e) -> IO (Either () (Event e))
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Tb_event -> Event e
forall e. Tb_event -> Event e
parseEvent (Tb_event -> Event e) -> Either () Tb_event -> Either () (Event e)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Either () Tb_event
result)

-- Parse an Event from a TbEvent.
parseEvent :: Termbox.Bindings.Hs.Tb_event -> Event e
parseEvent :: forall e. Tb_event -> Event e
parseEvent
  Termbox.Bindings.Hs.Tb_event
    { Tb_event_type
type_ :: Tb_event_type
$sel:type_:Tb_event :: Tb_event -> Tb_event_type
Termbox.Bindings.Hs.type_,
      $sel:mod:Tb_event :: Tb_event -> Maybe Tb_event_mod
Termbox.Bindings.Hs.mod = Maybe Tb_event_mod
_,
      Tb_key
key :: Tb_key
$sel:key:Tb_event :: Tb_event -> Tb_key
Termbox.Bindings.Hs.key,
      Char
ch :: Char
$sel:ch:Tb_event :: Tb_event -> Char
Termbox.Bindings.Hs.ch,
      Int32
w :: Int32
$sel:w:Tb_event :: Tb_event -> Int32
Termbox.Bindings.Hs.w,
      Int32
h :: Int32
$sel:h:Tb_event :: Tb_event -> Int32
Termbox.Bindings.Hs.h,
      Int32
x :: Int32
$sel:x:Tb_event :: Tb_event -> Int32
Termbox.Bindings.Hs.x,
      Int32
y :: Int32
$sel:y:Tb_event :: Tb_event -> Int32
Termbox.Bindings.Hs.y
    } =
    case Tb_event_type
type_ of
      Tb_event_type
Termbox.Bindings.Hs.TB_EVENT_KEY -> Key -> Event e
forall e. Key -> Event e
EventKey (if Char
ch Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'\0' then Tb_key -> Key
parseKey Tb_key
key else Char -> Key
KeyChar Char
ch)
      Tb_event_type
Termbox.Bindings.Hs.TB_EVENT_RESIZE ->
        Size -> Event e
forall e. Size -> Event e
EventResize
          Size
            { $sel:width:Size :: Int
width = forall a b. (Integral a, Num b) => a -> b
fromIntegral @Int32 @Int Int32
w,
              $sel:height:Size :: Int
height = forall a b. (Integral a, Num b) => a -> b
fromIntegral @Int32 @Int Int32
h
            }
      Tb_event_type
Termbox.Bindings.Hs.TB_EVENT_MOUSE ->
        Mouse -> Event e
forall e. Mouse -> Event e
EventMouse
          Mouse
            { $sel:button:Mouse :: MouseButton
button = Tb_key -> MouseButton
MouseButton Tb_key
key,
              $sel:pos:Mouse :: Pos
pos =
                Pos
                  { $sel:row:Pos :: Int
row = forall a b. (Integral a, Num b) => a -> b
fromIntegral @Int32 @Int Int32
y,
                    $sel:col:Pos :: Int
col = forall a b. (Integral a, Num b) => a -> b
fromIntegral @Int32 @Int Int32
x
                  }
            }