/// <summary>
        /// For platforms that do not support dynamic cast it to either IDictionary<string, object> if json object or IList<object> if array.
        /// For primitive types cast it to bool, string, dobule or long depending on the type.
        /// Reference: http://facebooksdk.net/docs/making-asynchronous-requests/#1
        /// </summary>
        public static void API(
            string endpoint,
            HttpMethod method,
            FacebookDelegate callback,
            object parameters = null)
        {
#if NETFX_CORE
            Task.Run(async() =>
            {
                FacebookClient fb = new FacebookClient(_fbSessionClient.CurrentAccessTokenData.AccessToken);
                FBResult fbResult = null;
                try
                {
                    object apiCall;
                    if (method == HttpMethod.GET)
                    {
                        apiCall = await fb.GetTaskAsync(endpoint, parameters);
                    }
                    else if (method == HttpMethod.POST)
                    {
                        apiCall = await fb.PostTaskAsync(endpoint, parameters);
                    }
                    else
                    {
                        apiCall = await fb.DeleteTaskAsync(endpoint);
                    }
                    if (apiCall != null)
                    {
                        fbResult      = new FBResult();
                        fbResult.Text = apiCall.ToString();
                        fbResult.Json = apiCall as JsonObject;
                    }
                }
                catch (Exception ex)
                {
                    fbResult       = new FBResult();
                    fbResult.Error = ex.Message;
                }
                if (callback != null)
                {
                    Dispatcher.InvokeOnAppThread(() => { callback(fbResult); });
                }
            });
#else
            throw new PlatformNotSupportedException("");
#endif
        }
        public static void Login(string permissions, FacebookDelegate callback)
        {
#if NETFX_CORE
            Session.OnFacebookAuthenticationFinished = (AccessTokenData data) =>
            {
                var result = new FBResult()
                {
                    Text = (data == null || String.IsNullOrEmpty(data.AccessToken)) ? "Fail" : "Success", Error = (data == null || String.IsNullOrEmpty(data.AccessToken)) ? "Error" : null
                };
                if (data == null || String.IsNullOrEmpty(data.AccessToken))
                {
                    if (callback != null)
                    {
                        Dispatcher.InvokeOnAppThread(() => { callback(result); });
                    }
                }
                else
                {
                    GetCurrentUser((user) =>
                    {
                        UserId   = user.Id;
                        UserName = user.Name;

                        Settings.Set(FBID_KEY, UserId);
                        Settings.Set(FBNAME_KEY, UserName);

                        if (callback != null)
                        {
                            Dispatcher.InvokeOnAppThread(() => { callback(result); });
                        }
                    });
                }
            };

            Dispatcher.InvokeOnUIThread(() =>
            {
                _fbSessionClient.LoginWithBehavior(permissions, FacebookLoginBehavior.LoginBehaviorMobileInternetExplorerOnly);
            });
#else
            throw new PlatformNotSupportedException("");
#endif
        }
        private static void HandleGetCompleted(object sender, FacebookApiEventArgs e)
        {
            var callback = e.UserState as FacebookDelegate;

            if (callback != null)
            {
                var result = new FBResult();
                if (e.Cancelled)
                {
                    result.Error = "Cancelled";
                }
                else if (e.Error != null)
                {
                    result.Error = e.Error.Message;
                }
                else
                {
                    var obj = e.GetResultData();
                    result.Text = obj.ToString();
                    result.Json = obj as JsonObject;
                }
                Dispatcher.InvokeOnAppThread(() => { callback(result); });
            }
        }
        /// <summary>
        /// Show the Feed Dialog.
        /// mediaSource, actionName, actionLink, reference and properties are not currently supported at this time.
        /// </summary>
        public static void Feed(
            string toId = "",
            string link = "",
            string linkName = "",
            string linkCaption = "",
            string linkDescription = "",
            string picture = "",
            string mediaSource = "",
            string actionName = "",
            string actionLink = "",
            string reference = "",
            Dictionary<string, string[]> properties = null,
            FacebookDelegate callback = null)
        {
#if NETFX_CORE
            if (_web == null) throw new MissingPlatformException();
            if (_web.IsActive || !IsLoggedIn)
            {
                // Already in use
                if (callback != null)
                    callback(new FBResult() { Error = "Already in use / Not Logged In" });
                return;
            }

            if (_onHideUnity != null)
                _onHideUnity(true);

            Uri uri = new Uri("https://www.facebook.com/dialog/feed?app_id=" + AppId + "&to=" + toId +
                "&link=" + link + "&name=" + linkName + "&caption=" + linkCaption + "&description=" + linkDescription + "&picture=" + picture + "&display=popup&redirect_uri=" + _redirectUrl, UriKind.RelativeOrAbsolute);
            _web.Navigate(uri, true, finishedCallback: (url, state) =>
            {
                if (url.ToString().StartsWith(_redirectUrl))
                {
                    // parsing query string to get request id and facebook ids of the people the request has been sent to
                    // or error code and error messages
                    FBResult fbResult = new FBResult();

                    fbResult.Json = new JsonObject();

                    string[] queries = url.Query.Split('&');
                    if (queries.Length > 0)
                    {
                        string postId = string.Empty;
                        List<string> toList = new List<string>();

                        foreach (string query in queries)
                        {
                            string[] keyValue = query.Split('=');
                            if (keyValue.Length == 2)
                            {
                                if (keyValue[0].Contains("post_id"))
                                    postId = keyValue[1];
                                else if (keyValue[0].Contains("error_code"))
                                    fbResult.Error = keyValue[1];
                                else if (keyValue[0].Contains("error_msg"))
                                    fbResult.Text = keyValue[1].Replace('+', ' ');
                            }
                        }
                        if (!string.IsNullOrWhiteSpace(postId))
                        {
                            fbResult.Json.Add(new KeyValuePair<string, object>("post_id", postId));
                        }
                    }

                    // If there's no error, assign the success text
                    if (string.IsNullOrWhiteSpace(fbResult.Text))
                        fbResult.Text = "Success";

                    _web.Finish();
                    if (_onHideUnity != null)
                        _onHideUnity(false);
                    if (callback != null)
                        callback(fbResult);
                }
            }, onError: LoginNavigationError, state: callback);

            // throw not supported exception when user passed in parameters not supported currently
            if (!string.IsNullOrWhiteSpace(mediaSource) || !string.IsNullOrWhiteSpace(actionName) || !string.IsNullOrWhiteSpace(actionLink) ||
                !string.IsNullOrWhiteSpace(reference) || properties != null)
                throw new NotSupportedException("mediaSource, actionName, actionLink, reference and properties are not currently supported at this time.");
#else
            throw new PlatformNotSupportedException("");
#endif
        }
        /// <summary>
        /// Show Request Dialog.
        /// to, title, data, filters, excludeIds and maxRecipients are not currently supported at this time.
        /// </summary>
        public static void AppRequest(
                string message,
                string[] to = null,
                string filters = "",
                string[] excludeIds = null,
                int? maxRecipients = null,
                string data = "",
                string title = "",
                FacebookDelegate callback = null
            )
        {
#if NETFX_CORE
            ///
            /// @note: [vaughan.sanders 15.8.14] We are overriding the Unity FB.AppRequest here to send a more
            /// general web style request as WP8 does not support the actual request functionality.
            /// Currently we ignore all but the message and callback params
            ///

            if (_web == null) throw new MissingPlatformException();
            if (_web.IsActive || !IsLoggedIn)
            {
                // Already in use
                if (callback != null)
                    callback(new FBResult() { Error = "Already in use / Not Logged In" });
                return;
            }

            if (_onHideUnity != null)
                _onHideUnity(true);

            Uri uri = new Uri("https://www.facebook.com/dialog/apprequests?app_id=" + AppId +
                "&message=" + message + "&display=popup&redirect_uri=" + _redirectUrl, UriKind.RelativeOrAbsolute);
            _web.Navigate(uri, true, finishedCallback: (url, state) =>
            {
                if (url.ToString().StartsWith(_redirectUrl))
                {
                    // parsing query string to get request id and facebook ids of the people the request has been sent to
                    // or error code and error messages
                    FBResult fbResult = new FBResult();

                    fbResult.Json = new JsonObject();

                    string[] queries = url.Query.Split('&');
                    if (queries.Length > 0)
                    {
                        string request = string.Empty;
                        List<string> toList = new List<string>();

                        foreach (string query in queries)
                        {
                            string[] keyValue = query.Split('=');
                            if (keyValue.Length == 2)
                            {
                                if (keyValue[0].Contains("request"))
                                    request = keyValue[1];
                                else if (keyValue[0].Contains("to"))
                                    toList.Add(keyValue[1]);
                                else if (keyValue[0].Contains("error_code"))
                                    fbResult.Error = keyValue[1];
                                else if (keyValue[0].Contains("error_message"))
                                    fbResult.Text = keyValue[1].Replace('+', ' ');
                            }
                        }
                        if (!string.IsNullOrWhiteSpace(request))
                        {
                            fbResult.Json.Add(new KeyValuePair<string, object>("request", request));
                            fbResult.Json.Add(new KeyValuePair<string, object>("to", toList));
                        }
                    }

                    // If there's no error, assign the success text
                    if (string.IsNullOrWhiteSpace(fbResult.Text))
                        fbResult.Text = "Success";

                    _web.Finish();
                    if (_onHideUnity != null)
                        _onHideUnity(false);
                    if (callback != null)
                        callback(fbResult);
                }
            }, onError: LoginNavigationError, state: callback);

            // throw not supported exception when user passed in parameters not supported currently
            if (!string.IsNullOrWhiteSpace(filters) || excludeIds != null || maxRecipients != null || to != null || !string.IsNullOrWhiteSpace(data) || !string.IsNullOrWhiteSpace(title))
                throw new NotSupportedException("to, title, data, filters, excludeIds and maxRecipients are not currently supported at this time.");
#else
            throw new PlatformNotSupportedException("");
#endif
        }
        public static void API(
            string endpoint,
            HttpMethod method,
            FacebookDelegate callback,
            object parameters = null)
        {
#if NETFX_CORE
            if (_web == null) throw new MissingPlatformException();
            if (!IsLoggedIn)
            {
                // Already in use
                if (callback != null)
                    callback(new FBResult() { Error = "Not logged in" });
                return;
            }

            Task.Run(async () =>
            {
                FBResult fbResult = null;
                try
                {
                    object apiCall;
                    if (method == HttpMethod.GET)
                    {
                        apiCall = await _client.GetTaskAsync(endpoint, parameters);
                    }
                    else if (method == HttpMethod.POST)
                    {
                        apiCall = await _client.PostTaskAsync(endpoint, parameters);
                    }
                    else
                    {
                        apiCall = await _client.DeleteTaskAsync(endpoint);
                    }
                    if (apiCall != null)
                    {
                        fbResult = new FBResult();
                        fbResult.Text = apiCall.ToString();
                        fbResult.Json = apiCall as JsonObject;
                    }
                }
                catch (Exception ex)
                {
                    fbResult = new FBResult();
                    fbResult.Error = ex.Message;
                }
                if (callback != null)
                {
                    Dispatcher.InvokeOnAppThread(() => { callback(fbResult); });
                }
            });
#else
            throw new PlatformNotSupportedException("");
#endif
        }
 private static void HandleGetCompleted(object sender, FacebookApiEventArgs e)
 {
     var callback = e.UserState as FacebookDelegate;
     if (callback != null)
     {
         var result = new FBResult();
         if (e.Cancelled)
             result.Error = "Cancelled";
         else if (e.Error != null)
             result.Error = e.Error.Message;
         else
         {
             var obj = e.GetResultData();
             result.Text = obj.ToString();
             result.Json = obj as JsonObject;
         }
         Dispatcher.InvokeOnAppThread(() => { callback(result); });
     }
 }
        /// <summary>
        /// Show the Feed Dialog.
        /// mediaSource, actionName, actionLink, reference and properties are not currently supported at this time.
        /// </summary>
        public static void Feed(
            string toId            = "",
            string link            = "",
            string linkName        = "",
            string linkCaption     = "",
            string linkDescription = "",
            string picture         = "",
            string mediaSource     = "",
            string actionName      = "",
            string actionLink      = "",
            string reference       = "",
            Dictionary <string, string[]> properties = null,
            FacebookDelegate callback = null)
        {
#if NETFX_CORE
            if (_web == null)
            {
                throw new MissingPlatformException();
            }
            if (_web.IsActive || !IsLoggedIn)
            {
                // Already in use
                if (callback != null)
                {
                    callback(new FBResult()
                    {
                        Error = "Already in use / Not Logged In"
                    });
                }
                return;
            }

            if (_onHideUnity != null)
            {
                _onHideUnity(true);
            }

            Uri uri = new Uri("https://www.facebook.com/dialog/feed?app_id=" + AppId + "&to=" + toId +
                              "&link=" + link + "&name=" + linkName + "&caption=" + linkCaption + "&description=" + linkDescription + "&picture=" + picture + "&display=popup&redirect_uri=" + _redirectUrl, UriKind.RelativeOrAbsolute);
            _web.Navigate(uri, true, finishedCallback: (url, state) =>
            {
                if (url.ToString().StartsWith(_redirectUrl))
                {
                    // parsing query string to get request id and facebook ids of the people the request has been sent to
                    // or error code and error messages
                    FBResult fbResult = new FBResult();

                    fbResult.Json = new JsonObject();

                    string[] queries = url.Query.Split('&');
                    if (queries.Length > 0)
                    {
                        string postId        = string.Empty;
                        List <string> toList = new List <string>();

                        foreach (string query in queries)
                        {
                            string[] keyValue = query.Split('=');
                            if (keyValue.Length == 2)
                            {
                                if (keyValue[0].Contains("post_id"))
                                {
                                    postId = keyValue[1];
                                }
                                else if (keyValue[0].Contains("error_code"))
                                {
                                    fbResult.Error = keyValue[1];
                                }
                                else if (keyValue[0].Contains("error_msg"))
                                {
                                    fbResult.Text = keyValue[1].Replace('+', ' ');
                                }
                            }
                        }
                        if (!string.IsNullOrWhiteSpace(postId))
                        {
                            fbResult.Json.Add(new KeyValuePair <string, object>("post_id", postId));
                        }
                    }

                    // If there's no error, assign the success text
                    if (string.IsNullOrWhiteSpace(fbResult.Text))
                    {
                        fbResult.Text = "Success";
                    }

                    _web.Finish();
                    if (_onHideUnity != null)
                    {
                        _onHideUnity(false);
                    }
                    if (callback != null)
                    {
                        callback(fbResult);
                    }
                }
            }, onError: LoginNavigationError, state: callback);

            // throw not supported exception when user passed in parameters not supported currently
            if (!string.IsNullOrWhiteSpace(mediaSource) || !string.IsNullOrWhiteSpace(actionName) || !string.IsNullOrWhiteSpace(actionLink) ||
                !string.IsNullOrWhiteSpace(reference) || properties != null)
            {
                throw new NotSupportedException("mediaSource, actionName, actionLink, reference and properties are not currently supported at this time.");
            }
#else
            throw new PlatformNotSupportedException("");
#endif
        }
        /// <summary>
        /// Show Request Dialog.
        /// to, title, data, filters, excludeIds and maxRecipients are not currently supported at this time.
        /// </summary>
        public static void AppRequest(
            string message,
            string[] to               = null,
            string filters            = "",
            string[] excludeIds       = null,
            int?maxRecipients         = null,
            string data               = "",
            string title              = "",
            FacebookDelegate callback = null
            )
        {
#if NETFX_CORE
            ///
            /// @note: [vaughan.sanders 15.8.14] We are overriding the Unity FB.AppRequest here to send a more
            /// general web style request as WP8 does not support the actual request functionality.
            /// Currently we ignore all but the message and callback params
            ///

            if (_web == null)
            {
                throw new MissingPlatformException();
            }
            if (_web.IsActive || !IsLoggedIn)
            {
                // Already in use
                if (callback != null)
                {
                    callback(new FBResult()
                    {
                        Error = "Already in use / Not Logged In"
                    });
                }
                return;
            }

            if (_onHideUnity != null)
            {
                _onHideUnity(true);
            }

            Uri uri = new Uri("https://www.facebook.com/dialog/apprequests?app_id=" + AppId +
                              "&message=" + message + "&display=popup&redirect_uri=" + _redirectUrl, UriKind.RelativeOrAbsolute);
            _web.Navigate(uri, true, finishedCallback: (url, state) =>
            {
                if (url.ToString().StartsWith(_redirectUrl))
                {
                    // parsing query string to get request id and facebook ids of the people the request has been sent to
                    // or error code and error messages
                    FBResult fbResult = new FBResult();

                    fbResult.Json = new JsonObject();

                    string[] queries = url.Query.Split('&');
                    if (queries.Length > 0)
                    {
                        string request       = string.Empty;
                        List <string> toList = new List <string>();

                        foreach (string query in queries)
                        {
                            string[] keyValue = query.Split('=');
                            if (keyValue.Length == 2)
                            {
                                if (keyValue[0].Contains("request"))
                                {
                                    request = keyValue[1];
                                }
                                else if (keyValue[0].Contains("to"))
                                {
                                    toList.Add(keyValue[1]);
                                }
                                else if (keyValue[0].Contains("error_code"))
                                {
                                    fbResult.Error = keyValue[1];
                                }
                                else if (keyValue[0].Contains("error_message"))
                                {
                                    fbResult.Text = keyValue[1].Replace('+', ' ');
                                }
                            }
                        }
                        if (!string.IsNullOrWhiteSpace(request))
                        {
                            fbResult.Json.Add(new KeyValuePair <string, object>("request", request));
                            fbResult.Json.Add(new KeyValuePair <string, object>("to", toList));
                        }
                    }

                    // If there's no error, assign the success text
                    if (string.IsNullOrWhiteSpace(fbResult.Text))
                    {
                        fbResult.Text = "Success";
                    }

                    _web.Finish();
                    if (_onHideUnity != null)
                    {
                        _onHideUnity(false);
                    }
                    if (callback != null)
                    {
                        callback(fbResult);
                    }
                }
            }, onError: LoginNavigationError, state: callback);

            // throw not supported exception when user passed in parameters not supported currently
            if (!string.IsNullOrWhiteSpace(filters) || excludeIds != null || maxRecipients != null || to != null || !string.IsNullOrWhiteSpace(data) || !string.IsNullOrWhiteSpace(title))
            {
                throw new NotSupportedException("to, title, data, filters, excludeIds and maxRecipients are not currently supported at this time.");
            }
#else
            throw new PlatformNotSupportedException("");
#endif
        }
        public static void API(
            string endpoint,
            HttpMethod method,
            FacebookDelegate callback,
            object parameters = null)
        {
#if NETFX_CORE
            if (_web == null)
            {
                throw new MissingPlatformException();
            }
            if (!IsLoggedIn)
            {
                // Already in use
                if (callback != null)
                {
                    callback(new FBResult()
                    {
                        Error = "Not logged in"
                    });
                }
                return;
            }

            Task.Run(async() =>
            {
                FBResult fbResult = null;
                try
                {
                    object apiCall;
                    if (method == HttpMethod.GET)
                    {
                        apiCall = await _client.GetTaskAsync(endpoint, parameters);
                    }
                    else if (method == HttpMethod.POST)
                    {
                        apiCall = await _client.PostTaskAsync(endpoint, parameters);
                    }
                    else
                    {
                        apiCall = await _client.DeleteTaskAsync(endpoint);
                    }
                    if (apiCall != null)
                    {
                        fbResult      = new FBResult();
                        fbResult.Text = apiCall.ToString();
                        fbResult.Json = apiCall as JsonObject;
                    }
                }
                catch (Exception ex)
                {
                    fbResult       = new FBResult();
                    fbResult.Error = ex.Message;
                }
                if (callback != null)
                {
                    Dispatcher.InvokeOnAppThread(() => { callback(fbResult); });
                }
            });
#else
            throw new PlatformNotSupportedException("");
#endif
        }