//
//  PFFacebookUtils.h
//
//  Copyright 2011-present Parse Inc. All rights reserved.
//

#import <Foundation/Foundation.h>

#import <FacebookSDK/FacebookSDK.h>

#import <Parse/PFConstants.h>
#import <Parse/PFNullability.h>
#import <Parse/PFUser.h>

PF_ASSUME_NONNULL_BEGIN

@class BFTask;

/*!
 The `PFFacebookUtils` class provides utility functions for working with Facebook in a Parse application.

 This class is currently for iOS only.
 */
@interface PFFacebookUtils : NSObject

///--------------------------------------
/// @name Interacting With Facebook
///--------------------------------------

/*!
 @abstract Gets the Facebook session for the current user.
 */
+ (PF_NULLABLE FBSession *)session;

/*!
 @abstract Initializes the Facebook singleton.

 @warning You must invoke this in order to use the Facebook functionality in Parse.

 @param appId The Facebook application id that you are using with your Parse application.

 @deprecated Please use `[PFFacebookUtils initializeFacebook]` instead.
 */
+ (void)initializeWithApplicationId:(PF_NULLABLE NSString *)appId PARSE_DEPRECATED("Use [PFFacebookUtils initializeFacebook] instead.");

/*!
 @abstract Initializes the Facebook singleton.

 @warning You must invoke this in order to use the Facebook functionality in Parse.

 @param appId The Facebook application id that you are using with your Parse application.
 @param urlSchemeSuffix The URL suffix for this application - used when multiple applications with the same

 @deprecated Please use `[PFFacebookUtils initializeFacebookWithUrlShemeSuffix:]` instead.
 */
+ (void)initializeWithApplicationId:(PF_NULLABLE NSString *)appId
                    urlSchemeSuffix:(PF_NULLABLE NSString *)urlSchemeSuffix PARSE_DEPRECATED("Use [PFFacebookUtils initializeFacebookWithUrlShemeSuffix:] instead.");

/*!
 @abstract Initializes the Facebook singleton.

 @discussion  You must provide your Facebook application ID as the value for FacebookAppID in your bundle's plist file
 as described here: https://developers.facebook.com/docs/getting-started/facebook-sdk-for-ios/

 @warning You must invoke this in order to use the Facebook functionality in Parse.
 */
+ (void)initializeFacebook;

/*!
 @abstract Initializes the Facebook singleton.

 @discussion  You must provide your Facebook application ID as the value for FacebookAppID in your bundle's plist file
 as described here: https://developers.facebook.com/docs/getting-started/facebook-sdk-for-ios/

 @warning You must invoke this in order to use the Facebook functionality in Parse.

 @param urlSchemeSuffix The URL suffix for this application - used when multiple applications with the same
 Facebook application ID may be on the same device.
 */
+ (void)initializeFacebookWithUrlShemeSuffix:(PF_NULLABLE NSString *)urlSchemeSuffix;

/*!
 @abstract Whether the user has their account linked to Facebook.

 @param user User to check for a facebook link. The user must be logged in on this device.

 @returns `YES` if the user has their account linked to Facebook, otherwise `NO`.
 */
+ (BOOL)isLinkedWithUser:(PFUser *)user;

///--------------------------------------
/// @name Customizing Login Behavior
///--------------------------------------

/*!
 @abstract Sets the default login behavior to be used when logging in or linking users with Facebook.

 @discussion Default is to allow Facebook Login, with fallback to Inline Facebook Login.

 @param behavior The behavior to set.
 */
+ (void)setFacebookLoginBehavior:(FBSessionLoginBehavior)behavior;

/*!
 @abstract Login behavior controls whether to allow, force or prohibit Facebook Login or Inline Facebook Login.

 @discussion Default is to allow Facebook Login, with fallback to Inline Facebook Login.

 @returns The login behavior currently set.
 */
+ (FBSessionLoginBehavior)facebookLoginBehavior;

///--------------------------------------
/// @name Logging In & Creating Facebook-Linked Users
///--------------------------------------

/*!
 @abstract Logs in a user using Facebook *asynchronously*.

 @discussion This method delegates to the Facebook SDK to authenticate the user,
 and then automatically logs in (or creates, in the case where it is a new user) a <PFUser>.

 @param permissions The permissions required for Facebook log in. This passed to the authorize method on
 the Facebook instance.

 @returns The task, that encapsulates the work being done.
 */
+ (BFTask *)logInWithPermissionsInBackground:(PF_NULLABLE NSArray *)permissions;

