{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}

module Simplex.Chat.Types.Shared where

import Data.Aeson (FromJSON (..), ToJSON (..))
import qualified Data.Aeson.TH as JQ
import qualified Data.Attoparsec.ByteString.Char8 as A
import qualified Data.ByteString.Char8 as B
import Data.Text (Text)
import Simplex.Chat.Options.DB (FromField (..), ToField (..))
import Simplex.Messaging.Agent.Store.DB (fromTextField_)
import Simplex.Messaging.Encoding.String
import Simplex.Messaging.Parsers (dropPrefix, enumJSON)
import Simplex.Messaging.Util ((<$?>))

data GroupMemberRole
  = GRUnknown Text -- unknown role from a newer client
  | GRRelay -- chat relay: forwards messages, can't send its own messages
  | GRObserver -- connects to all group members and receives all messages, can't send messages
  | GRAuthor -- reserved, unused
  | GRMember -- + can send messages to all group members
  | GRModerator -- + moderate messages and block members (excl. Admins and Owners)
  | GRAdmin -- + add/remove members, change member role (excl. Owners)
  | GROwner -- + delete and change group information, add/remove/change roles for Owners
  deriving (GroupMemberRole -> GroupMemberRole -> Bool
(GroupMemberRole -> GroupMemberRole -> Bool)
-> (GroupMemberRole -> GroupMemberRole -> Bool)
-> Eq GroupMemberRole
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: GroupMemberRole -> GroupMemberRole -> Bool
== :: GroupMemberRole -> GroupMemberRole -> Bool
$c/= :: GroupMemberRole -> GroupMemberRole -> Bool
/= :: GroupMemberRole -> GroupMemberRole -> Bool
Eq, Int -> GroupMemberRole -> ShowS
[GroupMemberRole] -> ShowS
GroupMemberRole -> String
(Int -> GroupMemberRole -> ShowS)
-> (GroupMemberRole -> String)
-> ([GroupMemberRole] -> ShowS)
-> Show GroupMemberRole
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> GroupMemberRole -> ShowS
showsPrec :: Int -> GroupMemberRole -> ShowS
$cshow :: GroupMemberRole -> String
show :: GroupMemberRole -> String
$cshowList :: [GroupMemberRole] -> ShowS
showList :: [GroupMemberRole] -> ShowS
Show, Eq GroupMemberRole
Eq GroupMemberRole =>
(GroupMemberRole -> GroupMemberRole -> Ordering)
-> (GroupMemberRole -> GroupMemberRole -> Bool)
-> (GroupMemberRole -> GroupMemberRole -> Bool)
-> (GroupMemberRole -> GroupMemberRole -> Bool)
-> (GroupMemberRole -> GroupMemberRole -> Bool)
-> (GroupMemberRole -> GroupMemberRole -> GroupMemberRole)
-> (GroupMemberRole -> GroupMemberRole -> GroupMemberRole)
-> Ord GroupMemberRole
GroupMemberRole -> GroupMemberRole -> Bool
GroupMemberRole -> GroupMemberRole -> Ordering
GroupMemberRole -> GroupMemberRole -> GroupMemberRole
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: GroupMemberRole -> GroupMemberRole -> Ordering
compare :: GroupMemberRole -> GroupMemberRole -> Ordering
$c< :: GroupMemberRole -> GroupMemberRole -> Bool
< :: GroupMemberRole -> GroupMemberRole -> Bool
$c<= :: GroupMemberRole -> GroupMemberRole -> Bool
<= :: GroupMemberRole -> GroupMemberRole -> Bool
$c> :: GroupMemberRole -> GroupMemberRole -> Bool
> :: GroupMemberRole -> GroupMemberRole -> Bool
$c>= :: GroupMemberRole -> GroupMemberRole -> Bool
>= :: GroupMemberRole -> GroupMemberRole -> Bool
$cmax :: GroupMemberRole -> GroupMemberRole -> GroupMemberRole
max :: GroupMemberRole -> GroupMemberRole -> GroupMemberRole
$cmin :: GroupMemberRole -> GroupMemberRole -> GroupMemberRole
min :: GroupMemberRole -> GroupMemberRole -> GroupMemberRole
Ord)

