{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}

module Facebook.Object.Order
  ( Order(..)
  , OrderId
  , OrderStatus(..)
  , OrderApplication(..)
  , getOrder
  ) where

import Control.Monad (mzero)
import Data.Text (Text)
import Data.Aeson ((.:), (.:?))
import Data.Typeable (Typeable)
import Data.Time.LocalTime (ZonedTime)

import qualified Control.Monad.Trans.Resource as R
import qualified Data.Aeson as A

import Facebook.Types
import Facebook.Monad
import Facebook.Graph

-- | 'Order' Id type.
type OrderId = Id

-- | A Facebook @Order@ oject.
data Order = Order
  { Order -> OrderId
orderId :: OrderId
  , Order -> OrderId
orderFrom :: UserId
  , Order -> OrderId
orderTo :: UserId
  , Order -> Integer
orderAmount :: Integer
  , Order -> OrderStatus
orderStatus :: OrderStatus
  , Order -> OrderApplication
orderApplication :: OrderApplication
  , Order -> Text
orderCountry :: Text
  , Order -> Maybe Text
orderRefundCode :: Maybe Text
  , Order -> ZonedTime
orderCreatedTime :: ZonedTime
  , Order -> ZonedTime
orderUpdatedTime :: ZonedTime
  } deriving (Int -> Order -> ShowS
[Order] -> ShowS
Order -> String
(Int -> Order -> ShowS)
-> (Order -> String) -> ([Order] -> ShowS) -> Show Order
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Order] -> ShowS
$cshowList :: [Order] -> ShowS
show :: Order -> String
$cshow :: Order -> String
showsPrec :: Int -> Order -> ShowS
$cshowsPrec :: Int -> Order -> ShowS
Show, Typeable)

-- | A Facebook 'Order' status type.
data OrderStatus
  = OrderPlaced
  | OrderSettled
  | OrderRefunded
  | OrderDisputed
  | OrderCancelled
  deriving (Int -> OrderStatus -> ShowS
[OrderStatus] -> ShowS
OrderStatus -> String
(Int -> OrderStatus -> ShowS)
-> (OrderStatus -> String)
-> ([OrderStatus] -> ShowS)
-> Show OrderStatus
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [OrderStatus] -> ShowS
$cshowList :: [OrderStatus] -> ShowS
show :: OrderStatus -> String
$cshow :: OrderStatus -> String
showsPrec :: Int -> OrderStatus -> ShowS
$cshowsPrec :: Int -> OrderStatus -> ShowS
Show, Int -> OrderStatus
OrderStatus -> Int
OrderStatus -> [OrderStatus]
OrderStatus -> OrderStatus
OrderStatus -> OrderStatus -> [OrderStatus]
OrderStatus -> OrderStatus -> OrderStatus -> [OrderStatus]
(OrderStatus -> OrderStatus)
-> (OrderStatus -> OrderStatus)
-> (Int -> OrderStatus)
-> (OrderStatus -> Int)
-> (OrderStatus -> [OrderStatus])
-> (OrderStatus -> OrderStatus -> [OrderStatus])
-> (OrderStatus -> OrderStatus -> [OrderStatus])
-> (OrderStatus -> OrderStatus -> OrderStatus -> [OrderStatus])
-> Enum OrderStatus
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: OrderStatus -> OrderStatus -> OrderStatus -> [OrderStatus]
$cenumFromThenTo :: OrderStatus -> OrderStatus -> OrderStatus -> [OrderStatus]
enumFromTo :: OrderStatus -> OrderStatus -> [OrderStatus]
$cenumFromTo :: OrderStatus -> OrderStatus -> [OrderStatus]
enumFromThen :: OrderStatus -> OrderStatus -> [OrderStatus]
$cenumFromThen :: OrderStatus -> OrderStatus -> [OrderStatus]
enumFrom :: OrderStatus -> [OrderStatus]
$cenumFrom :: OrderStatus -> [OrderStatus]
fromEnum :: OrderStatus -> Int
$cfromEnum :: OrderStatus -> Int
toEnum :: Int -> OrderStatus
$ctoEnum :: Int -> OrderStatus
pred :: OrderStatus -> OrderStatus
$cpred :: OrderStatus -> OrderStatus
succ :: OrderStatus -> OrderStatus
$csucc :: OrderStatus -> OrderStatus
Enum, OrderStatus -> OrderStatus -> Bool
(OrderStatus -> OrderStatus -> Bool)
-> (OrderStatus -> OrderStatus -> Bool) -> Eq OrderStatus
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: OrderStatus -> OrderStatus -> Bool
$c/= :: OrderStatus -> OrderStatus -> Bool
== :: OrderStatus -> OrderStatus -> Bool
$c== :: OrderStatus -> OrderStatus -> Bool
Eq, Typeable)

