module API.Gundeck where

import API.Common
import qualified Data.ByteString.Base16 as Base16
import qualified Data.Text as Text
import qualified Data.Text.Encoding as Text
import Testlib.Prelude

data GetNotifications = GetNotifications
  { GetNotifications -> Maybe String
since :: Maybe String,
    GetNotifications -> Maybe Int
size :: Maybe Int,
    GetNotifications -> Maybe String
client :: Maybe String
  }

instance Default GetNotifications where
  def :: GetNotifications
def = GetNotifications {$sel:since:GetNotifications :: Maybe String
since = Maybe String
forall a. Maybe a
Nothing, $sel:size:GetNotifications :: Maybe Int
size = Maybe Int
forall a. Maybe a
Nothing, $sel:client:GetNotifications :: Maybe String
client = Maybe String
forall a. Maybe a
Nothing}

getNotifications ::
  (HasCallStack, MakesValue user) =>
  user ->
  GetNotifications ->
  App Response
getNotifications :: forall user.
(HasCallStack, MakesValue user) =>
user -> GetNotifications -> App Response
getNotifications user
user GetNotifications
r = do
  Request
req <- user -> Service -> Versioned -> String -> App Request
forall user.
(HasCallStack, MakesValue user) =>
user -> Service -> Versioned -> String -> App Request
baseRequest user
user Service
Gundeck Versioned
Versioned String
"/notifications"
  let req' :: Request
req' =
        Request
req
          Request -> (Request -> Request) -> Request
forall a b. a -> (a -> b) -> b
& [(String, String)] -> Request -> Request
addQueryParams
            ( [(String
"since", String
since) | String
since <- Maybe String -> [String]
forall a. Maybe a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList GetNotifications
r.since]
                [(String, String)] -> [(String, String)] -> [(String, String)]
forall a. Semigroup a => a -> a -> a
<> [(String
"client", String
c) | String
c <- Maybe String -> [String]
forall a. Maybe a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList GetNotifications
r.client]
                [(String, String)] -> [(String, String)] -> [(String, String)]
forall a. Semigroup a => a -> a -> a
<> [(String
"size", Int -> String
forall a. Show a => a -> String
show Int
size) | Int
size <- Maybe Int -> [Int]
forall a. Maybe a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList GetNotifications
r.size]
            )
  String -> Request -> App Response
submit String
"GET" Request
req'

data GetNotification = GetNotification
  { GetNotification -> Maybe String
client :: Maybe String
  }

instance Default GetNotification where
  def :: GetNotification
def = Maybe String -> GetNotification
GetNotification Maybe String
forall a. Maybe a
Nothing

getNotification ::
  (HasCallStack, MakesValue user, MakesValue nid) =>
  user ->
  GetNotification ->
  nid ->
  App Response
getNotification :: forall user nid.
(HasCallStack, MakesValue user, MakesValue nid) =>
user -> GetNotification -> nid -> App Response
getNotification user
user GetNotification
opts nid
nid = do
  String
n <- nid
nid nid -> (nid -> App String) -> App String
forall a b. a -> (a -> b) -> b
& nid -> App String
forall a. (HasCallStack, MakesValue a) => a -> App String
asString
  Request
req <-
    user -> Service -> Versioned -> String -> App Request
forall user.
(HasCallStack, MakesValue user) =>
user -> Service -> Versioned -> String -> App Request
baseRequest user
user Service
Gundeck Versioned
Versioned
      (String -> App Request) -> String -> App Request
forall a b. (a -> b) -> a -> b
$ [String] -> String
joinHttpPath [String
"notifications", String
n]
  String -> Request -> App Response
submit String
"GET" (Request -> App Response) -> Request -> App Response
forall a b. (a -> b) -> a -> b
$ Request
req Request -> (Request -> Request) -> Request
forall a b. a -> (a -> b) -> b
& [(String, String)] -> Request -> Request
addQueryParams [(String
"client", String
c) | String
c <- Maybe String -> [String]
forall a. Maybe a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList GetNotification
opts.client]

