{-# LANGUAGE CPP #-}
module MixPanel
  ( MixPanelError(..)
  , AuthToken(..)
  , Operation(..)
  , DistinctId
  -- Setup
  , mkEnv
  , Env
  -- mixpanel api calls
  , track
  , alias
  , engage
  , engage'
  -- HTTP manager reexports
  , tlsManagerSettings
  , HTTP.newManager
  ) where

import           Control.Exception              ( Exception )
import           Data.Aeson                     ( Object, (.=) )
import           Data.Text                      ( Text )
import           GHC.Exts                       ( fromList )
import qualified Network.HTTP.Client           as HTTP
import           Network.HTTP.Client.TLS        ( tlsManagerSettings )
import           Servant.API             hiding ( URI )
import           Servant.Client

import           MixPanel.API                   ( api )
import           MixPanel.Types.Core            ( DidSucceed(..)
                                                , Toggle(..)
                                                , AuthToken(..)
                                                )
import           MixPanel.Types.TrackData       ( TrackData(..)
                                                , mkProperties
                                                )
import           MixPanel.Types.EngageData      ( EngageData, DistinctId, Operation(..), mkEngageData )

#if !MIN_VERSION_servant_client(0,16,0)
#define ClientError ServantError
#endif

host :: BaseUrl
host :: BaseUrl
host = Scheme -> String -> Int -> String -> BaseUrl
BaseUrl Scheme
Https String
"api.mixpanel.com" Int
443 String
""

data MixPanelError
  = ClientError ClientError
  | Error Text
  deriving (Int -> MixPanelError -> ShowS
[MixPanelError] -> ShowS
MixPanelError -> String
(Int -> MixPanelError -> ShowS)
-> (MixPanelError -> String)
-> ([MixPanelError] -> ShowS)
-> Show MixPanelError
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MixPanelError] -> ShowS
$cshowList :: [MixPanelError] -> ShowS
show :: MixPanelError -> String
$cshow :: MixPanelError -> String
showsPrec :: Int -> MixPanelError -> ShowS
$cshowsPrec :: Int -> MixPanelError -> ShowS
Show, Show MixPanelError
Typeable MixPanelError
Typeable MixPanelError
-> Show MixPanelError
-> (MixPanelError -> SomeException)
-> (SomeException -> Maybe MixPanelError)
-> (MixPanelError -> String)
-> Exception MixPanelError
SomeException -> Maybe MixPanelError
MixPanelError -> String
MixPanelError -> SomeException
forall e.
Typeable e
-> Show e
-> (e -> SomeException)
-> (SomeException -> Maybe e)
-> (e -> String)
-> Exception e
displayException :: MixPanelError -> String
$cdisplayException :: MixPanelError -> String
fromException :: SomeException -> Maybe MixPanelError
$cfromException :: SomeException -> Maybe MixPanelError
toException :: MixPanelError -> SomeException
$ctoException :: MixPanelError -> SomeException
$cp2Exception :: Show MixPanelError
$cp1Exception :: Typeable MixPanelError
Exception)

data Env = Env
  { Env -> AuthToken
authtoken :: AuthToken
  , Env -> Manager
httpManager :: HTTP.Manager
  , Env -> ClientEnv
clientEnv :: ClientEnv
  }

mkEnv :: AuthToken -> HTTP.Manager -> Env
mkEnv :: AuthToken -> Manager -> Env
mkEnv AuthToken
authtoken Manager
httpManager = Env :: AuthToken -> Manager -> ClientEnv -> Env
Env {Manager
ClientEnv
AuthToken
clientEnv :: ClientEnv
httpManager :: Manager
authtoken :: AuthToken
clientEnv :: ClientEnv
httpManager :: Manager
authtoken :: AuthToken
..}
  where
    clientEnv :: ClientEnv
clientEnv = Manager -> BaseUrl -> ClientEnv
mkClientEnv Manager
httpManager BaseUrl
host



trackC :: TrackData -> Maybe Toggle -> Maybe Text -> Maybe Toggle -> Maybe Text -> Maybe Toggle -> ClientM DidSucceed
engageC :: EngageData -> Maybe Text -> Maybe Text -> Maybe Toggle -> ClientM DidSucceed
TrackData
-> Maybe Toggle
-> Maybe Text
-> Maybe Toggle
-> Maybe Text
-> Maybe Toggle
-> ClientM DidSucceed
trackC :<|> EngageData
-> Maybe Text -> Maybe Text -> Maybe Toggle -> ClientM DidSucceed
engageC = Proxy API -> Client ClientM API
forall api.
HasClient ClientM api =>
Proxy api -> Client ClientM api
client Proxy API
api