instance FromField GroupMemberRole where fromField :: FieldParser GroupMemberRole
fromField = (Text -> Maybe GroupMemberRole) -> FieldParser GroupMemberRole
forall a. Typeable a => (Text -> Maybe a) -> Field -> Ok a
fromTextField_ Text -> Maybe GroupMemberRole
forall a. TextEncoding a => Text -> Maybe a
textDecode

instance ToField GroupMemberRole where toField :: GroupMemberRole -> SQLData
toField = Text -> SQLData
forall a. ToField a => a -> SQLData
toField (Text -> SQLData)
-> (GroupMemberRole -> Text) -> GroupMemberRole -> SQLData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GroupMemberRole -> Text
forall a. TextEncoding a => a -> Text
textEncode

instance TextEncoding GroupMemberRole where
  textEncode :: GroupMemberRole -> Text
textEncode = \case
    GroupMemberRole
GROwner -> Text
"owner"
    GroupMemberRole
GRAdmin -> Text
"admin"
    GroupMemberRole
GRModerator -> Text
"moderator"
    GroupMemberRole
GRMember -> Text
"member"
    GroupMemberRole
GRAuthor -> Text
"author"
    GroupMemberRole
GRObserver -> Text
"observer"
    GroupMemberRole
GRRelay -> Text
"relay"
    GRUnknown Text
t -> Text
t
  textDecode :: Text -> Maybe GroupMemberRole
textDecode = GroupMemberRole -> Maybe GroupMemberRole
forall a. a -> Maybe a
Just (GroupMemberRole -> Maybe GroupMemberRole)
-> (Text -> GroupMemberRole) -> Text -> Maybe GroupMemberRole
forall b c a. (b -> c) -> (a -> b) -> a -> c
. \case
    Text
"owner" -> GroupMemberRole
GROwner
    Text
"admin" -> GroupMemberRole
GRAdmin
    Text
"moderator" -> GroupMemberRole
GRModerator
    Text
"member" -> GroupMemberRole
GRMember
    Text
"author" -> GroupMemberRole
GRAuthor
    Text
"observer" -> GroupMemberRole
GRObserver
    Text
"relay" -> GroupMemberRole
GRRelay
    Text
t -> Text -> GroupMemberRole
GRUnknown Text
t

instance FromJSON GroupMemberRole where
  parseJSON :: Value -> Parser GroupMemberRole
parseJSON = String -> Value -> Parser GroupMemberRole
forall a. TextEncoding a => String -> Value -> Parser a
textParseJSON String
"GroupMemberRole"

instance ToJSON GroupMemberRole where
  toJSON :: GroupMemberRole -> Value
toJSON = GroupMemberRole -> Value
forall a. TextEncoding a => a -> Value
textToJSON
  toEncoding :: GroupMemberRole -> Encoding
toEncoding = GroupMemberRole -> Encoding
forall a. TextEncoding a => a -> Encoding
textToEncoding

data GroupAcceptance = GAAccepted | GAPendingApproval | GAPendingReview  deriving (GroupAcceptance -> GroupAcceptance -> Bool
(GroupAcceptance -> GroupAcceptance -> Bool)
-> (GroupAcceptance -> GroupAcceptance -> Bool)
-> Eq GroupAcceptance
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: GroupAcceptance -> GroupAcceptance -> Bool
== :: GroupAcceptance -> GroupAcceptance -> Bool
$c/= :: GroupAcceptance -> GroupAcceptance -> Bool
/= :: GroupAcceptance -> GroupAcceptance -> Bool
Eq, Int -> GroupAcceptance -> ShowS
[GroupAcceptance] -> ShowS
GroupAcceptance -> String
(Int -> GroupAcceptance -> ShowS)
-> (GroupAcceptance -> String)
-> ([GroupAcceptance] -> ShowS)
-> Show GroupAcceptance
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> GroupAcceptance -> ShowS
showsPrec :: Int -> GroupAcceptance -> ShowS
$cshow :: GroupAcceptance -> String
show :: GroupAcceptance -> String
$cshowList :: [GroupAcceptance] -> ShowS
showList :: [GroupAcceptance] -> ShowS
Show)

instance StrEncoding GroupAcceptance where
  strEncode :: GroupAcceptance -> ByteString
strEncode = \case
    GroupAcceptance
GAAccepted -> ByteString
"accepted"
    GroupAcceptance
