{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE ViewPatterns #-}

module DearImGui.Raw.DragDrop
  ( Payload(..)
  , beginSource
  , setPayload
  , endSource
  , beginTarget
  , acceptPayload
  , endTarget
  , getPayload
  )
  where

-- base
import Control.Monad.IO.Class
  ( MonadIO, liftIO )
import Foreign
  ( Ptr, castPtr )
import Foreign.C

-- dear-imgui
import DearImGui.Raw.Context
  ( imguiContext )
import DearImGui.Enums
import DearImGui.Structs

-- inline-c
import qualified Language.C.Inline as C

-- inline-c-cpp
import qualified Language.C.Inline.Cpp as Cpp

C.context (Cpp.cppCtx <> C.bsCtx <> imguiContext)
C.include "imgui.h"
Cpp.using "namespace ImGui"

-- | Font configuration data handle
--
-- Wraps @ImGuiPayload*@.
newtype Payload = Payload (Ptr ImGuiPayload)


beginSource :: MonadIO m => ImGuiDragDropFlags -> m Bool
beginSource :: forall (m :: * -> *). MonadIO m => ImGuiDragDropFlags -> m Bool
beginSource ImGuiDragDropFlags
flags = IO Bool -> m Bool
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO do
  (CBool
0 CBool -> CBool -> Bool
forall a. Eq a => a -> a -> Bool
/=) (CBool -> Bool) -> IO CBool -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [C.exp| bool { BeginDragDropSource( $(ImGuiDragDropFlags flags) ) } |]

setPayload :: MonadIO m => CString -> Ptr a -> CSize -> ImGuiCond -> m Bool
setPayload :: forall (m :: * -> *) a.
MonadIO m =>
CString -> Ptr a -> CSize -> ImGuiCond -> m Bool
setPayload CString
typePtr Ptr a
dataPtr CSize
sz ImGuiCond
cond = IO Bool -> m Bool
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO do
  (CBool
0 CBool -> CBool -> Bool
forall a. Eq a => a -> a -> Bool
/=) (CBool -> Bool) -> IO CBool -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [C.exp| bool { SetDragDropPayload( $(char* typePtr), $(void* dataPtr'), $(size_t sz), $(ImGuiCond cond) ) } |]
  where
    dataPtr' :: Ptr b
dataPtr' = Ptr a -> Ptr b
forall a b. Ptr a -> Ptr b
castPtr Ptr a
dataPtr

endSource :: MonadIO m => m ()
endSource :: forall (m :: * -> *). MonadIO m => m ()
endSource = IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO do
  IO ()
[C.block| void { EndDragDropSource( ); } |]

beginTarget :: MonadIO m => m ()
beginTarget :: forall (m :: * -> *). MonadIO m => m ()
beginTarget = IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO do
  IO ()
[C.block| void { BeginDragDropTarget(); } |]

acceptPayload :: MonadIO m => CString -> ImGuiDragDropFlags -> m Payload
acceptPayload :: forall (m :: * -> *).
MonadIO m =>
CString -> ImGuiDragDropFlags -> m Payload
acceptPayload CString
typePtr ImGuiDragDropFlags
flags = IO Payload -> m Payload
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO do
  Ptr ImGuiPayload -> Payload
Payload (Ptr ImGuiPayload -> Payload)
-> IO (Ptr ImGuiPayload) -> IO Payload
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [C.exp| const ImGuiPayload* { AcceptDragDropPayload( $(char* typePtr), $(ImGuiDragDropFlags flags) ) } |]

endTarget :: MonadIO m => m ()
endTarget :: forall (m :: * -> *). MonadIO m => m ()
endTarget = IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO do
  IO ()
[C.block| void { EndDragDropTarget(); } |]

getPayload :: MonadIO m => m Payload
getPayload :: forall (m :: * -> *). MonadIO m => m Payload
getPayload = IO Payload -> m Payload
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO do
  Ptr ImGuiPayload -> Payload
Payload (Ptr ImGuiPayload -> Payload)
-> IO (Ptr ImGuiPayload) -> IO Payload
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO (Ptr ImGuiPayload)
[C.exp| const ImGuiPayload* { GetDragDropPayload() } |]