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

module Facebook.Object.Checkin
  ( Checkin(..)
  , CheckinFrom(..)
  , getCheckin
  , createCheckin
  ) where
#if __GLASGOW_HASKELL__ <= 784
import Control.Applicative
#endif
import Control.Monad (mzero)
import Data.Aeson ((.:), (.:?))
import Data.Text (Text)
import Data.Time (UTCTime)
import Data.Typeable (Typeable)

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

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

-- | A Facebook check-in (see
-- <https://developers.facebook.com/docs/reference/api/checkin/>).
--
-- /NOTE:/ We still don't support all fields supported by
-- Facebook. Please fill an issue if you need access to any other
-- fields.
data Checkin = Checkin
  { Checkin -> Id
checkinId :: Id
  , Checkin -> Maybe CheckinFrom
checkinFrom :: Maybe CheckinFrom
  , Checkin -> Maybe Place
checkinPlace :: Maybe Place
  , Checkin -> Maybe UTCTime
checkinCreatedTime :: Maybe UTCTime
  , Checkin -> Maybe (Pager Tag)
checkinTags :: Maybe (Pager Tag)
  , Checkin -> Maybe Text
checkinMessage :: Maybe Text
  } deriving (Checkin -> Checkin -> Bool
(Checkin -> Checkin -> Bool)
-> (Checkin -> Checkin -> Bool) -> Eq Checkin
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Checkin -> Checkin -> Bool
$c/= :: Checkin -> Checkin -> Bool
== :: Checkin -> Checkin -> Bool
$c== :: Checkin -> Checkin -> Bool
Eq, Eq Checkin
Eq Checkin
-> (Checkin -> Checkin -> Ordering)
-> (Checkin -> Checkin -> Bool)
-> (Checkin -> Checkin -> Bool)
-> (Checkin -> Checkin -> Bool)
-> (Checkin -> Checkin -> Bool)
-> (Checkin -> Checkin -> Checkin)
-> (Checkin -> Checkin -> Checkin)
-> Ord Checkin
Checkin -> Checkin -> Bool
Checkin -> Checkin -> Ordering
Checkin -> Checkin -> Checkin
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Checkin -> Checkin -> Checkin
$cmin :: Checkin -> Checkin -> Checkin
max :: Checkin -> Checkin -> Checkin
$cmax :: Checkin -> Checkin -> Checkin
>= :: Checkin -> Checkin -> Bool
$c>= :: Checkin -> Checkin -> Bool
> :: Checkin -> Checkin -> Bool
$c> :: Checkin -> Checkin -> Bool
<= :: Checkin -> Checkin -> Bool
$c<= :: Checkin -> Checkin -> Bool
< :: Checkin -> Checkin -> Bool
$c< :: Checkin -> Checkin -> Bool
compare :: Checkin -> Checkin -> Ordering
$ccompare :: Checkin -> Checkin -> Ordering
$cp1Ord :: Eq Checkin
Ord, Int -> Checkin -> ShowS
[Checkin] -> ShowS
Checkin -> String
(Int -> Checkin -> ShowS)
-> (Checkin -> String) -> ([Checkin] -> ShowS) -> Show Checkin
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Checkin] -> ShowS
$cshowList :: [Checkin] -> ShowS
show :: Checkin -> String
$cshow :: Checkin -> String
showsPrec :: Int -> Checkin -> ShowS
$cshowsPrec :: Int -> Checkin -> ShowS
Show, ReadPrec [Checkin]
ReadPrec Checkin
Int -> ReadS Checkin
ReadS [Checkin]
(Int -> ReadS Checkin)
-> ReadS [Checkin]
-> ReadPrec Checkin
-> ReadPrec [Checkin]
-> Read Checkin
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Checkin]
$creadListPrec :: ReadPrec [Checkin]
readPrec :: ReadPrec Checkin
$creadPrec :: ReadPrec Checkin
readList :: ReadS [Checkin]
$creadList :: ReadS [Checkin]
readsPrec :: Int -> ReadS Checkin
$creadsPrec :: Int -> ReadS Checkin
Read, Typeable)

instance A.FromJSON Checkin where
  parseJSON :: Value -> Parser Checkin
parseJSON (A.Object Object
v) =
    Id
-> Maybe CheckinFrom
-> Maybe Place
-> Maybe UTCTime
-> Maybe (Pager Tag)
-> Maybe Text
-> Checkin
Checkin (Id
 -> Maybe CheckinFrom
 -> Maybe Place
 -> Maybe UTCTime
 -> Maybe (Pager Tag)
 -> Maybe Text
 -> Checkin)