GAPendingApproval -> ByteString
"pending"
    GroupAcceptance
GAPendingReview -> ByteString
"pending_review"
  strDecode :: ByteString -> Either String GroupAcceptance
strDecode = \case
    ByteString
"accepted" -> GroupAcceptance -> Either String GroupAcceptance
forall a b. b -> Either a b
Right GroupAcceptance
GAAccepted
    ByteString
"pending" -> GroupAcceptance -> Either String GroupAcceptance
forall a b. b -> Either a b
Right GroupAcceptance
GAPendingApproval
    ByteString
"pending_review" -> GroupAcceptance -> Either String GroupAcceptance
forall a b. b -> Either a b
Right GroupAcceptance
GAPendingReview
    ByteString
r -> String -> Either String GroupAcceptance
forall a b. a -> Either a b
Left (String -> Either String GroupAcceptance)
-> String -> Either String GroupAcceptance
forall a b. (a -> b) -> a -> b
$ String
"bad GroupAcceptance " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> ByteString -> String
B.unpack ByteString
r
  strP :: Parser GroupAcceptance
strP = ByteString -> Either String GroupAcceptance
forall a. StrEncoding a => ByteString -> Either String a
strDecode (ByteString -> Either String GroupAcceptance)
-> Parser ByteString ByteString -> Parser GroupAcceptance
forall (m :: * -> *) a b.
MonadFail m =>
(a -> Either String b) -> m a -> m b
<$?> Parser ByteString ByteString
A.takeByteString

instance FromJSON GroupAcceptance where
  parseJSON :: Value -> Parser GroupAcceptance
parseJSON = String -> Value -> Parser GroupAcceptance
forall a. StrEncoding a => String -> Value -> Parser a
strParseJSON String
"GroupAcceptance"

instance ToJSON GroupAcceptance where
  toJSON :: GroupAcceptance -> Value
toJSON = GroupAcceptance -> Value
forall a. StrEncoding a => a -> Value
strToJSON
  toEncoding :: GroupAcceptance -> Encoding
toEncoding = GroupAcceptance -> Encoding
forall a. StrEncoding a => a -> Encoding
strToJEncoding

data RelayStatus
  = RSNew -- only for owner
  | RSInvited
  | RSAccepted
  | RSActive
  | RSInactive
  deriving (RelayStatus -> RelayStatus -> Bool
(RelayStatus -> RelayStatus -> Bool)
-> (RelayStatus -> RelayStatus -> Bool) -> Eq RelayStatus
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: RelayStatus -> RelayStatus -> Bool
== :: RelayStatus -> RelayStatus -> Bool
$c/= :: RelayStatus -> RelayStatus -> Bool
/= :: RelayStatus -> RelayStatus -> Bool
Eq, Int -> RelayStatus -> ShowS
[RelayStatus] -> ShowS
RelayStatus -> String
(Int -> RelayStatus -> ShowS)
-> (RelayStatus -> String)
-> ([RelayStatus] -> ShowS)
-> Show RelayStatus
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> RelayStatus -> ShowS
showsPrec :: Int -> RelayStatus -> ShowS
$cshow :: RelayStatus -> String
show :: RelayStatus -> String
$cshowList :: [RelayStatus] -> ShowS
showList :: [RelayStatus] -> ShowS
Show)

relayStatusText :: RelayStatus -> Text
relayStatusText :: RelayStatus -> Text
relayStatusText = \case
  RelayStatus
RSNew -> Text
"new"
  RelayStatus
RSInvited -> Text
"invited"
  RelayStatus
RSAccepted -> Text
"accepted"
  RelayStatus
RSActive -> Text
"active"
  RelayStatus
RSInactive -> Text
"inactive"

instance TextEncoding RelayStatus where
  textEncode :: RelayStatus -> Text
textEncode = \case
    RelayStatus
RSNew -> Text
"new"
    RelayStatus
RSInvited -> Text
"invited"
    RelayStatus
RSAccepted -> Text
"accepted"
    RelayStatus
RSActive -> Text
"active"
    RelayStatus
RSInactive -> Text
"inactive"
  textDecode :: Text -> Maybe RelayStatus
textDecode = \case
    Text
"new" -> RelayStatus -> Maybe RelayStatus
forall a. a -> Maybe a
Just RelayStatus
RSNew
    Text