/*!
 @abstract Logs in a user using Facebook.

 @discussion This method delegates to the Facebook SDK to authenticate the user,
 and then automatically logs in (or creates, in the case where it is a new user) a <PFUser>.
 `user` is going to be non-nil if the authentication was succesful.
 `error` is set if there was an error.
 `user` and `error` are both nil - if the user cancelled authentication by switching back to the application.

 @param permissions The permissions required for Facebook log in. This passed to the authorize method on
 the Facebook instance.
 @param block The block to execute.
 It should have the following argument signature: `^(PFUser *user, NSError *error)`.
 */
+ (void)logInWithPermissions:(PF_NULLABLE NSArray *)permissions block:(PF_NULLABLE PFUserResultBlock)block;

/*
 @abstract Logs in a user using Facebook *asynchronously*.

 @discussion This method delegates to the Facebook SDK to authenticate the user,
 and then automatically logs in (or creates, in the case where it is a new user) a <PFUser>.
 `user` is going to be non-nil if the authentication was succesful.
 `error` is set if there was an error.
 `user` and `error` are both nil - if the user cancelled authentication by switching back to the application.

 @param permissions The permissions required for Facebook log in. This passed to the authorize method on
 the Facebook instance.
 @param target Target object for the selector
 @param selector The selector that will be called when the asynchronous request is complete.
 It should have the following signature: `(void)callbackWithUser:(PFUser *)user error:(NSError *)error`.
 */
+ (void)logInWithPermissions:(PF_NULLABLE NSArray *)permissions target:(PF_NULLABLE_S id)target selector:(PF_NULLABLE_S SEL)selector;

/*!
 @abstract Logs in a user using Facebook *asynchronously*.

 @discussion Allows you to handle user login to Facebook, then provide authentication
 data to log in (or create, in the case where it is a new user) the <PFUser>.

 @param facebookId The id of the Facebook user being linked
 @param accessToken The access token for the user's session
 @param expirationDate The expiration date for the access token

 @returns The task, that encapsulates the work being done.
 */
+ (BFTask *)logInWithFacebookIdInBackground:(NSString *)facebookId
                                accessToken:(NSString *)accessToken
                             expirationDate:(NSDate *)expirationDate;

/*!
 @abstract Logs in a user using Facebook *asynchronously*.

 @discussion Allows you to handle user login to Facebook, then provide authentication
 data to log in (or create, in the case where it is a new user) the <PFUser>.

 @param facebookId The id of the Facebook user being linked
 @param accessToken The access token for the user's session
 @param expirationDate The expiration date for the access token
 @param block The block to execute.
 It should have the following argument signature: `^(PFUser *user, NSError *error)`.
 */
+ (void)logInWithFacebookId:(NSString *)facebookId
                accessToken:(NSString *)accessToken
             expirationDate:(NSDate *)expirationDate
                      block:(PF_NULLABLE PFUserResultBlock)block;

/*
 @abstract Logs in a user using Facebook *asynchronously*.

 @discussion Allows you to handle user login to Facebook, then provide authentication
 data to log in (or create, in the case where it is a new user) the <PFUser>.

 @param facebookId The id of the Facebook user being linked
 @param accessToken The access token for the user's session
 @param expirationDate The expiration date for the access token
 @param target Target object for the selector
 @param selector The selector that will be called when the asynchronous request is complete.
 It should have the following signature: `(void)callbackWithUser:(PFUser *)user error:(NSError *)error`.
 */
+ (void)logInWithFacebookId:(NSString *)facebookId
                accessToken:(NSString *)accessToken
             expirationDate:(NSDate *)expirationDate
                     target:(PF_NULLABLE_S id)target
                   selector:(PF_NULLABLE_S SEL)selector;

///--------------------------------------
/// @name Linking Users with Facebook
///--------------------------------------

/*!
 @abstract Links Facebook to an existing <PFUser> *asynchronously*.

 @discussion This method delegates to the Facebook SDK to authenticate
 the user, and then automatically links the account to the <PFUser>.

 @param user User to link to Facebook.
 @param permissions The permissions required for Facebook log in.
 This passed to the authorize method on the Facebook instance.

 @deprecated Please use `[PFFacebookUtils linkUserInBackground:permissions:]` instead.
 */
+ (void)linkUser:(PFUser *)user permissions:(PF_NULLABLE NSArray *)permissions PARSE_DEPRECATED("Please use `[PFFacebookUtils linkUserInBackground:permissions:]` instead.");