-- | A trimmed down version of Facebook Application as it is used in 'Order'.
data OrderApplication = OrderApplication
  { OrderApplication -> Text
appId :: Text
  , OrderApplication -> Text
appName :: Text
  } deriving (Int -> OrderApplication -> ShowS
[OrderApplication] -> ShowS
OrderApplication -> String
(Int -> OrderApplication -> ShowS)
-> (OrderApplication -> String)
-> ([OrderApplication] -> ShowS)
-> Show OrderApplication
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [OrderApplication] -> ShowS
$cshowList :: [OrderApplication] -> ShowS
show :: OrderApplication -> String
$cshow :: OrderApplication -> String
showsPrec :: Int -> OrderApplication -> ShowS
$cshowsPrec :: Int -> OrderApplication -> ShowS
Show, Typeable)

instance A.FromJSON OrderApplication where
  parseJSON :: Value -> Parser OrderApplication
parseJSON (A.Object Object
v) = Text -> Text -> OrderApplication
OrderApplication (Text -> Text -> OrderApplication)
-> Parser Text -> Parser (Text -> OrderApplication)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v Object -> Key -> Parser Text
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"id" Parser (Text -> OrderApplication)
-> Parser Text -> Parser OrderApplication
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser Text
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"name"
  parseJSON Value
_ = Parser OrderApplication
forall (m :: * -> *) a. MonadPlus m => m a
mzero

instance A.FromJSON Order where
  parseJSON :: Value -> Parser Order
parseJSON (A.Object Object
v) =
    OrderId
-> OrderId
-> OrderId
-> Integer
-> OrderStatus
-> OrderApplication
-> Text
-> Maybe Text
-> ZonedTime
-> ZonedTime
-> Order
Order (OrderId
 -> OrderId
 -> OrderId
 -> Integer
 -> OrderStatus
 -> OrderApplication
 -> Text
 -> Maybe Text
 -> ZonedTime
 -> ZonedTime
 -> Order)
-> Parser OrderId
-> Parser
     (OrderId
      -> OrderId
      -> Integer
      -> OrderStatus
      -> OrderApplication
      -> Text
      -> Maybe Text
      -> ZonedTime
      -> ZonedTime
      -> Order)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v Object -> Key -> Parser OrderId
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"id" Parser
  (OrderId
   -> OrderId
   -> Integer
   -> OrderStatus
   -> OrderApplication
   -> Text
   -> Maybe Text
   -> ZonedTime
   -> ZonedTime
   -> Order)
-> Parser OrderId
-> Parser
     (OrderId
      -> Integer
      -> OrderStatus
      -> OrderApplication
      -> Text
      -> Maybe Text
      -> ZonedTime
      -> ZonedTime
      -> Order)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser OrderId
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"from" Parser
  (OrderId
   -> Integer
   -> OrderStatus
   -> OrderApplication
   -> Text
   -> Maybe Text
   -> ZonedTime
   -> ZonedTime
   -> Order)
-> Parser OrderId
-> Parser
     (Integer
      -> OrderStatus
      -> OrderApplication
      -> Text
      -> Maybe Text
      -> ZonedTime
      -> ZonedTime
      -> Order)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser OrderId
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"to" Parser
  (Integer
   -> OrderStatus
   -> OrderApplication
   -> Text
   -> Maybe Text
   -> ZonedTime
   -> ZonedTime
   -> Order)