trackC' :: TrackData -> ClientM DidSucceed
trackC' :: TrackData -> ClientM DidSucceed
trackC' TrackData
trackdata = TrackData
-> Maybe Toggle
-> Maybe Text
-> Maybe Toggle
-> Maybe Text
-> Maybe Toggle
-> ClientM DidSucceed
trackC TrackData
trackdata Maybe Toggle
forall a. Maybe a
Nothing Maybe Text
forall a. Maybe a
Nothing Maybe Toggle
forall a. Maybe a
Nothing Maybe Text
forall a. Maybe a
Nothing (Toggle -> Maybe Toggle
forall a. a -> Maybe a
Just Toggle
On)

engageC' :: EngageData -> ClientM DidSucceed
engageC' :: EngageData -> ClientM DidSucceed
engageC' EngageData
engagedata =
  EngageData
-> Maybe Text -> Maybe Text -> Maybe Toggle -> ClientM DidSucceed
engageC EngageData
engagedata Maybe Text
forall a. Maybe a
Nothing Maybe Text
forall a. Maybe a
Nothing (Toggle -> Maybe Toggle
forall a. a -> Maybe a
Just Toggle
On)

runMixPanel :: ClientEnv -> ClientM DidSucceed -> IO (Either MixPanelError ())
runMixPanel :: ClientEnv -> ClientM DidSucceed -> IO (Either MixPanelError ())
runMixPanel ClientEnv
clientEnv ClientM DidSucceed
comp = do
  Either ClientError DidSucceed
result <- ClientM DidSucceed
-> ClientEnv -> IO (Either ClientError DidSucceed)
forall a. ClientM a -> ClientEnv -> IO (Either ClientError a)
runClientM ClientM DidSucceed
comp ClientEnv
clientEnv
  Either MixPanelError () -> IO (Either MixPanelError ())
forall (m :: * -> *) a. Monad m => a -> m a
return (Either MixPanelError () -> IO (Either MixPanelError ()))
-> Either MixPanelError () -> IO (Either MixPanelError ())
forall a b. (a -> b) -> a -> b
$ case Either ClientError DidSucceed
result of
    Left ClientError
err -> MixPanelError -> Either MixPanelError ()
forall a b. a -> Either a b
Left (MixPanelError -> Either MixPanelError ())
-> MixPanelError -> Either MixPanelError ()
forall a b. (a -> b) -> a -> b
$ ClientError -> MixPanelError
ClientError ClientError
err
    Right (Fail Text
err) -> MixPanelError -> Either MixPanelError ()
forall a b. a -> Either a b
Left (MixPanelError -> Either MixPanelError ())
-> MixPanelError -> Either MixPanelError ()
forall a b. (a -> b) -> a -> b
$ Text -> MixPanelError
Error Text
err
    Right DidSucceed
Success -> () -> Either MixPanelError ()
forall a b. b -> Either a b
Right ()

track :: Env -> Text -> Object -> IO (Either MixPanelError ())
track :: Env -> Text -> Object -> IO (Either MixPanelError ())
track Env{Manager
ClientEnv
AuthToken
clientEnv :: ClientEnv
httpManager :: Manager
authtoken :: AuthToken
clientEnv :: Env -> ClientEnv
httpManager :: Env -> Manager
authtoken :: Env -> AuthToken
..} Text
event Object
props =
  ClientEnv -> ClientM DidSucceed -> IO (Either MixPanelError ())
runMixPanel ClientEnv
clientEnv (ClientM DidSucceed -> IO (Either MixPanelError ()))
-> ClientM DidSucceed -> IO (Either MixPanelError ())
forall a b. (a -> b) -> a -> b
$ TrackData -> ClientM DidSucceed
trackC' (TrackData -> ClientM DidSucceed)
-> TrackData -> ClientM DidSucceed
forall a b. (a -> b) -> a -> b
$ Text -> Properties -> TrackData
TrackData Text
event (Properties -> TrackData) -> Properties -> TrackData
forall a b. (a -> b) -> a -> b
$ AuthToken -> Object -> Properties
mkProperties AuthToken
authtoken Object
props