getLastNotification ::
  (HasCallStack, MakesValue user) =>
  user ->
  GetNotification ->
  App Response
getLastNotification :: forall user.
(HasCallStack, MakesValue user) =>
user -> GetNotification -> App Response
getLastNotification user
user GetNotification
opts = do
  Request
req <-
    user -> Service -> Versioned -> String -> App Request
forall user.
(HasCallStack, MakesValue user) =>
user -> Service -> Versioned -> String -> App Request
baseRequest user
user Service
Gundeck Versioned
Versioned String
"/notifications/last"
  String -> Request -> App Response
submit String
"GET" (Request -> App Response) -> Request -> App Response
forall a b. (a -> b) -> a -> b
$ Request
req Request -> (Request -> Request) -> Request
forall a b. a -> (a -> b) -> b
& [(String, String)] -> Request -> Request
addQueryParams [(String
"client", String
c) | String
c <- Maybe String -> [String]
forall a. Maybe a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList GetNotification
opts.client]

data GeneratePushToken = GeneratePushToken
  { GeneratePushToken -> String
transport :: String,
    GeneratePushToken -> String
app :: String,
    GeneratePushToken -> Int
tokenSize :: Int
  }

instance Default GeneratePushToken where
  def :: GeneratePushToken
def =
    GeneratePushToken
      { $sel:transport:GeneratePushToken :: String
transport = String
"GCM",
        $sel:app:GeneratePushToken :: String
app = String
"test",
        $sel:tokenSize:GeneratePushToken :: Int
tokenSize = Int
16
      }

generateAndPostPushToken ::
  (HasCallStack, MakesValue user, MakesValue client) =>
  user ->
  client ->
  GeneratePushToken ->
  App Response
generateAndPostPushToken :: forall user client.
(HasCallStack, MakesValue user, MakesValue client) =>
user -> client -> GeneratePushToken -> App Response
generateAndPostPushToken user
user client
client GeneratePushToken
args = do
  String
token <- Int -> App String
generateToken GeneratePushToken
args.tokenSize
  String
clientId <- client -> App Value
forall a. (MakesValue a, HasCallStack) => a -> App Value
make client
client App Value -> (App Value -> App String) -> App String
forall a b. a -> (a -> b) -> b
& App Value -> App String
forall a. (HasCallStack, MakesValue a) => a -> App String
asString
  user -> PushToken -> App Response
forall token user.
(HasCallStack, MakesValue token, MakesValue user) =>
user -> token -> App Response
postPushToken user
user (PushToken -> App Response) -> PushToken -> App Response
forall a b. (a -> b) -> a -> b
$ String -> String -> String -> String -> PushToken
PushToken GeneratePushToken
args.transport GeneratePushToken
args.app String
token String
clientId

data PushToken = PushToken
  { PushToken -> String
transport :: String,
    PushToken -> String
app :: String,
    PushToken -> String
token :: String,
    PushToken -> String
client :: String
  }
  deriving (Int -> PushToken -> ShowS
[PushToken] -> ShowS
PushToken -> String
(Int -> PushToken -> ShowS)
-> (PushToken -> String)
-> ([PushToken] -> ShowS)
-> Show PushToken
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PushToken -> ShowS
showsPrec :: Int -> PushToken -> ShowS
$cshow :: PushToken -> String
show :: PushToken -> String
$cshowList :: [PushToken] -> ShowS
showList :: [PushToken] -> ShowS
Show, PushToken -> PushToken -> Bool
(PushToken -> PushToken -> Bool)
-> (PushToken -> PushToken -> Bool) -> Eq PushToken
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PushToken -> PushToken -> Bool
== :: PushToken -> PushToken -> Bool
$c/= :: PushToken -> PushToken -> Bool
/= :: PushToken -> PushToken -> Bool
Eq)

instance ToJSON PushToken where
  toJSON :: PushToken -> Value