"invited" -> RelayStatus -> Maybe RelayStatus
forall a. a -> Maybe a
Just RelayStatus
RSInvited
    Text
"accepted" -> RelayStatus -> Maybe RelayStatus
forall a. a -> Maybe a
Just RelayStatus
RSAccepted
    Text
"active" -> RelayStatus -> Maybe RelayStatus
forall a. a -> Maybe a
Just RelayStatus
RSActive
    Text
"inactive" -> RelayStatus -> Maybe RelayStatus
forall a. a -> Maybe a
Just RelayStatus
RSInactive
    Text
_ -> Maybe RelayStatus
forall a. Maybe a
Nothing

instance FromField RelayStatus where fromField :: FieldParser RelayStatus
fromField = (Text -> Maybe RelayStatus) -> FieldParser RelayStatus
forall a. Typeable a => (Text -> Maybe a) -> Field -> Ok a
fromTextField_ Text -> Maybe RelayStatus
forall a. TextEncoding a => Text -> Maybe a
textDecode

instance ToField RelayStatus where toField :: RelayStatus -> SQLData
toField = Text -> SQLData
forall a. ToField a => a -> SQLData
toField (Text -> SQLData)
-> (RelayStatus -> Text) -> RelayStatus -> SQLData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RelayStatus -> Text
forall a. TextEncoding a => a -> Text
textEncode

$(JQ.deriveJSON (enumJSON $ dropPrefix "RS") ''RelayStatus)

data MsgSigStatus = MSSVerified | MSSSignedNoKey
  deriving (MsgSigStatus -> MsgSigStatus -> Bool
(MsgSigStatus -> MsgSigStatus -> Bool)
-> (MsgSigStatus -> MsgSigStatus -> Bool) -> Eq MsgSigStatus
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: MsgSigStatus -> MsgSigStatus -> Bool
== :: MsgSigStatus -> MsgSigStatus -> Bool
$c/= :: MsgSigStatus -> MsgSigStatus -> Bool
/= :: MsgSigStatus -> MsgSigStatus -> Bool
Eq, Int -> MsgSigStatus -> ShowS
[MsgSigStatus] -> ShowS
MsgSigStatus -> String
(Int -> MsgSigStatus -> ShowS)
-> (MsgSigStatus -> String)
-> ([MsgSigStatus] -> ShowS)
-> Show MsgSigStatus
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> MsgSigStatus -> ShowS
showsPrec :: Int -> MsgSigStatus -> ShowS
$cshow :: MsgSigStatus -> String
show :: MsgSigStatus -> String
$cshowList :: [MsgSigStatus] -> ShowS
showList :: [MsgSigStatus] -> ShowS
Show)

instance TextEncoding MsgSigStatus where
  textEncode :: MsgSigStatus -> Text
textEncode = \case
    MsgSigStatus
MSSVerified -> Text
"verified"
    MsgSigStatus
MSSSignedNoKey -> Text
"no_key"
  textDecode :: Text -> Maybe MsgSigStatus
textDecode = \case
    Text
"verified" -> MsgSigStatus -> Maybe MsgSigStatus
forall a. a -> Maybe a
Just MsgSigStatus
MSSVerified
    Text
"no_key" -> MsgSigStatus -> Maybe MsgSigStatus
forall a. a -> Maybe a
Just MsgSigStatus
MSSSignedNoKey
    Text
_ -> Maybe MsgSigStatus
forall a. Maybe a
Nothing

instance ToField MsgSigStatus where toField :: MsgSigStatus -> SQLData
toField = Text -> SQLData
forall a. ToField a => a -> SQLData
toField (Text -> SQLData)
-> (MsgSigStatus -> Text) -> MsgSigStatus -> SQLData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MsgSigStatus -> Text
forall a. TextEncoding a => a -> Text
textEncode

instance FromField MsgSigStatus where fromField :: FieldParser MsgSigStatus
fromField = (Text -> Maybe MsgSigStatus) -> FieldParser MsgSigStatus
forall a. Typeable a => (Text -> Maybe a) -> Field -> Ok a
fromTextField_ Text -> Maybe MsgSigStatus
forall a. TextEncoding a => Text -> Maybe a
textDecode

$(JQ.deriveJSON (enumJSON $ dropPrefix "MSS") ''MsgSigStatus)