/// <summary>
        /// Deserializes the specified json string to a presence object.
        /// </summary>
        /// <param name="message">Json string to deserialize.</param>
        /// <returns></returns>
        public static Presence Deserialize(string message)
        {
            Presence result = new Presence();
            
            if (!String.IsNullOrEmpty(message))
            {
                var json = message.Replace("\\\\\"", @"""");
                json = Regex.Unescape(json);

                Match presenceMatch = Regex.Match(json, SUBSCRIPTIONS_PATTERN, RegexOptions.Compiled);

                var subscriptions = 0;

                if (int.TryParse(presenceMatch.Groups["subscriptions"].Value, out subscriptions))
                {
                    var metadataContent = presenceMatch.Groups["metadata"].Value;

                    var metadataRegex = new Regex(METADATA_PATTERN, RegexOptions.Compiled);
                    foreach (Match metadata in metadataRegex.Matches(metadataContent))
                    {
                        if (metadata.Groups.Count > 1)
                        {
                            var metadataDetailMatch = Regex.Match(metadata.Groups[0].Value, METADATA_DETAIL_PATTERN, RegexOptions.Compiled);

                            var metadataSubscriptions = 0;
                            if (int.TryParse(metadataDetailMatch.Groups[2].Value, out metadataSubscriptions))
                            {
                                result.Metadata.Add(metadataDetailMatch.Groups[1].Value, metadataSubscriptions);
                            }
                        }
                    }
                }

                result.Subscriptions = subscriptions;
               
            }

            return result;
        }
        /// <summary>
        /// Gets the subscriptions in the specified channel and if active the first 100 unique metadata.
        /// </summary>
        /// <param name="url">Server containing the presence service.</param>
        /// <param name="isCluster">Specifies if url is cluster.</param>
        /// <param name="applicationKey">Application key with access to presence service.</param>
        /// <param name="authenticationToken">Authentication token with access to presence service.</param>
        /// <param name="channel">Channel with presence data active.</param>
        /// <param name="callback"><see cref="OnPresenceDelegate"/>Callback with error <see cref="OrtcPresenceException"/> and result <see cref="Presence"/>.</param>
        /// <example>
        /// <code>
        /// client.Presence("http://ortc-developers.realtime.co/server/2.1", true, "myApplicationKey", "myAuthenticationToken", "presence-channel", (error, result) =>
        /// {
        ///     if (error != null)
        ///     {
        ///         Console.WriteLine(error.Message);
        ///     }
        ///     else
        ///     {
        ///         if (result != null)
        ///         {
        ///             Console.WriteLine(result.Subscriptions);
        /// 
        ///             if (result.Metadata != null)
        ///             {
        ///                 foreach (var metadata in result.Metadata)
        ///                 {
        ///                     Console.WriteLine(metadata.Key + " - " + metadata.Value);
        ///                 }
        ///             }
        ///         }
        ///         else
        ///         {
        ///             Console.WriteLine("There is no presence data");
        ///         }
        ///     }
        /// });
        /// </code>
        /// </example>
        public static void GetPresence(String url, bool isCluster, String applicationKey, String authenticationToken, String channel, OnPresenceDelegate callback)
        {
            Balancer.GetServerUrl(url, isCluster, applicationKey, (error, server) =>
            {
                var presenceUrl = String.IsNullOrEmpty(server) ? server : server[server.Length - 1] == '/' ? server : server + "/";
                presenceUrl = String.Format("{0}presence/{1}/{2}/{3}", presenceUrl, applicationKey, authenticationToken, channel);

                RestWebservice.GetAsync(presenceUrl, (responseError, result) =>
                {
                    if (responseError != null)
                    {
                        callback(responseError, null);
                    }
                    else
                    {
                        Presence presenceData = new Presence();
                        if (!String.IsNullOrEmpty(result))
                        {
                            presenceData = Extensibility.Presence.Deserialize(result);
                        }
                        callback(null, presenceData);
                    }
                });
            });
        }