toJSON PushToken
pt =
    [Pair] -> Value
object
      [ String
"transport" String -> String -> Pair
forall a. ToJSON a => String -> a -> Pair
.= PushToken
pt.transport,
        String
"app" String -> String -> Pair
forall a. ToJSON a => String -> a -> Pair
.= PushToken
pt.app,
        String
"token" String -> String -> Pair
forall a. ToJSON a => String -> a -> Pair
.= PushToken
pt.token,
        String
"client" String -> String -> Pair
forall a. ToJSON a => String -> a -> Pair
.= PushToken
pt.client
      ]

instance MakesValue PushToken where
  make :: HasCallStack => PushToken -> App Value
make = Value -> App Value
forall a. a -> App a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Value -> App Value)
-> (PushToken -> Value) -> PushToken -> App Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PushToken -> Value
forall a. ToJSON a => a -> Value
toJSON

generateToken :: Int -> App String
generateToken :: Int -> App String
generateToken =
  (ByteString -> String) -> App ByteString -> App String
forall a b. (a -> b) -> App a -> App b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Text -> String
Text.unpack (Text -> String) -> (ByteString -> Text) -> ByteString -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Text
Text.decodeUtf8 (ByteString -> Text)
-> (ByteString -> ByteString) -> ByteString -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
Base16.encode) (App ByteString -> App String)
-> (Int -> App ByteString) -> Int -> App String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> App ByteString
randomBytes

postPushToken ::
  ( HasCallStack,
    MakesValue token,
    MakesValue user
  ) =>
  user ->
  token ->
  App Response
postPushToken :: forall token user.
(HasCallStack, MakesValue token, MakesValue user) =>
user -> token -> App Response
postPushToken user
user token
token = do
  Request
req <- user -> Service -> Versioned -> String -> App Request
forall user.
(HasCallStack, MakesValue user) =>
user -> Service -> Versioned -> String -> App Request
baseRequest user
user Service
Gundeck Versioned
Versioned String
"/push/tokens"
  Value
tokenJson <- token -> App Value
forall a. (MakesValue a, HasCallStack) => a -> App Value
make token
token
  String -> Request -> App Response
submit String
"POST" (Request -> App Response) -> Request -> App Response
forall a b. (a -> b) -> a -> b
$ Request
req Request -> (Request -> Request) -> Request
forall a b. a -> (a -> b) -> b
& Value -> Request -> Request
forall a. ToJSON a => a -> Request -> Request
addJSON Value
tokenJson

listPushTokens :: (MakesValue user) => user -> App Response
listPushTokens :: forall user. MakesValue user => user -> App Response
listPushTokens user
user = do
  Request
req <-
    user -> Service -> Versioned -> String -> App Request
forall user.
(HasCallStack, MakesValue user) =>
user -> Service -> Versioned -> String -> App Request
baseRequest user
user Service
Gundeck Versioned
Versioned
      (String -> App Request) -> String -> App Request
forall a b. (a -> b) -> a -> b
$ [String] -> String
joinHttpPath [String
"/push/tokens"]
  String -> Request -> App Response
submit String
"GET" Request
req

unregisterClient ::
  (MakesValue user, MakesValue client) =>
  user ->
  client ->
  App Response
unregisterClient :: forall user client.
(MakesValue user, MakesValue client) =>
user -> client -> App Response
unregisterClient user
user client
client = do
  String
cid <- client -> App String
forall a. (HasCallStack, MakesValue a) => a -> App String
asString client
client
  Request
req <-
    user -> Service -> Versioned -> String -> App Request
forall user.
(HasCallStack, MakesValue user) =>
user -> Service -> Versioned -> String -> App Request
baseRequest user
user Service
Gundeck Versioned
Unversioned
      (String -> App Request) -> String -> App Request
forall a b. (a -> b) -> a -> b
$ [String] -> String
joinHttpPath [String
"/i/clients", String
cid]
  String -> Request -> App Response
submit String
"DELETE" Request
req