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

module Facebook.Object.FriendList
  ( FriendList(..)
  , FriendListType(..)
  , getUserFriendLists
  , getFriendListMembers
  ) where
#if __GLASGOW_HASKELL__ <= 784
import Control.Applicative
#endif
import Control.Monad (mzero)
import Data.Aeson ((.:))
import Data.Text (Text)
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
import Facebook.Object.User

-- | A friend list for a 'User'.
data FriendList = FriendList
  { friendListId :: Id
  , friendListName :: Text
  , friendListType :: FriendListType
  } deriving (Eq, Ord, Show, Read, Typeable)

instance A.FromJSON FriendList where
  parseJSON (A.Object v) =
    FriendList <$> v .: "id" <*> v .: "name" <*> v .: "list_type"
  parseJSON _ = mzero

data FriendListType
  = CloseFriendsList
  | AcquaintancesList
  | RestrictedList
  | UserCreatedList
  | EducationList
  | WorkList
  | CurrentCityList
  | FamilyList
  deriving (Eq, Ord, Show, Read, Enum, Typeable)

instance A.FromJSON FriendListType where
  parseJSON (A.String "close_friends") = return CloseFriendsList
  parseJSON (A.String "acquaintances") = return AcquaintancesList
  parseJSON (A.String "restricted") = return RestrictedList
  parseJSON (A.String "user_created") = return UserCreatedList
  parseJSON (A.String "education") = return EducationList
  parseJSON (A.String "work") = return WorkList
  parseJSON (A.String "current_city") = return CurrentCityList
  parseJSON (A.String "family") = return FamilyList
  parseJSON _ = mzero

instance A.ToJSON FriendListType where
  toJSON = A.toJSON . toText
    where
      toText :: FriendListType -> Text
      toText CloseFriendsList = "close_friends"
      toText AcquaintancesList = "aquaintances"
      toText RestrictedList = "restricted"
      toText UserCreatedList = "user_created"
      toText EducationList = "education"
      toText WorkList = "work"
      toText CurrentCityList = "current_city"
      toText FamilyList = "family"

-- close_friends, acquaintances, restricted, user_created, education, work, current_city, family
-- | Get the friend lists of the given user.
getUserFriendLists
  :: (R.MonadResource m, R.MonadUnliftIO m, R.MonadThrow m)
  => UserId -- ^ User ID or @\"me\"@.
  -> [Argument] -- ^ Arguments to be passed to Facebook.
  -> UserAccessToken -- ^ User access token.
  -> FacebookT anyAuth m (Pager FriendList)
getUserFriendLists id_ query token =
  getObject ("/" <> idCode id_ <> "/friendlists") query (Just token)

-- | Get the members of a friend list.
getFriendListMembers
  :: (R.MonadResource m, R.MonadUnliftIO m, R.MonadThrow m)
  => Id -- ^ List ID.
  -> [Argument] -- ^ Arguments to be passed to Facebook.
  -> UserAccessToken -- ^ User access token.
  -> FacebookT anyAuth m (Pager Friend)
getFriendListMembers id_ query token =
  getObject ("/" <> idCode id_ <> "/members") query (Just token)