/*!
 @abstract Links Facebook to an existing <PFUser> *asynchronously*.

 @discussion This method delegates to the Facebook SDK to authenticate
 the user, and then automatically links the account to the <PFUser>.

 @param user User to link to Facebook.
 @param permissions The permissions required for Facebook log in.
 This passed to the authorize method on the Facebook instance.

 @returns The task, that encapsulates the work being done.
 */
+ (BFTask *)linkUserInBackground:(PFUser *)user permissions:(PF_NULLABLE NSArray *)permissions;

/*!
 @abstract Links Facebook to an existing <PFUser> *asynchronously*.

 @discussion This method delegates to the Facebook SDK to authenticate
 the user, and then automatically links the account to the <PFUser>.

 @param user User to link to Facebook.
 @param permissions The permissions required for Facebook log in.
 This passed to the authorize method on the Facebook instance.
 @param block The block to execute.
 It should have the following argument signature: `^(BOOL *success, NSError *error)`.
 */
+ (void)linkUser:(PFUser *)user
     permissions:(PF_NULLABLE NSArray *)permissions
           block:(PF_NULLABLE PFBooleanResultBlock)block;

/*
 @abstract Links Facebook to an existing <PFUser> *asynchronously*.

 @discussion This method delegates to the Facebook SDK to authenticate
 the user, and then automatically links the account to the <PFUser>.

 @param user User to link to Facebook.
 @param permissions The permissions required for Facebook log in. This passed to the authorize method on
 the Facebook instance.
 @param target Target object for the selector
 @param selector The selector that will be called when the asynchronous request is complete.
 It should have the following signature: `(void)callbackWithResult:(NSNumber *)result error:(NSError *)error`.
 */
+ (void)linkUser:(PFUser *)user
     permissions:(PF_NULLABLE NSArray *)permissions
          target:(PF_NULLABLE_S id)target
        selector:(PF_NULLABLE_S SEL)selector;

/*!
 @abstract Links Facebook to an existing <PFUser> *asynchronously*.

 @discussion Allows you to handle user login to Facebook,
 then provide authentication data to link the account to the <PFUser>.

 @param user User to link to Facebook.
 @param facebookId The id of the Facebook user being linked
 @param accessToken The access token for the user's session
 @param expirationDate The expiration date for the access token

 @returns The task, that encapsulates the work being done.
 */
+ (BFTask *)linkUserInBackground:(PFUser *)user
                      facebookId:(NSString *)facebookId
                     accessToken:(NSString *)accessToken
                  expirationDate:(NSDate *)expirationDate;

/*!
 @abstract Links Facebook to an existing <PFUser> *asynchronously*.

 @discussion Allows you to handle user login to Facebook,
 then provide authentication data to link the account to the <PFUser>.

 @param user User to link to Facebook.
 @param facebookId The id of the Facebook user being linked
 @param accessToken The access token for the user's session
 @param expirationDate The expiration date for the access token
 @param block The block to execute.
 It should have the following argument signature: `^(BOOL success, NSError *error)`.
 */
+ (void)linkUser:(PFUser *)user
      facebookId:(NSString *)facebookId
     accessToken:(NSString *)accessToken
  expirationDate:(NSDate *)expirationDate
           block:(PF_NULLABLE PFBooleanResultBlock)block;

/*
 @abstract Links Facebook to an existing <PFUser> *asynchronously*.

 @discussion Allows you to handle user login to Facebook,
 then provide authentication data to link the account to the <PFUser>.

 @param user User to link to Facebook.
 @param facebookId The id of the Facebook user being linked
 @param accessToken The access token for the user's session
 @param expirationDate The expiration date for the access token
 @param target Target object for the selector
 @param selector The selector that will be called when the asynchronous request is complete.
 It should have the following signature: `(void)callbackWithResult:(NSNumber *)result error:(NSError *)error`.
 */
+ (void)linkUser:(PFUser *)user
      facebookId:(NSString *)facebookId
     accessToken:(NSString *)accessToken
  expirationDate:(NSDate *)expirationDate
          target:(PF_NULLABLE_S id)target
        selector:(PF_NULLABLE_S SEL)selector;

///--------------------------------------
/// @name Unlinking Users from Facebook
///--------------------------------------

/*!
 @abstract Unlinks the <PFUser> from a Facebook account *synchronously*.

 @param user User to unlink from Facebook.

 @returns Returns `YES` if the unlink was successful, otherwise `NO`.
 */
+ (BOOL)unlinkUser:(PFUser *)user;

