{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE TemplateHaskell #-}

module Simplex.Chat.Messages.CIContent.Events where

import Data.Aeson (FromJSON (..), ToJSON (..))
import qualified Data.Aeson.TH as J
import Simplex.Chat.Types
import Simplex.Chat.Types.Shared
import Simplex.Messaging.Agent.Protocol (RatchetSyncState (..), SwitchPhase (..))
import Simplex.Messaging.Parsers (dropPrefix, singleFieldJSON, sumTypeJSON)
import Simplex.Messaging.Crypto.Ratchet (PQEncryption)

data RcvGroupEvent
  = RGEMemberAdded {RcvGroupEvent -> GroupMemberId
groupMemberId :: GroupMemberId, RcvGroupEvent -> Profile
profile :: Profile} -- CRJoinedGroupMemberConnecting
  | RGEMemberConnected -- CEvtUserJoinedGroup, CRJoinedGroupMember, CEvtConnectedToGroupMember
  | RGEMemberAccepted {groupMemberId :: GroupMemberId, profile :: Profile}
  | RGEUserAccepted
  | RGEMemberLeft -- CRLeftMember
  | RGEMemberRole {groupMemberId :: GroupMemberId, profile :: Profile, RcvGroupEvent -> GroupMemberRole
role :: GroupMemberRole}
  | RGEMemberBlocked {groupMemberId :: GroupMemberId, profile :: Profile, RcvGroupEvent -> Bool
blocked :: Bool} -- CRMemberBlockedForAll
  | RGEUserRole {role :: GroupMemberRole}
  | RGEMemberDeleted {groupMemberId :: GroupMemberId, profile :: Profile} -- CRDeletedMember
  | RGEUserDeleted -- CRDeletedMemberUser
  | RGEGroupDeleted -- CRGroupDeleted
  | RGEGroupUpdated {RcvGroupEvent -> GroupProfile
groupProfile :: GroupProfile} -- CRGroupUpdated
  -- RGEInvitedViaGroupLink chat items are not received - they're created when sending group invitations,
  -- but being RcvGroupEvent allows them to be assigned to the respective member (and so enable "send direct message")
  -- and be created as unread without adding / working around new status for sent items
  | RGEInvitedViaGroupLink -- CRSentGroupInvitationViaLink
  | RGEMemberCreatedContact -- CRNewMemberContactReceivedInv
  | RGEMemberProfileUpdated {RcvGroupEvent -> Profile
fromProfile :: Profile, RcvGroupEvent -> Profile
toProfile :: Profile} -- CRGroupMemberUpdated
  | RGENewMemberPendingReview
  deriving (Int -> RcvGroupEvent -> ShowS
[RcvGroupEvent] -> ShowS
RcvGroupEvent -> String
(Int -> RcvGroupEvent -> ShowS)
-> (RcvGroupEvent -> String)
-> ([RcvGroupEvent] -> ShowS)
-> Show RcvGroupEvent
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> RcvGroupEvent -> ShowS
showsPrec :: Int -> RcvGroupEvent -> ShowS
$cshow :: RcvGroupEvent -> String
show :: RcvGroupEvent -> String
$cshowList :: [RcvGroupEvent] -> ShowS
showList :: [RcvGroupEvent] -> ShowS
Show)

data SndGroupEvent
  = SGEMemberRole {SndGroupEvent -> GroupMemberId
groupMemberId :: GroupMemberId, SndGroupEvent -> Profile
profile :: Profile, SndGroupEvent -> GroupMemberRole
role :: GroupMemberRole}
  | SGEMemberBlocked {groupMemberId :: GroupMemberId, profile :: Profile, SndGroupEvent -> Bool
blocked :: Bool} -- CRMembersBlockedForAllUser
  | SGEUserRole {role :: GroupMemberRole}
  | SGEMemberDeleted {groupMemberId :: GroupMemberId, profile :: Profile} -- CRUserDeletedMembers
  | SGEUserLeft -- CRLeftMemberUser
  | SGEGroupUpdated {SndGroupEvent -> GroupProfile
groupProfile :: GroupProfile} -- CRGroupUpdated
  | SGEMemberAccepted {groupMemberId :: GroupMemberId, profile :: Profile}
  | SGEUserPendingReview
  deriving (Int -> SndGroupEvent -> ShowS
[SndGroupEvent] -> ShowS
SndGroupEvent -> String
(Int -> SndGroupEvent -> ShowS)
-> (SndGroupEvent -> String)
-> ([SndGroupEvent] -> ShowS)
-> Show SndGroupEvent
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SndGroupEvent -> ShowS
showsPrec :: Int -> SndGroupEvent -> ShowS
$cshow :: SndGroupEvent -> String
show :: SndGroupEvent -> String
$cshowList :: [SndGroupEvent] -> ShowS
showList :: [SndGroupEvent] -> ShowS
Show)

data RcvConnEvent
  = RCESwitchQueue {RcvConnEvent -> SwitchPhase
phase :: SwitchPhase}
  | RCERatchetSync {RcvConnEvent -> RatchetSyncState
syncStatus :: RatchetSyncState}
  | RCEVerificationCodeReset
  | RCEPqEnabled {RcvConnEvent -> PQEncryption
enabled :: PQEncryption}
  deriving (Int -> RcvConnEvent -> ShowS
[RcvConnEvent] -> ShowS
RcvConnEvent -> String
(Int -> RcvConnEvent -> ShowS)
-> (RcvConnEvent -> String)
-> ([RcvConnEvent] -> ShowS)
-> Show RcvConnEvent
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> RcvConnEvent -> ShowS
showsPrec :: Int -> RcvConnEvent -> ShowS
$cshow :: RcvConnEvent -> String
show :: RcvConnEvent -> String
$cshowList :: [RcvConnEvent] -> ShowS
showList :: [RcvConnEvent] -> ShowS
Show)

data SndConnEvent
  = SCESwitchQueue {SndConnEvent -> SwitchPhase
phase :: SwitchPhase, SndConnEvent -> Maybe GroupMemberRef
member :: Maybe GroupMemberRef}
  | SCERatchetSync {SndConnEvent -> RatchetSyncState
syncStatus :: RatchetSyncState, member :: Maybe GroupMemberRef}
  | SCEPqEnabled {SndConnEvent -> PQEncryption
enabled :: PQEncryption}
  deriving (Int -> SndConnEvent -> ShowS
[SndConnEvent] -> ShowS
SndConnEvent -> String
(Int -> SndConnEvent -> ShowS)
-> (SndConnEvent -> String)
-> ([SndConnEvent] -> ShowS)
-> Show SndConnEvent
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SndConnEvent -> ShowS
showsPrec :: Int -> SndConnEvent -> ShowS
$cshow :: SndConnEvent -> String
show :: SndConnEvent -> String
$cshowList :: [SndConnEvent] -> ShowS
showList :: [SndConnEvent] -> ShowS
Show)

data RcvDirectEvent
  = RDEContactDeleted
  | RDEProfileUpdated {RcvDirectEvent -> Profile
fromProfile :: Profile, RcvDirectEvent -> Profile
toProfile :: Profile} -- CRContactUpdated
  | RDEGroupInvLinkReceived {RcvDirectEvent -> GroupProfile
groupProfile :: GroupProfile}
  deriving (Int -> RcvDirectEvent -> ShowS
[RcvDirectEvent] -> ShowS
RcvDirectEvent -> String
(Int -> RcvDirectEvent -> ShowS)
-> (RcvDirectEvent -> String)
-> ([RcvDirectEvent] -> ShowS)
-> Show RcvDirectEvent
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> RcvDirectEvent -> ShowS
showsPrec :: Int -> RcvDirectEvent -> ShowS
$cshow :: RcvDirectEvent -> String
show :: RcvDirectEvent -> String
$cshowList :: [RcvDirectEvent] -> ShowS
showList :: [RcvDirectEvent] -> ShowS
Show)

-- platform-specific JSON encoding (used in API)
$(J.deriveJSON (sumTypeJSON $ dropPrefix "RGE") ''RcvGroupEvent)

-- platform-independent JSON encoding (stored in DB)
newtype DBRcvGroupEvent = RGE RcvGroupEvent

instance FromJSON DBRcvGroupEvent where
  parseJSON :: Value -> Parser DBRcvGroupEvent
parseJSON Value
v = RcvGroupEvent -> DBRcvGroupEvent
RGE (RcvGroupEvent -> DBRcvGroupEvent)
-> Parser RcvGroupEvent -> Parser DBRcvGroupEvent
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> $(J.mkParseJSON (singleFieldJSON $ dropPrefix "RGE") ''RcvGroupEvent) Value
v

instance ToJSON DBRcvGroupEvent where
  toJSON :: DBRcvGroupEvent -> Value
toJSON (RGE RcvGroupEvent
v) = $(J.mkToJSON (singleFieldJSON $ dropPrefix "RGE") ''RcvGroupEvent) RcvGroupEvent
v
  toEncoding :: DBRcvGroupEvent -> Encoding
toEncoding (RGE RcvGroupEvent
v) = $(J.mkToEncoding (singleFieldJSON $ dropPrefix "RGE") ''RcvGroupEvent) RcvGroupEvent
v

-- platform-specific JSON encoding (used in API)
$(J.deriveJSON (sumTypeJSON $ dropPrefix "SGE") ''SndGroupEvent)

-- platform-independent JSON encoding (stored in DB)
newtype DBSndGroupEvent = SGE SndGroupEvent

instance FromJSON DBSndGroupEvent where
  parseJSON :: Value -> Parser DBSndGroupEvent
parseJSON Value
v = SndGroupEvent -> DBSndGroupEvent
SGE (SndGroupEvent -> DBSndGroupEvent)
-> Parser SndGroupEvent -> Parser DBSndGroupEvent
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> $(J.mkParseJSON (singleFieldJSON $ dropPrefix "SGE") ''SndGroupEvent) Value
v

instance ToJSON DBSndGroupEvent where
  toJSON :: DBSndGroupEvent -> Value
toJSON (SGE SndGroupEvent
v) = $(J.mkToJSON (singleFieldJSON $ dropPrefix "SGE") ''SndGroupEvent) SndGroupEvent
v
  toEncoding :: DBSndGroupEvent -> Encoding
toEncoding (SGE SndGroupEvent
v) = $(J.mkToEncoding (singleFieldJSON $ dropPrefix "SGE") ''SndGroupEvent) SndGroupEvent
v

-- platform-specific JSON encoding (used in API)
$(J.deriveJSON (sumTypeJSON $ dropPrefix "RCE") ''RcvConnEvent)

-- platform-independent JSON encoding (stored in DB)
newtype DBRcvConnEvent = RCE RcvConnEvent

instance FromJSON DBRcvConnEvent where
  parseJSON :: Value -> Parser DBRcvConnEvent
parseJSON Value
v = RcvConnEvent -> DBRcvConnEvent
RCE (RcvConnEvent -> DBRcvConnEvent)
-> Parser RcvConnEvent -> Parser DBRcvConnEvent
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> $(J.mkParseJSON (singleFieldJSON $ dropPrefix "RCE") ''RcvConnEvent) Value
v

instance ToJSON DBRcvConnEvent where
  toJSON :: DBRcvConnEvent -> Value
toJSON (RCE RcvConnEvent
v) = $(J.mkToJSON (singleFieldJSON $ dropPrefix "RCE") ''RcvConnEvent) RcvConnEvent
v
  toEncoding :: DBRcvConnEvent -> Encoding
toEncoding (RCE RcvConnEvent
v) = $(J.mkToEncoding (singleFieldJSON $ dropPrefix "RCE") ''RcvConnEvent) RcvConnEvent
v

-- platform-specific JSON encoding (used in API)
$(J.deriveJSON (sumTypeJSON $ dropPrefix "SCE") ''SndConnEvent)

-- platform-independent JSON encoding (stored in DB)
newtype DBSndConnEvent = SCE SndConnEvent

instance FromJSON DBSndConnEvent where
  parseJSON :: Value -> Parser DBSndConnEvent
parseJSON Value
v = SndConnEvent -> DBSndConnEvent
SCE (SndConnEvent -> DBSndConnEvent)
-> Parser SndConnEvent -> Parser DBSndConnEvent
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> $(J.mkParseJSON (singleFieldJSON $ dropPrefix "SCE") ''SndConnEvent) Value
v

instance ToJSON DBSndConnEvent where
  toJSON :: DBSndConnEvent -> Value
toJSON (SCE SndConnEvent
v) = $(J.mkToJSON (singleFieldJSON $ dropPrefix "SCE") ''SndConnEvent) SndConnEvent
v
  toEncoding :: DBSndConnEvent -> Encoding
toEncoding (SCE SndConnEvent
v) = $(J.mkToEncoding (singleFieldJSON $ dropPrefix "SCE") ''SndConnEvent) SndConnEvent
v

$(J.deriveJSON (sumTypeJSON $ dropPrefix "RDE") ''RcvDirectEvent)

-- platform-independent JSON encoding (stored in DB)
newtype DBRcvDirectEvent = RDE RcvDirectEvent

instance FromJSON DBRcvDirectEvent where
  parseJSON :: Value -> Parser DBRcvDirectEvent
parseJSON Value
v = RcvDirectEvent -> DBRcvDirectEvent
RDE (RcvDirectEvent -> DBRcvDirectEvent)
-> Parser RcvDirectEvent -> Parser DBRcvDirectEvent
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> $(J.mkParseJSON (singleFieldJSON $ dropPrefix "RDE") ''RcvDirectEvent) Value
v

instance ToJSON DBRcvDirectEvent where
  toJSON :: DBRcvDirectEvent -> Value
toJSON (RDE RcvDirectEvent
v) = $(J.mkToJSON (singleFieldJSON $ dropPrefix "RDE") ''RcvDirectEvent) RcvDirectEvent
v
  toEncoding :: DBRcvDirectEvent -> Encoding
toEncoding (RDE RcvDirectEvent
v) = $(J.mkToEncoding (singleFieldJSON $ dropPrefix "RDE") ''RcvDirectEvent) RcvDirectEvent
v