{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}

module Simplex.Chat.Bot.KnownContacts where

import qualified Data.Attoparsec.ByteString.Char8 as A
import Data.Int (Int64)
import Data.Text (Text)
import qualified Data.Text as T
import Data.Text.Encoding (encodeUtf8)
import Options.Applicative
import Simplex.Chat.Library.Commands (displayNameP)
import Simplex.Messaging.Parsers (parseAll)

data KnownContact = KnownContact
  { KnownContact -> Int64
contactId :: Int64,
    KnownContact -> Text
localDisplayName :: Text
  }
  deriving (KnownContact -> KnownContact -> Bool
(KnownContact -> KnownContact -> Bool)
-> (KnownContact -> KnownContact -> Bool) -> Eq KnownContact
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: KnownContact -> KnownContact -> Bool
== :: KnownContact -> KnownContact -> Bool
$c/= :: KnownContact -> KnownContact -> Bool
/= :: KnownContact -> KnownContact -> Bool
Eq)

data KnownGroup = KnownGroup
  { KnownGroup -> Int64
groupId :: Int64,
    KnownGroup -> Text
localDisplayName :: Text
  }

knownContactNames :: [KnownContact] -> Text
knownContactNames :: [KnownContact] -> Text
knownContactNames = Text -> [Text] -> Text
T.intercalate Text
", " ([Text] -> Text)
-> ([KnownContact] -> [Text]) -> [KnownContact] -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (KnownContact -> Text) -> [KnownContact] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map ((Text
"@" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>) (Text -> Text) -> (KnownContact -> Text) -> KnownContact -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (\KnownContact {localDisplayName :: KnownContact -> Text
localDisplayName = Text
n} -> Text
n))

parseKnownContacts :: ReadM [KnownContact]
parseKnownContacts :: ReadM [KnownContact]
parseKnownContacts = (String -> Either String [KnownContact]) -> ReadM [KnownContact]
forall a. (String -> Either String a) -> ReadM a
eitherReader ((String -> Either String [KnownContact]) -> ReadM [KnownContact])
-> (String -> Either String [KnownContact]) -> ReadM [KnownContact]
forall a b. (a -> b) -> a -> b
$ Parser [KnownContact] -> ByteString -> Either String [KnownContact]
forall a. Parser a -> ByteString -> Either String a
parseAll Parser [KnownContact]
knownContactsP (ByteString -> Either String [KnownContact])
-> (String -> ByteString) -> String -> Either String [KnownContact]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
encodeUtf8 (Text -> ByteString) -> (String -> Text) -> String -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
T.pack

knownContactsP :: A.Parser [KnownContact]
knownContactsP :: Parser [KnownContact]
knownContactsP = Parser ByteString KnownContact
contactP Parser ByteString KnownContact
-> Parser ByteString Char -> Parser [KnownContact]
forall (f :: * -> *) a s. Alternative f => f a -> f s -> f [a]
`A.sepBy1` Char -> Parser ByteString Char
A.char Char
','
  where
    contactP :: Parser ByteString KnownContact
contactP = do
      Int64
contactId <- Parser Int64
forall a. Integral a => Parser a
A.decimal Parser Int64 -> Parser ByteString Char -> Parser Int64
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Char -> Parser ByteString Char
A.char Char
':'
      Text
localDisplayName <- Parser Text
displayNameP
      KnownContact -> Parser ByteString KnownContact
forall a. a -> Parser ByteString a
forall (f :: * -> *) a. Applicative f => a -> f a
pure KnownContact {Int64
contactId :: Int64
contactId :: Int64
contactId, Text
localDisplayName :: Text
localDisplayName :: Text
localDisplayName}

parseKnownGroup :: ReadM KnownGroup
parseKnownGroup :: ReadM KnownGroup
parseKnownGroup = (String -> Either String KnownGroup) -> ReadM KnownGroup
forall a. (String -> Either String a) -> ReadM a
eitherReader ((String -> Either String KnownGroup) -> ReadM KnownGroup)
-> (String -> Either String KnownGroup) -> ReadM KnownGroup
forall a b. (a -> b) -> a -> b
$ Parser KnownGroup -> ByteString -> Either String KnownGroup
forall a. Parser a -> ByteString -> Either String a
parseAll Parser KnownGroup
knownGroupP (ByteString -> Either String KnownGroup)
-> (String -> ByteString) -> String -> Either String KnownGroup
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
encodeUtf8 (Text -> ByteString) -> (String -> Text) -> String -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
T.pack

knownGroupP :: A.Parser KnownGroup
knownGroupP :: Parser KnownGroup
knownGroupP = do
  Int64
groupId <- Parser Int64
forall a. Integral a => Parser a
A.decimal Parser Int64 -> Parser ByteString Char -> Parser Int64
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Char -> Parser ByteString Char
A.char Char
':'
  Text
localDisplayName <- Parser Text
displayNameP
  KnownGroup -> Parser KnownGroup
forall a. a -> Parser ByteString a
forall (f :: * -> *) a. Applicative f => a -> f a
pure KnownGroup {Int64
groupId :: Int64
groupId :: Int64
groupId, Text
localDisplayName :: Text
localDisplayName :: Text
localDisplayName}