module TD.Data.CallState
  (CallState(..)) where

import qualified Data.Aeson as A
import qualified Data.Aeson.Types as AT
import qualified TD.Lib.Internal as I
import qualified TD.Data.CallProtocol as CallProtocol
import qualified TD.Data.CallServer as CallServer
import qualified Data.Text as T
import qualified Data.ByteString as BS
import qualified TD.Data.CallDiscardReason as CallDiscardReason
import qualified TD.Data.Error as Error

-- | Describes the current call state
data CallState
  = CallStatePending -- ^ The call is pending, waiting to be accepted by a user
    { CallState -> Maybe Bool
is_created  :: Maybe Bool -- ^ True, if the call has already been created by the server
    , CallState -> Maybe Bool
is_received :: Maybe Bool -- ^ True, if the call has already been received by the other party
    }
  | CallStateExchangingKeys -- ^ The call has been answered and encryption keys are being exchanged
  | CallStateReady -- ^ The call is ready to use
    { CallState -> Maybe CallProtocol
protocol          :: Maybe CallProtocol.CallProtocol -- ^ Call protocols supported by the other call participant
    , CallState -> Maybe [CallServer]
servers           :: Maybe [CallServer.CallServer]   -- ^ List of available call servers
    , CallState -> Maybe Text
config            :: Maybe T.Text                    -- ^ A JSON-encoded call config
    , CallState -> Maybe ByteString
encryption_key    :: Maybe BS.ByteString             -- ^ Call encryption key
    , CallState -> Maybe [Text]
emojis            :: Maybe [T.Text]                  -- ^ Encryption key fingerprint represented as 4 emoji
    , CallState -> Maybe Bool
allow_p2p         :: Maybe Bool                      -- ^ True, if peer-to-peer connection is allowed by users privacy settings
    , CallState -> Maybe Text
custom_parameters :: Maybe T.Text                    -- ^ Custom JSON-encoded call parameters to be passed to tgcalls
    }
  | CallStateHangingUp -- ^ The call is hanging up after discardCall has been called
  | CallStateDiscarded -- ^ The call has ended successfully
    { CallState -> Maybe CallDiscardReason
reason                 :: Maybe CallDiscardReason.CallDiscardReason -- ^ The reason why the call has ended
    , CallState -> Maybe Bool
need_rating            :: Maybe Bool                                -- ^ True, if the call rating must be sent to the server
    , CallState -> Maybe Bool
need_debug_information :: Maybe Bool                                -- ^ True, if the call debug information must be sent to the server
    , CallState -> Maybe Bool
need_log               :: Maybe Bool                                -- ^ True, if the call log must be sent to the server
    }
  | CallStateError -- ^ The call has ended with an error
    { CallState -> Maybe Error
_error :: Maybe Error.Error -- ^ Error. An error with the code 4005000 will be returned if an outgoing call is missed because of an expired timeout
    }
  deriving (CallState -> CallState -> Bool
(CallState -> CallState -> Bool)
-> (CallState -> CallState -> Bool) -> Eq CallState
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CallState -> CallState -> Bool
== :: CallState -> CallState -> Bool
$c/= :: CallState -> CallState -> Bool
/= :: CallState -> CallState -> Bool
Eq, Int -> CallState -> ShowS
[CallState] -> ShowS
CallState -> String
(Int -> CallState -> ShowS)
-> (CallState -> String)
-> ([CallState] -> ShowS)
-> Show CallState
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CallState -> ShowS
showsPrec :: Int -> CallState -> ShowS
$cshow :: CallState -> String
show :: CallState -> String
$cshowList :: [CallState] -> ShowS
showList :: [CallState] -> ShowS
Show)

instance I.ShortShow CallState where
  shortShow :: CallState -> String
shortShow CallStatePending
    { is_created :: CallState -> Maybe Bool
is_created  = Maybe Bool
is_created_
    , is_received :: CallState -> Maybe Bool
is_received = Maybe Bool
is_received_
    }
      = String
