///// <summary>
        ///// Creates a representation of the catalog object located at the input service endpoint.
        ///// </summary>
        ///// <param name="url">The url to the REST endpoint.</param>
        ///// <param name="callback">A callback action used to retrieve the result of the operation.</param>
        //public void CreateCatalogAsync(string url, Action<IArcGISServerCatalog> callback)
        //{
        //    Throw.IfArgumentNullOrEmpty(url, "url");
        //    Throw.IfArgumentNull(callback, "callback");
        //    Uri uri = new Uri(url);
        //    string rooturl = url = uri.GetLeftPart(UriPartial.Path);
        //    if (rooturl.EndsWith("/")) rooturl = rooturl.Substring(0, rooturl.Length - 1);

        //    if (!url.EndsWith("/")) url += "/";
        //    if (!url.Contains("?")) url += "?";
        //    int len = url.IndexOf("?");
        //    url = url.Substring(0, len >0? len : url.Length);
        //    services = new List<ArcGISService>();
        //    svcloaded = totalcount = 0;
        //    // get root catalog
        //    this.rest.HydrateAsync<ArcGISServerCatalog>(url +"?"+ JSON, cb =>
        //        {
        //            if (cb != null)
        //            {
        //                cb.RootUrl = url;
        //                List<ArcGISServerCatalog> folders = new List<ArcGISServerCatalog>();
        //                int foldercnt = 0;
        //                // get a count each folder's services and add to the total count of services
        //                // also, add the hydrated folders to a list for future enumeration
        //                foreach (var f in cb.Folders)
        //                {
        //                    this.rest.HydrateAsync<ArcGISServerCatalog>(url + f + "?"+ JSON, folder =>
        //                    {
        //                        if (folder != null)
        //                        {
        //                            foldercnt += 1;
        //                            totalcount += folder.ServiceInfos.Count(x => supportedtypes.Contains(x.Type));
        //                            folders.Add(folder);
        //                            folder.RootUrl = rooturl;

        //                            //if all folders have been retrieved get services within each folder
        //                            if (foldercnt == cb.Folders.Length)
        //                            {
        //                                foreach (var subcatalog in folders)
        //                                {
        //                                    GetServices(subcatalog, folderservices =>
        //                                    {
        //                                        // finally get top level services
        //                                        totalcount += cb.ServiceInfos.Count(x => supportedtypes.Contains(x.Type));
        //                                        GetServices(cb, toplevel =>
        //                                        {
        //                                            cb.Services = services.ToArray();
        //                                            callback(cb);
        //                                        });
        //                                    });
        //                                }
        //                            }
        //                        }
        //                    });
        //                }
        //            }
        //        });
        //}

        /// <summary>
        /// Creates a representation of the catalog object located at the input service endpoint.
        /// </summary>
        /// <param name="url">The url to the REST endpoint.</param>
        /// <returns>
        /// Returns an instance of <see cref="T:Geocrest.Data.Contracts.Gis.IArcGISServerCatalog">IArcGISServerCatalog</see>.
        /// </returns>
        public IArcGISServerCatalog CreateCatalog(string url)
        {
            Throw.IfArgumentNullOrEmpty(url, "url");
            Uri    uri     = new Uri(url);
            string rooturl = uri.GetLeftPart(UriPartial.Path);

            if (rooturl.EndsWith("/"))
            {
                rooturl = rooturl.Substring(0, rooturl.Length - 1);
            }
            var query = HttpUtility.ParseQueryString(uri.Query);
            var token = query["token"];

            // get root catalog
            List <IArcGISService> services = new List <IArcGISService>();
            ArcGISServerCatalog   catalog  = this.rest.Hydrate <ArcGISServerCatalog>(
                !string.IsNullOrEmpty(this.ProxyUrl) ? this.ProxyUrl + "?" + url : url);

            if (catalog != null)
            {
                catalog.RootUrl    = rooturl;
                catalog.RestHelper = this.rest;
                catalog.Token      = token;
                string template = catalog.RootUrl + "/{0}/{1}";
                List <IArcGISServerCatalog> folders = new List <IArcGISServerCatalog>();
                foreach (var f in catalog.Folders)
                {
                    // need to catch any exceptions if a service folder is down
                    // but allow the rest of the catalog to populate
                    IArcGISServerCatalog folder = null;
                    try
                    {
                        folder = CreateCatalog(rooturl + "/" + f + (!string.IsNullOrEmpty(token) ? "?token=" + token : ""));
                        //folder = this.rest.Hydrate<ArcGISServerCatalog>(url + f + "?" + JSON);
                    }
                    catch { }
                    if (folder != null)
                    {
                        folder.RootUrl = rooturl;
                        folders.Add(folder);
                        foreach (var service in folder.ServiceInfos)
                        {
                            services.AddIfNotNull <IArcGISService>(this.CreateService(string.Format(template,
                                                                                                    service.Name, service.Type.ToString()) + "?" + JSON + (!string.IsNullOrEmpty(token) ?
                                                                                                                                                           "&token=" + token : ""), folder.CurrentVersion));
                        }
                    }
                }
                foreach (var service in catalog.ServiceInfos)
                {
                    services.Add(this.CreateService(string.Format(template,
                                                                  service.Name.Contains("/") ? service.Name.Substring(service.Name.IndexOf("/") + 1)
                        : service.Name, service.Type.ToString()) + "?" + JSON + (!string.IsNullOrEmpty(token) ?
                                                                                 "&token=" + token : ""), catalog.CurrentVersion));
                }
                catalog.Services = services.ToArray();
            }
            return(catalog);
        }
 /// <summary>
 /// Determines whether the catalogs's existing token is valid. If no token exists the method will return
 /// true to indicate that the catalog can be accessed as-is.
 /// </summary>
 /// <returns>
 /// Whether the existing token is still valid or not.
 /// </returns>
 public bool IsTokenValid()
 {
     if (string.IsNullOrEmpty(this.Token))
     {
         return(true);
     }
     else
     {
         try
         {
             ArcGISServerCatalog catalog = Geocrest.Model.RestHelper.HydrateObject <ArcGISServerCatalog>(string.Format("{0}?token={1}", this.RootUrl, this.Token));
             return(catalog != null);
         }
         catch (HttpException ex)
         {
             int code = ex.GetHttpCode();
             return(!(code == 498 || code == 499));
         }
     }
 }