-- | Renames distinct id into alias id
alias :: Env -> DistinctId -> Text -> IO (Either MixPanelError ())
alias :: Env -> Text -> Text -> IO (Either MixPanelError ())
alias Env{Manager
ClientEnv
AuthToken
clientEnv :: ClientEnv
httpManager :: Manager
authtoken :: AuthToken
clientEnv :: Env -> ClientEnv
httpManager :: Env -> Manager
authtoken :: Env -> AuthToken
..} Text
distinctId Text
aliasId =
   ClientEnv -> ClientM DidSucceed -> IO (Either MixPanelError ())
runMixPanel ClientEnv
clientEnv (ClientM DidSucceed -> IO (Either MixPanelError ()))
-> ClientM DidSucceed -> IO (Either MixPanelError ())
forall a b. (a -> b) -> a -> b
$ TrackData -> ClientM DidSucceed
trackC' (TrackData -> ClientM DidSucceed)
-> TrackData -> ClientM DidSucceed
forall a b. (a -> b) -> a -> b
$ Text -> Properties -> TrackData
TrackData Text
"$create_alias" (Properties -> TrackData) -> Properties -> TrackData
forall a b. (a -> b) -> a -> b
$ AuthToken -> Object -> Properties
mkProperties AuthToken
authtoken Object
props
    where
      props :: Object
      props :: Object
props = [Item Object] -> Object
forall l. IsList l => [Item l] -> l
fromList [ Text
"alias" Text -> Text -> (Text, Value)
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
aliasId
                       , Text
"distinct_id" Text -> Text -> (Text, Value)
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
distinctId]

engage :: Env -> DistinctId -> Operation -> IO (Either MixPanelError ())
engage :: Env -> Text -> Operation -> IO (Either MixPanelError ())
engage Env{Manager
ClientEnv
AuthToken
clientEnv :: ClientEnv
httpManager :: Manager
authtoken :: AuthToken
clientEnv :: Env -> ClientEnv
httpManager :: Env -> Manager
authtoken :: Env -> AuthToken
..} Text
distinctid Operation
operation =
  ClientEnv -> ClientM DidSucceed -> IO (Either MixPanelError ())
runMixPanel ClientEnv
clientEnv (ClientM DidSucceed -> IO (Either MixPanelError ()))
-> ClientM DidSucceed -> IO (Either MixPanelError ())
forall a b. (a -> b) -> a -> b
$ EngageData -> ClientM DidSucceed
engageC' (EngageData -> ClientM DidSucceed)
-> EngageData -> ClientM DidSucceed
forall a b. (a -> b) -> a -> b
$ AuthToken -> Text -> Operation -> EngageData
mkEngageData AuthToken
authtoken Text
distinctid Operation
operation

engage' :: Env -> DistinctId -> (EngageData -> EngageData) -> Operation -> IO (Either MixPanelError ())
engage' :: Env
-> Text
-> (EngageData -> EngageData)
-> Operation
-> IO (Either MixPanelError ())
engage' Env{Manager
ClientEnv
AuthToken
clientEnv :: ClientEnv
httpManager :: Manager
authtoken :: AuthToken
clientEnv :: Env -> ClientEnv
httpManager :: Env -> Manager
authtoken :: Env -> AuthToken
..} Text
distinctid EngageData -> EngageData
f Operation
operation =
  ClientEnv -> ClientM DidSucceed -> IO (Either MixPanelError ())
runMixPanel ClientEnv
clientEnv (ClientM DidSucceed -> IO (Either MixPanelError ()))
-> ClientM DidSucceed -> IO (Either MixPanelError ())
forall a b. (a -> b) -> a -> b
$ EngageData -> ClientM DidSucceed
engageC' (EngageData -> ClientM DidSucceed)
-> EngageData -> ClientM DidSucceed
forall a b. (a -> b) -> a -> b
$ EngageData -> EngageData
f (EngageData -> EngageData) -> EngageData -> EngageData
forall a b. (a -> b) -> a -> b
$ AuthToken -> Text -> Operation -> EngageData
mkEngageData AuthToken
authtoken Text
distinctid Operation
operation