-> Parser Integer
-> Parser
     (OrderStatus
      -> OrderApplication
      -> Text
      -> Maybe Text
      -> ZonedTime
      -> ZonedTime
      -> Order)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser Integer
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"amount" Parser
  (OrderStatus
   -> OrderApplication
   -> Text
   -> Maybe Text
   -> ZonedTime
   -> ZonedTime
   -> Order)
-> Parser OrderStatus
-> Parser
     (OrderApplication
      -> Text -> Maybe Text -> ZonedTime -> ZonedTime -> Order)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*>
    Object
v Object -> Key -> Parser OrderStatus
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"status" Parser
  (OrderApplication
   -> Text -> Maybe Text -> ZonedTime -> ZonedTime -> Order)
-> Parser OrderApplication
-> Parser (Text -> Maybe Text -> ZonedTime -> ZonedTime -> Order)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*>
    Object
v Object -> Key -> Parser OrderApplication
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"application" Parser (Text -> Maybe Text -> ZonedTime -> ZonedTime -> Order)
-> Parser Text
-> Parser (Maybe Text -> ZonedTime -> ZonedTime -> Order)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*>
    Object
v Object -> Key -> Parser Text
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"country" Parser (Maybe Text -> ZonedTime -> ZonedTime -> Order)
-> Parser (Maybe Text) -> Parser (ZonedTime -> ZonedTime -> Order)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*>
    Object
v Object -> Key -> Parser (Maybe Text)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"refund_reason_code" Parser (ZonedTime -> ZonedTime -> Order)
-> Parser ZonedTime -> Parser (ZonedTime -> Order)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*>
    Object
v Object -> Key -> Parser ZonedTime
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"created_time" Parser (ZonedTime -> Order) -> Parser ZonedTime -> Parser Order
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*>
    Object
v Object -> Key -> Parser ZonedTime
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"updated_time"
  parseJSON Value
_ = Parser Order
forall (m :: * -> *) a. MonadPlus m => m a
mzero

instance A.FromJSON OrderStatus where
  parseJSON :: Value -> Parser OrderStatus
parseJSON (A.String Text
"placed") = OrderStatus -> Parser OrderStatus
forall (m :: * -> *) a. Monad m => a -> m a
return OrderStatus
OrderPlaced
  parseJSON (A.String Text
"settled") = OrderStatus -> Parser OrderStatus
forall (m :: * -> *) a. Monad m => a -> m a
return OrderStatus
OrderSettled
  parseJSON (A.String Text
"refunded") = OrderStatus -> Parser OrderStatus
forall (m :: * -> *) a. Monad m => a -> m a
return OrderStatus
OrderRefunded
  parseJSON (A.String Text
"disputed") = OrderStatus -> Parser OrderStatus
forall (m :: * -> *) a. Monad m => a -> m a
return OrderStatus
OrderDisputed
  parseJSON (A.String Text
"cancelled") = OrderStatus -> Parser OrderStatus
forall (m :: * -> *) a. Monad m => a -> m a
return OrderStatus
OrderCancelled
  parseJSON Value
_ = Parser OrderStatus
forall (m :: * -> *) a. MonadPlus m => m a
mzero

-- | Get an 'Order' using its 'OrderId'.  The user access token
-- is mandatory.
getOrder
  :: (R.MonadResource m, R.MonadUnliftIO m, R.MonadThrow m)
  => OrderId -- ^ Order ID.
  -> UserAccessToken -- ^ User access token.
  -> FacebookT anyAuth m Order
getOrder :: OrderId -> UserAccessToken -> FacebookT anyAuth m Order
getOrder OrderId
id_ UserAccessToken
mtoken = Text
-> [Argument] -> Maybe UserAccessToken -> FacebookT anyAuth m Order
forall (m :: * -> *) a anyKind anyAuth.
(MonadResource m, MonadUnliftIO m, MonadThrow m, FromJSON a) =>
Text
-> [Argument]
-> Maybe (AccessToken anyKind)
-> FacebookT anyAuth m a
getObject (Text
"/" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> OrderId -> Text
idCode OrderId
id_) [] (UserAccessToken -> Maybe UserAccessToken
forall a. a -> Maybe a
Just UserAccessToken
mtoken)