private IEnumerable <IPackage> SearchPackagesWithBackup(string baseUrl, HttpQueryBuilder qb, RequestWrapper request, NuGetSearchContext searchContext, NuGetSearchTerm searchTerm)
        {
            // First execute the actual search
            HashSet <string> foundPackageIds = new HashSet <string>();

            return(NuGetWebUtility.GetResults <dynamic, PackageBase>(request, (dynamic root) =>
            {
                long res = -1;
                if (root.HasProperty("totalhits"))
                {
                    res = root.totalhits;
                    request.Debug(Resources.Messages.TotalPackagesDiscovered, res);
                }
                else
                {
                    request.Warning(Resources.Messages.JsonSchemaMismatch, "totalhits");
                    request.Debug(Resources.Messages.JsonObjectDump, DynamicJsonParser.Serialize(root));
                }

                return res;
            }, (dynamic root) => GetPackageCollectionsForSearchResult(root, searchContext, searchTerm, foundPackageIds, request), (long packagesToSkip) =>
            {
                if (packagesToSkip > 0)
                {
                    HttpQueryBuilder currentQb = qb.CloneAdd(Constants.SkipQueryParam, packagesToSkip.ToString());
                    return currentQb.AddQueryString(baseUrl);
                }

                return qb.AddQueryString(baseUrl);
            }, (string content) =>
            {
                return DynamicJsonParser.Parse(content);
            }, Constants.SearchPageCountInt));
        }
        public IEnumerable <string> Autocomplete(NuGetSearchTerm autocompleteSearchTerm, RequestWrapper request, WildcardPattern acceptedPattern, bool allowPrerelease)
        {
            try
            {
                request.Debug(Messages.DebugInfoCallMethod3, "NuGetAutoCompleteFeed3", "Autocomplete", autocompleteSearchTerm.ToString());
                return(base.Execute <IEnumerable <string> >((baseUrl) =>
                {
                    HttpQueryBuilder qb = new HttpQueryBuilder();
                    if (autocompleteSearchTerm.Term == NuGetSearchTerm.NuGetSearchTermType.Id)
                    {
                        qb.Add(Constants.PackageIdQueryParam, autocompleteSearchTerm.Text);
                    }
                    else if (autocompleteSearchTerm.Term == NuGetSearchTerm.NuGetSearchTermType.AutoComplete)
                    {
                        qb.Add(Constants.QueryQueryParam, autocompleteSearchTerm.Text);
                    }

                    if (allowPrerelease)
                    {
                        qb.Add(Constants.PrereleaseQueryParam, "true");
                    }

                    qb.Add(Constants.TakeQueryParam, Constants.SearchPageCount)
                    .Add(Constants.SemVerLevelQueryParam, Constants.SemVerLevel2);

                    return NuGetWebUtility.GetResults <dynamic, string>(request, (dynamic root) =>
                    {
                        long res = -1;
                        if (root.HasProperty("totalhits"))
                        {
                            res = root.totalhits;
                            request.Debug(Resources.Messages.TotalPackagesDiscovered, res);
                        }
                        else
                        {
                            request.Warning(Resources.Messages.JsonSchemaMismatch, "totalhits");
                            request.Debug(Resources.Messages.JsonObjectDump, DynamicJsonParser.Serialize(root));
                        }

                        return res;
                    }, (dynamic root) => GetAutoCompleteResults(root, autocompleteSearchTerm, acceptedPattern), (long resultsToSkip) =>
                    {
                        if (resultsToSkip > 0)
                        {
                            HttpQueryBuilder currentQb = qb.CloneAdd(Constants.SkipQueryParam, resultsToSkip.ToString());
                            return currentQb.AddQueryString(baseUrl);
                        }

                        return qb.AddQueryString(baseUrl);
                    }, (string content) =>
                    {
                        return DynamicJsonParser.Parse(content);
                    }, Constants.SearchPageCountInt);
                }));
            }
            finally
            {
                request.Debug(Messages.DebugInfoReturnCall, "NuGetAutoCompleteFeed3", "Autocomplete");
            }
        }
        /// <summary>
        /// Adds the name-value pair to a new instance of HttpQueryBuilder, while keeping this instance's name-value pairs in the new instance.
        /// </summary>
        public HttpQueryBuilder CloneAdd(string name, string val, string separator = "=")
        {
            HttpQueryBuilder clone = new HttpQueryBuilder();

            clone.innerQueryBuilder = this;
            clone.Add(name, val, separator);
            return(clone);
        }
        public NuGetSearchResult Search(NuGetSearchContext searchContext, RequestWrapper request)
        {
            // This is a search scenario, so it should be safe to skip some metadata for the sake of performance
            searchContext.EnableDeepMetadataBypass = true;
            return(base.Execute <NuGetSearchResult>((baseUrl) =>
            {
                // For now we'll just get all versions and return the latest
                HttpQueryBuilder qb = new HttpQueryBuilder();
                // Once searchTermQb encodes the searchTerm, don't encode the ":" part of the resulting string
                qb.Add(Constants.QueryQueryParam, this.ResourcesCollection.GetSearchQueryDelegate(searchContext.SearchTerms), separator: "=", encode: false).Add(Constants.TakeQueryParam, Constants.SearchPageCount)
                .Add(Constants.SemVerLevelQueryParam, Constants.SemVerLevel2);
                if (searchContext.AllowPrerelease)
                {
                    qb.Add(Constants.PrereleaseQueryParam, "true");
                }

                NuGetSearchTerm searchTerm = searchContext.SearchTerms.Where(st => st.Term == NuGetSearchTerm.NuGetSearchTermType.SearchTerm).FirstOrDefault();
                IEnumerable <IPackage> packages = SearchPackagesWithBackup(baseUrl, qb, request, searchContext, searchTerm);

                return searchContext.MakeResult(packages, versionPostFilterRequired: true, namePostFilterRequired: false, containsPostFilterRequired: false);
            }));
        }
        public static NuGetResourceCollection3 Make(dynamic root, string baseUrl, RequestWrapper request)
        {
            request.Debug(Messages.DebugInfoCallMethod3, "NuGetResourceCollection3", "Make", baseUrl);
            NuGetResourceCollection3 collection = new NuGetResourceCollection3();
            Dictionary <NuGetServiceType, NuGetServiceInfo> currentServiceMap = new Dictionary <NuGetServiceType, NuGetServiceInfo>();

            foreach (dynamic resourceElement in root.resources)
            {
                NuGetServiceInfo serviceInfo = NuGetServiceInfo.GetV3Endpoint(resourceElement);
                if (serviceInfo == null)
                {
                    continue;
                }

                bool serviceUsed       = currentServiceMap.ContainsKey(serviceInfo.Type) && currentServiceMap[serviceInfo.Type].Preference <= serviceInfo.Preference;
                bool serviceSupplement = currentServiceMap.ContainsKey(serviceInfo.Type) && currentServiceMap[serviceInfo.Type].Preference == serviceInfo.Preference;
                switch (serviceInfo.Type)
                {
                case NuGetServiceType.AutoComplete:
                    // No feed yet OR no version (lowest possible stable version) OR greater version
                    if (serviceUsed || collection.AutoCompleteFeed == null)
                    {
                        serviceUsed = true;
                        if (serviceSupplement)
                        {
                            ((NuGetAutoCompleteFeed3)collection.AutoCompleteFeed).Endpoints.Add(serviceInfo);
                        }
                        else
                        {
                            collection.AutoCompleteFeed = new NuGetAutoCompleteFeed3(serviceInfo);
                        }
                    }

                    break;

                case NuGetServiceType.Registrations:
                    if (serviceUsed || collection.PackagesFeed == null)
                    {
                        serviceUsed = true;
                        if (serviceSupplement)
                        {
                            ((NuGetPackageFeed3)collection.PackagesFeed).Endpoints.Add(serviceInfo);
                        }
                        else
                        {
                            collection.PackagesFeed = new NuGetPackageFeed3(serviceInfo);
                        }
                    }

                    break;

                case NuGetServiceType.Query:
                    if (serviceUsed || collection.QueryFeed == null)
                    {
                        serviceUsed = true;
                        if (serviceSupplement)
                        {
                            ((NuGetQueryFeed3)collection.QueryFeed).Endpoints.Add(serviceInfo);
                        }
                        else
                        {
                            collection.QueryFeed = new NuGetQueryFeed3(serviceInfo);
                        }
                    }

                    break;

                case NuGetServiceType.Files:
                    if (serviceUsed || collection.FilesFeed == null)
                    {
                        serviceUsed          = true;
                        collection.FilesFeed = new NuGetFilesFeed3(serviceInfo.Url);
                    }

                    break;

                case NuGetServiceType.ReportAbuse:
                    if (serviceUsed || collection.AbuseFeed == null)
                    {
                        serviceUsed          = true;
                        collection.AbuseFeed = new NuGetAbuseFeed3(serviceInfo.Url);
                    }

                    break;
                }

                if (serviceUsed)
                {
                    request.Debug(Messages.NuGetEndpointDiscovered, serviceInfo.Type, serviceInfo.Url);
                    if (!serviceSupplement)
                    {
                        currentServiceMap[serviceInfo.Type] = serviceInfo;
                    }
                }
            }

            collection.GetSearchQueryDelegate = (searchTerms) =>
            {
                string searchString = String.Empty;
                // TODO: encode search terms?
                foreach (NuGetSearchTerm searchTerm in searchTerms)
                {
                    switch (searchTerm.Term)
                    {
                    case NuGetSearchTerm.NuGetSearchTermType.SearchTerm:
                        searchString += searchTerm.Text;
                        break;

                    case NuGetSearchTerm.NuGetSearchTermType.Tag:
                        HttpQueryBuilder tQb = new HttpQueryBuilder().Add(Constants.TagQueryParam, searchTerm.Text, separator: ":", encode: false);
                        searchString += " " + tQb.ToQueryString();
                        break;

                    case NuGetSearchTerm.NuGetSearchTermType.Contains:
                        HttpQueryBuilder cQb = new HttpQueryBuilder().Add(Constants.DescriptionQueryParam, searchTerm.Text, separator: ":", encode: false);
                        searchString += " " + cQb.ToQueryString();
                        break;

                    default:
                        break;
                    }
                }

                return(searchString.Trim());
            };

            collection.PackageConverter              = new PackageBaseConverter();
            collection.PackageDependencyConverter    = new PackageDependencyConverter();
            collection.PackageDependencySetConverter = new DependencyGroupConverter();
            collection.CatalogUrlConverter           = new CatalogUrlConverter();
            Uri uri = new Uri(baseUrl);

            if (uri.Host.Contains(Constants.NuGetOrgHost))
            {
                collection.GalleryFeed = new NuGetGalleryFeedOrg();
            }
            else if (uri.Host.Contains(Constants.MyGetOrgHost))
            {
                collection.GalleryFeed = new NuGetGalleryFeedMyGet(baseUrl);
            }

            request.Debug(Messages.DebugInfoReturnCall, "NuGetResourceCollection3", "Make");
            return(collection);
        }