/*!
 @abstract Unlinks the <PFUser> from a Facebook account *synchronously*.

 @param user User to unlink from Facebook.
 @param error Error object to set on error.

 @returns Returns `YES` if the unlink was successful, otherwise `NO`.
 */
+ (BOOL)unlinkUser:(PFUser *)user error:(NSError **)error;

/*!
 @abstract Unlinks the <PFUser> from a Facebook account *asynchronously*.

 @param user User to unlink from Facebook.
 @returns The task, that encapsulates the work being done.
 */
+ (BFTask *)unlinkUserInBackground:(PFUser *)user;

/*!
 @abstract Unlinks the <PFUser> from a Facebook account *asynchronously*.

 @param user User to unlink from Facebook.
 @param block The block to execute.
 It should have the following argument signature: `^(BOOL succeeded, NSError *error)`.
 */
+ (void)unlinkUserInBackground:(PFUser *)user block:(PF_NULLABLE PFBooleanResultBlock)block;

/*
 @abstract Unlinks the <PFUser> from a Facebook account *asynchronously*.

 @param user User to unlink from Facebook
 @param target Target object for the selector
 @param selector The selector that will be called when the asynchronous request is complete.
 It should have the following signature: `(void)callbackWithResult:(NSNumber *)result error:(NSError *)error`.
 */
+ (void)unlinkUserInBackground:(PFUser *)user
                        target:(PF_NULLABLE_S id)target
                      selector:(PF_NULLABLE_S SEL)selector;

///--------------------------------------
/// @name Obtaining New Permissions
///--------------------------------------

/*!
 @abstract Requests new Facebook publish permissions for the given user *asynchronously*.

 @discussion The user will be saved as part of this operation.

 @warning This may prompt the user to reauthorize the application.

 @param user User to request new permissions for.  The user must be linked to Facebook.
 @param permissions The new publishing permissions to request.
 @param audience The default audience for publishing permissions to request.

 @returns The task, that encapsulates the work being done.
 */
+ (BFTask *)reauthorizeUserInBackground:(PFUser *)user
                 withPublishPermissions:(PF_NULLABLE NSArray *)permissions
                               audience:(FBSessionDefaultAudience)audience;

/*!
 @abstract Requests new Facebook publish permissions for the given user *asynchronously*.

 @discussion The user will be saved as part of this operation.

 @warning This may prompt the user to reauthorize the application.

 @param user User to request new permissions for.  The user must be linked to Facebook.
 @param permissions The new publishing permissions to request.
 @param audience The default audience for publishing permissions to request.
 @param block The block to execute.
 It should have the following argument signature: `^(BOOL succeeded, NSError *error)`.
 */
+ (void)reauthorizeUser:(PFUser *)user
 withPublishPermissions:(PF_NULLABLE NSArray *)permissions
               audience:(FBSessionDefaultAudience)audience
                  block:(PF_NULLABLE PFBooleanResultBlock)block;

/*
 @abstract Requests new Facebook publish permissions for the given user *asynchronously*.

 @discussion The user will be saved as part of this operation.

 @warning This may prompt the user to reauthorize the application.

 @param user User to request new permissions for.  The user must be linked to Facebook.
 @param permissions The new publishing permissions to request.
 @param audience The default audience for publishing permissions to request.
 @param target Target object for the selector.
 @param selector The selector that will be called when the asynchronous request is complete.
 It should have the following signature: `(void)callbackWithResult:(NSNumber *)result error:(NSError *)error`.
 */
+ (void)reauthorizeUser:(PFUser *)user
 withPublishPermissions:(PF_NULLABLE NSArray *)permissions
               audience:(FBSessionDefaultAudience)audience
                 target:(PF_NULLABLE_S id)target
               selector:(PF_NULLABLE_S SEL)selector;

///--------------------------------------
/// @name Delegating URL Actions
///--------------------------------------

/*!
 @abstract Handles URLs being opened by your AppDelegate. Invoke and return this from application:handleOpenURL:
 or application:openURL:sourceApplication:annotation in your AppDelegate.

 @param url URL being opened by your application.
 @returns `YES` if Facebook will handle this URL, otherwise `NO`.

 @deprecated Please use
 `[FBAppCall handleOpenURL:url
 sourceApplication:sourceApplication
 withSession:[PFFacebookUtils session]];` instead.
 */
+ (BOOL)handleOpenURL:(PF_NULLABLE NSURL *)url PARSE_DEPRECATED("Use [FBAppCall handleOpenURL:sourceApplication:withSession:] instead.");

@end

PF_ASSUME_NONNULL_END
