{-# LANGUAGE DeriveGeneric         #-}
{-# LANGUAGE DuplicateRecordFields #-}
-- |
-- Module: Network.Greskell.WebSocket.Request
-- Description: Request to Gremlin Server
-- Maintainer: Toshio Ito <debug.ito@gmail.com>
--
--
module Network.Greskell.WebSocket.Request
    ( -- * RequestMessage
      RequestMessage (..)
    , Operation (..)
    , toRequestMessage
    , makeRequestMessage
    ) where

import           Control.Applicative                       ((<$>), (<*>))
import           Data.Aeson                                (FromJSON (..), Object, ToJSON (..))
import           Data.Text                                 (Text)
import           Data.UUID                                 (UUID)
import           Data.UUID.V4                              (nextRandom)
import           GHC.Generics                              (Generic)

import qualified Network.Greskell.WebSocket.Request.Aeson  as GAeson
import           Network.Greskell.WebSocket.Request.Common (Operation (..))


-- | RequestMessage to a Gremlin Server. See
-- <http://tinkerpop.apache.org/docs/current/dev/provider/>.
data RequestMessage
  = RequestMessage
      { RequestMessage -> UUID
requestId :: !UUID
      , RequestMessage -> Text
op        :: !Text
      , RequestMessage -> Text
processor :: !Text
      , RequestMessage -> Object
args      :: !Object
      }
  deriving (RequestMessage -> RequestMessage -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: RequestMessage -> RequestMessage -> Bool
$c/= :: RequestMessage -> RequestMessage -> Bool
== :: RequestMessage -> RequestMessage -> Bool
$c== :: RequestMessage -> RequestMessage -> Bool
Eq, forall x. Rep RequestMessage x -> RequestMessage
forall x. RequestMessage -> Rep RequestMessage x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep RequestMessage x -> RequestMessage
$cfrom :: forall x. RequestMessage -> Rep RequestMessage x
Generic, Int -> RequestMessage -> ShowS
[RequestMessage] -> ShowS
RequestMessage -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [RequestMessage] -> ShowS
$cshowList :: [RequestMessage] -> ShowS
show :: RequestMessage -> String
$cshow :: RequestMessage -> String
showsPrec :: Int -> RequestMessage -> ShowS
$cshowsPrec :: Int -> RequestMessage -> ShowS
Show)

instance ToJSON RequestMessage where
  toJSON :: RequestMessage -> Value
toJSON = forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
GAeson.genericToJSON Options
GAeson.opt
  toEncoding :: RequestMessage -> Encoding
toEncoding = forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
GAeson.genericToEncoding Options
GAeson.opt

instance FromJSON RequestMessage where
  parseJSON :: Value -> Parser RequestMessage
parseJSON = forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
GAeson.genericParseJSON Options
GAeson.opt

-- | Convert an 'Operation' object to 'RequestMessage'.
toRequestMessage :: Operation o => UUID -> o -> RequestMessage
toRequestMessage :: forall o. Operation o => UUID -> o -> RequestMessage
toRequestMessage UUID
rid o
o =
  RequestMessage { $sel:requestId:RequestMessage :: UUID
requestId = UUID
rid,
                   $sel:op:RequestMessage :: Text
op = forall o. Operation o => o -> Text
opName o
o,
                   $sel:processor:RequestMessage :: Text
processor = forall o. Operation o => o -> Text
opProcessor o
o,
                   $sel:args:RequestMessage :: Object
args = forall o. Operation o => o -> Object
opArgs o
o
                 }

-- | Create a 'RequestMessage' from an 'Operation' object. The
-- 'requestId' is generated by the random number generator of the
-- system.
makeRequestMessage :: Operation o => o -> IO RequestMessage
makeRequestMessage :: forall o. Operation o => o -> IO RequestMessage
makeRequestMessage o
o = forall o. Operation o => UUID -> o -> RequestMessage
toRequestMessage forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO UUID
nextRandom forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a. Applicative f => a -> f a
pure o
o