-> Parser Id
-> Parser
     (Maybe CheckinFrom
      -> Maybe Place
      -> Maybe UTCTime
      -> Maybe (Pager Tag)
      -> Maybe Text
      -> Checkin)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v Object -> Key -> Parser Id
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"id" Parser
  (Maybe CheckinFrom
   -> Maybe Place
   -> Maybe UTCTime
   -> Maybe (Pager Tag)
   -> Maybe Text
   -> Checkin)
-> Parser (Maybe CheckinFrom)
-> Parser
     (Maybe Place
      -> Maybe UTCTime -> Maybe (Pager Tag) -> Maybe Text -> Checkin)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser (Maybe CheckinFrom)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"from" Parser
  (Maybe Place
   -> Maybe UTCTime -> Maybe (Pager Tag) -> Maybe Text -> Checkin)
-> Parser (Maybe Place)
-> Parser
     (Maybe UTCTime -> Maybe (Pager Tag) -> Maybe Text -> Checkin)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser (Maybe Place)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"place" Parser
  (Maybe UTCTime -> Maybe (Pager Tag) -> Maybe Text -> Checkin)
-> Parser (Maybe UTCTime)
-> Parser (Maybe (Pager Tag) -> Maybe Text -> Checkin)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*>
    ((FbUTCTime -> UTCTime
unFbUTCTime (FbUTCTime -> UTCTime) -> Maybe FbUTCTime -> Maybe UTCTime
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>) (Maybe FbUTCTime -> Maybe UTCTime)
-> Parser (Maybe FbUTCTime) -> Parser (Maybe UTCTime)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v Object -> Key -> Parser (Maybe FbUTCTime)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"created_time") Parser (Maybe (Pager Tag) -> Maybe Text -> Checkin)
-> Parser (Maybe (Pager Tag)) -> Parser (Maybe Text -> Checkin)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*>
    Object
v Object -> Key -> Parser (Maybe (Pager Tag))
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"tags" Parser (Maybe Text -> Checkin)
-> Parser (Maybe Text) -> Parser Checkin
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
"message"
  parseJSON Value
_ = Parser Checkin
forall (m :: * -> *) a. MonadPlus m => m a
mzero

-- | Information about the user who made the check-in.
data CheckinFrom = CheckinFrom
  { CheckinFrom -> Id
checkinFromId :: UserId
  , CheckinFrom -> Text
checkinFromName :: Text
  } deriving (CheckinFrom -> CheckinFrom -> Bool
(CheckinFrom -> CheckinFrom -> Bool)
-> (CheckinFrom -> CheckinFrom -> Bool) -> Eq CheckinFrom
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CheckinFrom -> CheckinFrom -> Bool
$c/= :: CheckinFrom -> CheckinFrom -> Bool
== :: CheckinFrom -> CheckinFrom -> Bool
$c== :: CheckinFrom -> CheckinFrom -> Bool
Eq, Eq CheckinFrom
Eq CheckinFrom
-> (CheckinFrom -> CheckinFrom -> Ordering)
-> (CheckinFrom -> CheckinFrom -> Bool)
-> (CheckinFrom -> CheckinFrom -> Bool)
-> (CheckinFrom -> CheckinFrom -> Bool)
-> (CheckinFrom -> CheckinFrom -> Bool)
-> (CheckinFrom -> CheckinFrom -> CheckinFrom)
-> (CheckinFrom -> CheckinFrom -> CheckinFrom)
-> Ord CheckinFrom
CheckinFrom -> CheckinFrom -> Bool
CheckinFrom -> CheckinFrom -> Ordering
CheckinFrom -> CheckinFrom -> CheckinFrom
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: CheckinFrom -> CheckinFrom -> CheckinFrom
$cmin :: CheckinFrom -> CheckinFrom -> CheckinFrom
max :: CheckinFrom -> CheckinFrom -> CheckinFrom
$cmax :: CheckinFrom -> CheckinFrom -> CheckinFrom
>= :: CheckinFrom -> CheckinFrom -> Bool
$c>= :: CheckinFrom -> CheckinFrom -> Bool
> :: CheckinFrom -> CheckinFrom -> Bool
$c> :: CheckinFrom -> CheckinFrom -> Bool
<= :: CheckinFrom -> CheckinFrom -> Bool
$c<= :: CheckinFrom -> CheckinFrom -> Bool
< :: CheckinFrom -> CheckinFrom -> Bool
$c< :: CheckinFrom -> CheckinFrom -> Bool
compare :: CheckinFrom -> CheckinFrom -> Ordering
$ccompare :: CheckinFrom -> CheckinFrom -> Ordering
$cp1Ord :: Eq CheckinFrom
Ord, Int -> CheckinFrom -> ShowS
[CheckinFrom] -> ShowS
CheckinFrom -> String
(Int -> CheckinFrom -> ShowS)
-> (CheckinFrom -> String)
-> ([CheckinFrom] -> ShowS)
-> Show CheckinFrom
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CheckinFrom] -> ShowS
$cshowList :: [CheckinFrom] -> ShowS
show :: CheckinFrom -> String
$cshow :: CheckinFrom -> String
showsPrec :: Int -> CheckinFrom -> ShowS
$cshowsPrec :: Int -> CheckinFrom -> ShowS
Show, ReadPrec [CheckinFrom]
ReadPrec CheckinFrom
Int -> ReadS CheckinFrom
ReadS [CheckinFrom]
(Int -> ReadS CheckinFrom)
-> ReadS [CheckinFrom]
-> ReadPrec CheckinFrom
-> ReadPrec [CheckinFrom]
-> Read CheckinFrom
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [CheckinFrom]
$creadListPrec :: ReadPrec [CheckinFrom]
readPrec :: ReadPrec CheckinFrom
$creadPrec :: ReadPrec CheckinFrom
readList :: ReadS [CheckinFrom]
$creadList :: ReadS [CheckinFrom]
readsPrec :: Int -> ReadS CheckinFrom
$creadsPrec :: Int -> ReadS CheckinFrom
Read, Typeable)

