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

module Facebook.Object.Page
  ( Page(..)
  , getPage
  , getPage_
  , searchPages
  ) where

import Control.Monad (mzero)
import Data.Aeson ((.:), (.:?))
import qualified Control.Monad.Trans.Resource as R
import qualified Data.Aeson as A
import Data.Text (Text)
import Data.Typeable (Typeable)

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

-- | A Facebook page (see
-- <https://developers.facebook.com/docs/reference/api/page/>).
--
-- /NOTE:/ Does not yet support all fields. Please file an issue if
-- you need any other fields.
data Page = Page
  { pageId :: Id
  , pageName :: Maybe Text
  , pageLink :: Maybe Text
  , pageCategory :: Maybe Text
  , pageIsPublished :: Maybe Bool
  , pageCanPost :: Maybe Bool
  , pageLikes :: Maybe Integer
  , pageLocation :: Maybe Location
  , pagePhone :: Maybe Text
  , pageCheckins :: Maybe Integer
  , pagePicture :: Maybe Text
  , pageWebsite :: Maybe Text
  , pageTalkingAboutCount :: Maybe Integer
  } deriving (Eq, Ord, Show, Read, Typeable)

instance A.FromJSON Page where
  parseJSON (A.Object v) =
    Page <$> v .: "id" <*> v .:? "name" <*> v .:? "link" <*> v .:? "category" <*>
    v .:? "is_published" <*>
    v .:? "can_post" <*>
    v .:? "likes" <*>
    v .:? "location" <*>
    v .:? "phone" <*>
    v .:? "checkin" <*>
    v .:? "picture" <*>
    v .:? "website" <*>
    v .:? "talking_about_count"
  parseJSON _ = mzero

-- | Get a page using its ID. The user access token is optional.
getPage
  :: (R.MonadResource m, R.MonadUnliftIO m, R.MonadThrow m)
  => Id -- ^ Page ID
  -> [Argument] -- ^ Arguments to be passed to Facebook
  -> Maybe UserAccessToken -- ^ Optional user access token
  -> FacebookT anyAuth m Page
getPage id_ = getObject $ ("/" <> idCode id_)

-- | Get a page using its ID. The user access token is optional.
getPage_
  :: (R.MonadResource m, R.MonadUnliftIO m, R.MonadThrow m)
  => Id -- ^ Page ID
  -> [Argument] -- ^ Arguments to be passed to Facebook
  -> Maybe AppAccessToken -- ^ Optional user access token
  -> FacebookT anyAuth m Page
getPage_ id_ = getObject $ ("/" <> idCode id_)

-- | Search pages by keyword. The user access token is optional.
searchPages
  :: (R.MonadResource m, R.MonadUnliftIO m, R.MonadThrow m)
  => Text -- ^ Keyword to search for
  -> [Argument] -- ^ Arguments to pass to Facebook
  -> Maybe UserAccessToken -- ^ Optional user access token
  -> FacebookT anyAuth m (Pager Page)
searchPages = searchObjects "page"