"CallStatePending"
        String -> ShowS
forall a. [a] -> [a] -> [a]
++ [String] -> String
I.cc
        [ String
"is_created"  String -> Maybe Bool -> String
forall a. ShortShow a => String -> Maybe a -> String
`I.p` Maybe Bool
is_created_
        , String
"is_received" String -> Maybe Bool -> String
forall a. ShortShow a => String -> Maybe a -> String
`I.p` Maybe Bool
is_received_
        ]
  shortShow CallState
CallStateExchangingKeys
      = String
"CallStateExchangingKeys"
  shortShow CallStateReady
    { protocol :: CallState -> Maybe CallProtocol
protocol          = Maybe CallProtocol
protocol_
    , servers :: CallState -> Maybe [CallServer]
servers           = Maybe [CallServer]
servers_
    , config :: CallState -> Maybe Text
config            = Maybe Text
config_
    , encryption_key :: CallState -> Maybe ByteString
encryption_key    = Maybe ByteString
encryption_key_
    , emojis :: CallState -> Maybe [Text]
emojis            = Maybe [Text]
emojis_
    , allow_p2p :: CallState -> Maybe Bool
allow_p2p         = Maybe Bool
allow_p2p_
    , custom_parameters :: CallState -> Maybe Text
custom_parameters = Maybe Text
custom_parameters_
    }
      = String
"CallStateReady"
        String -> ShowS
forall a. [a] -> [a] -> [a]
++ [String] -> String
I.cc
        [ String
"protocol"          String -> Maybe CallProtocol -> String
forall a. ShortShow a => String -> Maybe a -> String
`I.p` Maybe CallProtocol
protocol_
        , String
"servers"           String -> Maybe [CallServer] -> String
forall a. ShortShow a => String -> Maybe a -> String
`I.p` Maybe [CallServer]
servers_
        , String
"config"            String -> Maybe Text -> String
forall a. ShortShow a => String -> Maybe a -> String
`I.p` Maybe Text
config_
        , String
"encryption_key"    String -> Maybe ByteString -> String
forall a. ShortShow a => String -> Maybe a -> String
`I.p` Maybe ByteString
encryption_key_
        , String
"emojis"            String -> Maybe [Text] -> String
forall a. ShortShow a => String -> Maybe a -> String
`I.p` Maybe [Text]
emojis_
        , String
"allow_p2p"         String -> Maybe Bool -> String
forall a. ShortShow a => String -> Maybe a -> String
`I.p` Maybe Bool
allow_p2p_
        , String
"custom_parameters" String -> Maybe Text -> String
forall a. ShortShow a => String -> Maybe a -> String
`I.p` Maybe Text
custom_parameters_
        ]
  shortShow CallState
CallStateHangingUp
      = String
"CallStateHangingUp"
  shortShow CallStateDiscarded
    { reason :: CallState -> Maybe CallDiscardReason
reason                 = Maybe CallDiscardReason
reason_
    , need_rating :: CallState -> Maybe Bool
need_rating            = Maybe Bool
need_rating_
    , need_debug_information :: CallState -> Maybe Bool
need_debug_information = Maybe Bool
need_debug_information_
    , need_log :: CallState -> Maybe Bool
need_log               = Maybe Bool
need_log_
    }
      = String
"CallStateDiscarded"
        String -> ShowS
forall a. [a] -> [a] -> [a]
++ [String] -> String
I.cc
        [ String
"reason"                 String -> Maybe CallDiscardReason -> String
forall a. ShortShow a => String -> Maybe a -> String
`I.p` Maybe CallDiscardReason
reason_
        , String
"need_rating"            String -> Maybe Bool -> String
forall a. ShortShow a => String -> Maybe a -> String
`I.p` Maybe Bool
need_rating_
        , String
"need_debug_information" String -> Maybe Bool -> String
forall a. ShortShow a => String -> Maybe a -> String
`I.p` Maybe Bool
need_debug_information_
        , String
"need_log"               String -> Maybe Bool -> String
forall a. ShortShow a => String -> Maybe a -> String
`I.p` Maybe Bool
need_log_
        ]
  shortShow CallStateError
    { _error :: CallState -> Maybe Error
_error = Maybe Error
_error_
    }
      = String
