{-# LANGUAGE GADTs #-}
{-# LANGUAGE FlexibleContexts #-}
module MixPanel.Types.EngageData
  ( EngageData(..)
  , DistinctId
  , mkEngageData
  , Operation(..)
  ) where

import           Data.Text                      ( Text )
import           Data.Aeson                     ( ToJSON
                                                , toJSON
                                                , Object
                                                , Value(..)
                                                , Array
                                                , encode
                                                , (.=)
                                                )
import qualified Data.ByteString.Base64.Lazy   as B64
import           Data.String.Conv               ( toS )
import           GHC.Exts                       ( fromList )
import           Servant.API

import           MixPanel.Types.Core            ( AuthToken )


data Operation where
  Set :: Object -> Operation
  SetOnce :: Object -> Operation
  Add :: Object -> Operation
  Append :: Object -> Operation
  Union :: Object -> Operation
  Remove :: Object -> Operation
  Unset :: Array -> Operation
  Delete :: Operation

instance ToJSON Operation where
  toJSON :: Operation -> Value
toJSON (Set Object
obj) = Object -> Value
Object Object
obj
  toJSON (SetOnce Object
obj) = Object -> Value
Object Object
obj
  toJSON (Add Object
obj) = Object -> Value
Object Object
obj
  toJSON (Append Object
obj) = Object -> Value
Object Object
obj
  toJSON (Union Object
obj) = Object -> Value
Object Object
obj
  toJSON (Remove Object
obj) = Object -> Value
Object Object
obj
  toJSON (Unset Array
obj) = Array -> Value
Array Array
obj
  toJSON Operation
Delete = Value
""

operationIdentifier :: Operation -> Text
operationIdentifier :: Operation -> Text
operationIdentifier (Set Object
_) = Text
"$set"
operationIdentifier (SetOnce Object
_) = Text
"$set_once"
operationIdentifier (Add Object
_) = Text
"$add"
operationIdentifier (Append Object
_) = Text
"$append"
operationIdentifier (Union Object
_) = Text
"$union"
operationIdentifier (Remove Object
_) = Text
"$remove"
operationIdentifier (Unset Array
_) = Text
"$unset"
operationIdentifier Operation
Delete = Text
"$delete"

type DistinctId = Text

data EngageData = EngageData
  { EngageData -> AuthToken
token :: AuthToken
  , EngageData -> Text
distinctId :: DistinctId
  , EngageData -> Maybe Text
ip :: Maybe Text
  , EngageData -> Maybe Text
time :: Maybe Text
  , EngageData -> Maybe Bool
ignoreTime :: Maybe Bool
  , EngageData -> Operation
operation :: Operation
  }

instance ToJSON EngageData where
  toJSON :: EngageData -> Value
toJSON EngageData{Maybe Bool
Maybe Text
Text
AuthToken
Operation
operation :: Operation
ignoreTime :: Maybe Bool
time :: Maybe Text
ip :: Maybe Text
distinctId :: Text
token :: AuthToken
operation :: EngageData -> Operation
ignoreTime :: EngageData -> Maybe Bool
time :: EngageData -> Maybe Text
ip :: EngageData -> Maybe Text
distinctId :: EngageData -> Text
token :: EngageData -> AuthToken
..} = Object -> Value
Object (Object -> Value) -> Object -> Value
forall a b. (a -> b) -> a -> b
$ [Item Object] -> Object
forall l. IsList l => [Item l] -> l
fromList
    [ Text
"$token" Text -> AuthToken -> (Text, Value)
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= AuthToken
token
    , Text
"$distinct_id" Text -> Text -> (Text, Value)
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
distinctId
    , Text
"$time" Text -> Maybe Text -> (Text, Value)
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Maybe Text
time
    , Text
"$ignore_time" Text -> Maybe Bool -> (Text, Value)
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Maybe Bool
ignoreTime
    , Text
"$ip" Text -> Maybe Text -> (Text, Value)
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Maybe Text
ip
    , Operation -> Text
operationIdentifier Operation
operation Text -> Value -> (Text, Value)
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Operation -> Value
forall a. ToJSON a => a -> Value
toJSON Operation
operation
    ]

instance ToHttpApiData EngageData where
  toUrlPiece :: EngageData -> Text
toUrlPiece = ByteString -> Text
forall a b. StringConv a b => a -> b
toS (ByteString -> Text)
-> (EngageData -> ByteString) -> EngageData -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
B64.encode (ByteString -> ByteString)
-> (EngageData -> ByteString) -> EngageData -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EngageData -> ByteString
forall a. ToJSON a => a -> ByteString
encode

mkEngageData :: AuthToken -> DistinctId -> Operation -> EngageData
mkEngageData :: AuthToken -> Text -> Operation -> EngageData
mkEngageData AuthToken
token Text
di Operation
op = EngageData :: AuthToken
-> Text
-> Maybe Text
-> Maybe Text
-> Maybe Bool
-> Operation
-> EngageData
EngageData
  { token :: AuthToken
token = AuthToken
token
  , distinctId :: Text
distinctId = Text
di
  , ip :: Maybe Text
ip = Maybe Text
forall a. Maybe a
Nothing
  , time :: Maybe Text
time = Maybe Text
forall a. Maybe a
Nothing
  , ignoreTime :: Maybe Bool
ignoreTime = Maybe Bool
forall a. Maybe a
Nothing
  , operation :: Operation
operation = Operation
op
  }