    {-# 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
    $cshowsPrec :: Int -> Order -> ShowS
    showsPrec :: Int -> Order -> ShowS
    $cshow :: Order -> String
    show :: Order -> String
    $cshowList :: [Order] -> ShowS
    showList :: [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
    $cshowsPrec :: Int -> OrderStatus -> ShowS
    showsPrec :: Int -> OrderStatus -> ShowS
    $cshow :: OrderStatus -> String
    show :: OrderStatus -> String
    $cshowList :: [OrderStatus] -> ShowS
    showList :: [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
    $csucc :: OrderStatus -> OrderStatus
    succ :: OrderStatus -> OrderStatus
    $cpred :: OrderStatus -> OrderStatus
    pred :: OrderStatus -> OrderStatus
    $ctoEnum :: Int -> OrderStatus
    toEnum :: Int -> OrderStatus
    $cfromEnum :: OrderStatus -> Int
    fromEnum :: OrderStatus -> Int
    $cenumFrom :: OrderStatus -> [OrderStatus]
    enumFrom :: OrderStatus -> [OrderStatus]
    $cenumFromThen :: OrderStatus -> OrderStatus -> [OrderStatus]
    enumFromThen :: OrderStatus -> OrderStatus -> [OrderStatus]
    $cenumFromTo :: OrderStatus -> OrderStatus -> [OrderStatus]
    enumFromTo :: OrderStatus -> OrderStatus -> [OrderStatus]
    $cenumFromThenTo :: OrderStatus -> OrderStatus -> OrderStatus -> [OrderStatus]
    enumFromThenTo :: OrderStatus -> OrderStatus -> OrderStatus -> [OrderStatus]
    Enum, OrderStatus -> OrderStatus -> Bool
    (OrderStatus -> OrderStatus -> Bool)
    -> (OrderStatus -> OrderStatus -> Bool) -> Eq OrderStatus
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: OrderStatus -> OrderStatus -> Bool
    == :: OrderStatus -> OrderStatus -> Bool
    $c/= :: OrderStatus -> OrderStatus -> Bool
    /= :: 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
    $cshowsPrec :: Int -> OrderApplication -> ShowS
    showsPrec :: Int -> OrderApplication -> ShowS
    $cshow :: OrderApplication -> String
    show :: OrderApplication -> String
    $cshowList :: [OrderApplication] -> ShowS
    showList :: [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 a b. Parser (a -> b) -> Parser a -> Parser b
    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 a. Parser a
    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 a b. Parser (a -> b) -> Parser a -> Parser b
    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 a b. Parser (a -> b) -> Parser a -> Parser b
    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 a b. Parser (a -> b) -> Parser a -> Parser b
    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 a b. Parser (a -> b) -> Parser a -> Parser b
    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 a b. Parser (a -> b) -> Parser a -> Parser b
    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 a b. Parser (a -> b) -> Parser a -> Parser b
    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 a b. Parser (a -> b) -> Parser a -> Parser b
    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 a b. Parser (a -> b) -> Parser a -> Parser b
    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 a b. Parser (a -> b) -> Parser a -> Parser b
    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 a. Parser a
    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 a. a -> Parser a
    forall (m :: * -> *) a. Monad m => a -> m a
    return OrderStatus
    OrderPlaced
      parseJSON (A.String Text
    "settled") = OrderStatus -> Parser OrderStatus
    forall a. a -> Parser a
    forall (m :: * -> *) a. Monad m => a -> m a
    return OrderStatus
    OrderSettled
      parseJSON (A.String Text
    "refunded") = OrderStatus -> Parser OrderStatus
    forall a. a -> Parser a
    forall (m :: * -> *) a. Monad m => a -> m a
    return OrderStatus
    OrderRefunded
      parseJSON (A.String Text
    "disputed") = OrderStatus -> Parser OrderStatus
    forall a. a -> Parser a
    forall (m :: * -> *) a. Monad m => a -> m a
    return OrderStatus
    OrderDisputed
      parseJSON (A.String Text
    "cancelled") = OrderStatus -> Parser OrderStatus
    forall a. a -> Parser a
    forall (m :: * -> *) a. Monad m => a -> m a
    return OrderStatus
    OrderCancelled
      parseJSON Value
    _ = Parser OrderStatus
    forall a. Parser a
    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 :: forall (m :: * -> *) anyAuth.
    (MonadResource m, MonadUnliftIO m, MonadThrow m) =>
    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)