"CallStateError"
        String -> ShowS
forall a. [a] -> [a] -> [a]
++ [String] -> String
I.cc
        [ String
"_error" String -> Maybe Error -> String
forall a. ShortShow a => String -> Maybe a -> String
`I.p` Maybe Error
_error_
        ]

instance AT.FromJSON CallState where
  parseJSON :: Value -> Parser CallState
parseJSON v :: Value
v@(AT.Object Object
obj) = do
    String
t <- Object
obj Object -> Key -> Parser String
forall a. FromJSON a => Object -> Key -> Parser a
A..: Key
"@type" :: AT.Parser String

    case String
t of
      String
"callStatePending"        -> Value -> Parser CallState
parseCallStatePending Value
v
      String
"callStateExchangingKeys" -> CallState -> Parser CallState
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure CallState
CallStateExchangingKeys
      String
"callStateReady"          -> Value -> Parser CallState
parseCallStateReady Value
v
      String
"callStateHangingUp"      -> CallState -> Parser CallState
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure CallState
CallStateHangingUp
      String
"callStateDiscarded"      -> Value -> Parser CallState
parseCallStateDiscarded Value
v
      String
"callStateError"          -> Value -> Parser CallState
parseCallStateError Value
v
      String
_                         -> Parser CallState
forall a. Monoid a => a
mempty
    
    where
      parseCallStatePending :: A.Value -> AT.Parser CallState
      parseCallStatePending :: Value -> Parser CallState
parseCallStatePending = String -> (Object -> Parser CallState) -> Value -> Parser CallState
forall a. String -> (Object -> Parser a) -> Value -> Parser a
A.withObject String
"CallStatePending" ((Object -> Parser CallState) -> Value -> Parser CallState)
-> (Object -> Parser CallState) -> Value -> Parser CallState
forall a b. (a -> b) -> a -> b
$ \Object
o -> do
        Maybe Bool
is_created_  <- Object
o Object -> Key -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
A..:?  Key
"is_created"
        Maybe Bool
is_received_ <- Object
o Object -> Key -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
A..:?  Key
"is_received"
        CallState -> Parser CallState
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CallState -> Parser CallState) -> CallState -> Parser CallState
forall a b. (a -> b) -> a -> b
$ CallStatePending
          { is_created :: Maybe Bool
is_created  = Maybe Bool
is_created_
          , is_received :: Maybe Bool
is_received = Maybe Bool
is_received_
          }
      parseCallStateReady :: A.Value -> AT.Parser CallState
      parseCallStateReady :: Value -> Parser CallState
parseCallStateReady = String -> (Object -> Parser CallState) -> Value -> Parser CallState
forall a. String -> (Object -> Parser a) -> Value -> Parser a
A.withObject String
"CallStateReady" ((Object -> Parser CallState) -> Value -> Parser CallState)
-> (Object -> Parser CallState) -> Value -> Parser CallState
forall a b. (a -> b) -> a -> b
$ \Object
o -> do
        Maybe CallProtocol
protocol_          <- Object
o Object -> Key -> Parser (Maybe CallProtocol)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
A..:?                       Key
"protocol"
        Maybe [CallServer]
servers_           <- Object
o Object -> Key -> Parser (Maybe [CallServer])
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
A..:?                       Key
"servers"
        Maybe Text
config_            <- Object
o Object -> Key -> Parser (Maybe Text)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
A..:?                       Key
"config"
        Maybe ByteString
encryption_key_    <- (String -> ByteString) -> Maybe String -> Maybe ByteString
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap String -> ByteString
I.readBytes (Maybe String -> Maybe ByteString)
-> Parser (Maybe String) -> Parser (Maybe ByteString)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Key -> Parser (Maybe String)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
A..:?  Key
"encryption_key"
        Maybe [Text]
