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

module Simplex.Chat.Types.Shared where

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

data GroupMemberRole
  = 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 = (ByteString -> Either String GroupMemberRole)
-> FieldParser GroupMemberRole
forall k.
Typeable k =>
(ByteString -> Either String k) -> FieldParser k
blobFieldDecoder ByteString -> Either String GroupMemberRole
forall a. StrEncoding a => ByteString -> Either String a
strDecode

instance ToField GroupMemberRole where toField :: GroupMemberRole -> SQLData
toField = ByteString -> SQLData
forall a. ToField a => a -> SQLData
toField (ByteString -> SQLData)
-> (GroupMemberRole -> ByteString) -> GroupMemberRole -> SQLData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GroupMemberRole -> ByteString
forall a. StrEncoding a => a -> ByteString
strEncode

instance StrEncoding GroupMemberRole where
  strEncode :: GroupMemberRole -> ByteString
strEncode = \case
    GroupMemberRole
GROwner -> ByteString
"owner"
    GroupMemberRole
GRAdmin -> ByteString
"admin"
    GroupMemberRole
GRModerator -> ByteString
"moderator"
    GroupMemberRole
GRMember -> ByteString
"member"
    GroupMemberRole
GRAuthor -> ByteString
"author"
    GroupMemberRole
GRObserver -> ByteString
"observer"
  strDecode :: ByteString -> Either String GroupMemberRole
strDecode = \case
    ByteString
"owner" -> GroupMemberRole -> Either String GroupMemberRole
forall a b. b -> Either a b
Right GroupMemberRole
GROwner
    ByteString
"admin" -> GroupMemberRole -> Either String GroupMemberRole
forall a b. b -> Either a b
Right GroupMemberRole
GRAdmin
    ByteString
"moderator" -> GroupMemberRole -> Either String GroupMemberRole
forall a b. b -> Either a b
Right GroupMemberRole
GRModerator
    ByteString
"member" -> GroupMemberRole -> Either String GroupMemberRole
forall a b. b -> Either a b
Right GroupMemberRole
GRMember
    ByteString
"author" -> GroupMemberRole -> Either String GroupMemberRole
forall a b. b -> Either a b
Right GroupMemberRole
GRAuthor
    ByteString
"observer" -> GroupMemberRole -> Either String GroupMemberRole
forall a b. b -> Either a b
Right GroupMemberRole
GRObserver
    ByteString
r -> String -> Either String GroupMemberRole
forall a b. a -> Either a b
Left (String -> Either String GroupMemberRole)
-> String -> Either String GroupMemberRole
forall a b. (a -> b) -> a -> b
$ String
"bad GroupMemberRole " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> ByteString -> String
B.unpack ByteString
r
  strP :: Parser GroupMemberRole
strP = ByteString -> Either String GroupMemberRole
forall a. StrEncoding a => ByteString -> Either String a
strDecode (ByteString -> Either String GroupMemberRole)
-> Parser ByteString ByteString -> Parser GroupMemberRole
forall (m :: * -> *) a b.
MonadFail m =>
(a -> Either String b) -> m a -> m b
<$?> Parser ByteString ByteString
A.takeByteString

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

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

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