instance A.FromJSON CheckinFrom where
  parseJSON :: Value -> Parser CheckinFrom
parseJSON (A.Object Object
v) = Id -> Text -> CheckinFrom
CheckinFrom (Id -> Text -> CheckinFrom)
-> Parser Id -> Parser (Text -> CheckinFrom)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v Object -> Key -> Parser Id
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"id" Parser (Text -> CheckinFrom) -> Parser Text -> Parser CheckinFrom
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 CheckinFrom
forall (m :: * -> *) a. MonadPlus m => m a
mzero

-- | Get a checkin from its ID.  The user access token is
-- optional, but when provided more information can be returned
-- back by Facebook.
getCheckin
  :: (R.MonadResource m, R.MonadUnliftIO m, R.MonadThrow m)
  => Id -- ^ Checkin ID.
  -> [Argument] -- ^ Arguments to be passed to Facebook.
  -> Maybe UserAccessToken -- ^ Optional user access token.
  -> FacebookT anyAuth m Checkin
getCheckin :: Id
-> [Argument]
-> Maybe UserAccessToken
-> FacebookT anyAuth m Checkin
getCheckin Id
id_ [Argument]
query Maybe UserAccessToken
mtoken = Text
-> [Argument]
-> Maybe UserAccessToken
-> FacebookT anyAuth m Checkin
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
<> Id -> Text
idCode Id
id_) [Argument]
query Maybe UserAccessToken
mtoken

-- | Creates a 'check-in' and returns its ID. Place and
-- coordinates are both required by Facebook.
createCheckin
  :: (R.MonadResource m, R.MonadUnliftIO m, R.MonadThrow m)
  => Id -- ^ Place ID.
  -> GeoCoordinates -- ^ Coordinates.
  -> [Argument] -- ^ Other arguments of the action.
  -> UserAccessToken -- ^ Required user access token.
  -> FacebookT Auth m Id
createCheckin :: Id
-> GeoCoordinates
-> [Argument]
-> UserAccessToken
-> FacebookT Auth m Id
createCheckin Id
pid GeoCoordinates
coords [Argument]
args UserAccessToken
usertoken = do
  let body :: [Argument]
body = (ByteString
"place" ByteString -> Id -> Argument
forall a. SimpleType a => ByteString -> a -> Argument
#= Id
pid) Argument -> [Argument] -> [Argument]
forall a. a -> [a] -> [a]
: (ByteString
"coordinates" ByteString -> GeoCoordinates -> Argument
forall a. SimpleType a => ByteString -> a -> Argument
#= GeoCoordinates
coords) Argument -> [Argument] -> [Argument]
forall a. a -> [a] -> [a]
: [Argument]
args
  Text -> [Argument] -> UserAccessToken -> FacebookT Auth m Id
forall (m :: * -> *) a anyKind.
(MonadResource m, MonadUnliftIO m, MonadThrow m, FromJSON a) =>
Text -> [Argument] -> AccessToken anyKind -> FacebookT Auth m a
postObject Text
"me/checkins" [Argument]
body UserAccessToken
usertoken