emojis_            <- Object
o Object -> Key -> Parser (Maybe [Text])
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
A..:?                       Key
"emojis"
        Maybe Bool
allow_p2p_         <- Object
o Object -> Key -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
A..:?                       Key
"allow_p2p"
        Maybe Text
custom_parameters_ <- Object
o Object -> Key -> Parser (Maybe Text)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
A..:?                       Key
"custom_parameters"
        CallState -> Parser CallState
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CallState -> Parser CallState) -> CallState -> Parser CallState
forall a b. (a -> b) -> a -> b
$ CallStateReady
          { protocol :: Maybe CallProtocol
protocol          = Maybe CallProtocol
protocol_
          , servers :: Maybe [CallServer]
servers           = Maybe [CallServer]
servers_
          , config :: Maybe Text
config            = Maybe Text
config_
          , encryption_key :: Maybe ByteString
encryption_key    = Maybe ByteString
encryption_key_
          , emojis :: Maybe [Text]
emojis            = Maybe [Text]
emojis_
          , allow_p2p :: Maybe Bool
allow_p2p         = Maybe Bool
allow_p2p_
          , custom_parameters :: Maybe Text
custom_parameters = Maybe Text
custom_parameters_
          }
      parseCallStateDiscarded :: A.Value -> AT.Parser CallState
      parseCallStateDiscarded :: Value -> Parser CallState
parseCallStateDiscarded = String -> (Object -> Parser CallState) -> Value -> Parser CallState
forall a. String -> (Object -> Parser a) -> Value -> Parser a
A.withObject String
"CallStateDiscarded" ((Object -> Parser CallState) -> Value -> Parser CallState)
-> (Object -> Parser CallState) -> Value -> Parser CallState
forall a b. (a -> b) -> a -> b
$ \Object
o -> do
        Maybe CallDiscardReason
reason_                 <- Object
o Object -> Key -> Parser (Maybe CallDiscardReason)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
A..:?  Key
"reason"
        Maybe Bool
need_rating_            <- Object
o Object -> Key -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
A..:?  Key
"need_rating"
        Maybe Bool
need_debug_information_ <- Object
o Object -> Key -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
A..:?  Key
"need_debug_information"
        Maybe Bool
need_log_               <- Object
o Object -> Key -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
A..:?  Key
"need_log"
        CallState -> Parser CallState
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CallState -> Parser CallState) -> CallState -> Parser CallState
forall a b. (a -> b) -> a -> b
$ CallStateDiscarded
          { reason :: Maybe CallDiscardReason
reason                 = Maybe CallDiscardReason
reason_
          , need_rating :: Maybe Bool
need_rating            = Maybe Bool
need_rating_
          , need_debug_information :: Maybe Bool
need_debug_information = Maybe Bool
need_debug_information_
          , need_log :: Maybe Bool
need_log               = Maybe Bool
need_log_
          }
      parseCallStateError :: A.Value -> AT.Parser CallState
      parseCallStateError :: Value -> Parser CallState
parseCallStateError = String -> (Object -> Parser CallState) -> Value -> Parser CallState
forall a. String -> (Object -> Parser a) -> Value -> Parser a
A.withObject String
"CallStateError" ((Object -> Parser CallState) -> Value -> Parser CallState)
-> (Object -> Parser CallState) -> Value -> Parser CallState
forall a b. (a -> b) -> a -> b
$ \Object
o -> do
        Maybe Error
_error_ <- Object
o Object -> Key -> Parser (Maybe Error)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
A..:?  Key
"error"
        CallState -> Parser CallState
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CallState -> Parser CallState) -> CallState -> Parser CallState
forall a b. (a -> b) -> a -> b
$ CallStateError
          { _error :: Maybe Error
_error = Maybe Error
_error_
          }
  parseJSON Value
_ = Parser CallState
forall a. Monoid a => a
mempty