private static void WriteData(
            JsonWriter jsonWriter,
            NuGetIndexSearcher searcher,
            TopDocs topDocs,
            int skip,
            int take,
            Uri baseAddress,
            bool includePrerelease,
            bool includeExplanation,
            NuGetVersion semVerLevel,
            Query query)
        {
            jsonWriter.WritePropertyName("data");

            jsonWriter.WriteStartArray();

            for (int i = skip; i < Math.Min(skip + take, topDocs.ScoreDocs.Length); i++)
            {
                ScoreDoc scoreDoc = topDocs.ScoreDocs[i];

                Document document = searcher.Doc(scoreDoc.Doc);

                jsonWriter.WriteStartObject();

                string id = document.Get("Id");

                var relativeAddress = UriFormatter.MakeRegistrationRelativeAddress(id);
                var absoluteAddress = new Uri(baseAddress, relativeAddress).AbsoluteUri;

                WriteProperty(jsonWriter, "@id", absoluteAddress);
                WriteProperty(jsonWriter, "@type", "Package");
                WriteProperty(jsonWriter, "registration", absoluteAddress);

                WriteProperty(jsonWriter, "id", id);

                WriteDocumentValue(jsonWriter, "version", document, LuceneMetadataConstants.FullVersionPropertyName);
                WriteDocumentValue(jsonWriter, "description", document, "Description");
                WriteDocumentValue(jsonWriter, "summary", document, "Summary");
                WriteDocumentValue(jsonWriter, "title", document, "Title");
                WriteDocumentValue(jsonWriter, "iconUrl", document, "IconUrl");
                WriteDocumentValue(jsonWriter, "licenseUrl", document, "LicenseUrl");
                WriteDocumentValue(jsonWriter, "projectUrl", document, "ProjectUrl");
                WriteDocumentValueAsArray(jsonWriter, "tags", document, "Tags");
                WriteDocumentValueAsArray(jsonWriter, "authors", document, "Authors", true);
                WriteProperty(jsonWriter, "totalDownloads", searcher.Versions[scoreDoc.Doc].AllVersionDetails.Select(item => item.Downloads).Sum());
                WriteProperty(jsonWriter, "verified", searcher.VerifiedPackages.Contains(id));
                WriteVersions(jsonWriter, baseAddress, id, includePrerelease, semVerLevel, searcher.Versions[scoreDoc.Doc]);

                if (includeExplanation)
                {
                    Explanation explanation = searcher.Explain(query, scoreDoc.Doc);
                    WriteProperty(jsonWriter, "explanation", explanation.ToString());
                    WriteProperty(jsonWriter, "score", scoreDoc.Score);
                }

                jsonWriter.WriteEndObject();
            }

            jsonWriter.WriteEndArray();
        }
 private static void WriteIds(JsonWriter jsonWriter, NuGetIndexSearcher searcher, TopDocs topDocs, int skip, int take)
 {
     jsonWriter.WritePropertyName("data");
     jsonWriter.WriteStartArray();
     for (int i = skip; i < Math.Min(skip + take, topDocs.ScoreDocs.Length); i++)
     {
         ScoreDoc scoreDoc = topDocs.ScoreDocs[i];
         Document document = searcher.Doc(scoreDoc.Doc);
         string   id       = document.Get("Id");
         jsonWriter.WriteValue(id);
     }
     jsonWriter.WriteEndArray();
 }
        private static void WriteDataV2(JsonWriter jsonWriter, NuGetIndexSearcher searcher, TopDocs topDocs, int skip, int take, NuGetVersion semVerLevel)
        {
            jsonWriter.WritePropertyName("data");

            jsonWriter.WriteStartArray();

            var includeSemVer2 = SemVerHelpers.ShouldIncludeSemVer2Results(semVerLevel);

            var isLatestBitSet       = includeSemVer2 ? searcher.LatestSemVer2BitSet : searcher.LatestBitSet;
            var isLatestStableBitSet = includeSemVer2 ? searcher.LatestStableSemVer2BitSet : searcher.LatestStableBitSet;

            for (int i = skip; i < Math.Min(skip + take, topDocs.ScoreDocs.Length); i++)
            {
                ScoreDoc scoreDoc = topDocs.ScoreDocs[i];
                Document document = searcher.Doc(scoreDoc.Doc);

                string id = document.Get("Id");
                string normalizedVersion = document.Get(LuceneMetadataConstants.NormalizedVersionPropertyName);
                string fullVersion       = document.Get(LuceneMetadataConstants.FullVersionPropertyName);

                Tuple <int, int> downloadCounts = NuGetIndexSearcher.DownloadCounts(searcher.Versions[scoreDoc.Doc], normalizedVersion);

                bool isVerified     = searcher.VerifiedPackages.Contains(id);
                bool isLatest       = isLatestBitSet.Get(scoreDoc.Doc);
                bool isLatestStable = isLatestStableBitSet.Get(scoreDoc.Doc);

                jsonWriter.WriteStartObject();
                WriteRegistrationV2(jsonWriter, id, downloadCounts.Item1, NuGetIndexSearcher.GetOwners(searcher, id), isVerified);
                WriteDocumentValue(jsonWriter, "Version", document, LuceneMetadataConstants.VerbatimVersionPropertyName);
                WriteProperty(jsonWriter, "NormalizedVersion", normalizedVersion);
                WriteDocumentValue(jsonWriter, "Title", document, "Title");
                WriteDocumentValue(jsonWriter, "Description", document, "Description");
                WriteDocumentValue(jsonWriter, "Summary", document, "Summary");
                WriteDocumentValue(jsonWriter, "Authors", document, "Authors");
                WriteDocumentValue(jsonWriter, "Copyright", document, "Copyright");
                WriteDocumentValue(jsonWriter, "Language", document, "Language");
                WriteDocumentValue(jsonWriter, "Tags", document, "Tags");
                WriteDocumentValue(jsonWriter, "ReleaseNotes", document, "ReleaseNotes");
                WriteDocumentValue(jsonWriter, "ProjectUrl", document, "ProjectUrl");
                WriteDocumentValue(jsonWriter, "IconUrl", document, "IconUrl");
                WriteProperty(jsonWriter, "IsLatestStable", isLatestStable);
                WriteProperty(jsonWriter, "IsLatest", isLatest);
                WriteProperty(jsonWriter, "Listed", bool.Parse(document.Get("Listed") ?? "true"));
                WriteDocumentValue(jsonWriter, "Created", document, "OriginalCreated");
                WriteDocumentValue(jsonWriter, "Published", document, "OriginalPublished");
                WriteDocumentValue(jsonWriter, "LastUpdated", document, "OriginalPublished");
                WriteDocumentValue(jsonWriter, "LastEdited", document, "OriginalLastEdited");
                WriteProperty(jsonWriter, "DownloadCount", downloadCounts.Item2);
                WriteDocumentValue(jsonWriter, "FlattenedDependencies", document, "FlattenedDependencies");
                jsonWriter.WritePropertyName("Dependencies");
                jsonWriter.WriteRawValue(document.Get("Dependencies") ?? "[]");
                jsonWriter.WritePropertyName("SupportedFrameworks");
                jsonWriter.WriteRawValue(document.Get("SupportedFrameworks") ?? "[]");
                WriteDocumentValue(jsonWriter, "MinClientVersion", document, "MinClientVersion");
                WriteDocumentValue(jsonWriter, "Hash", document, "PackageHash");
                WriteDocumentValue(jsonWriter, "HashAlgorithm", document, "PackageHashAlgorithm");
                WriteProperty(jsonWriter, "PackageFileSize", int.Parse(document.Get("PackageSize") ?? "0"));
                WriteDocumentValue(jsonWriter, "LicenseUrl", document, "LicenseUrl");
                WriteProperty(jsonWriter, "RequiresLicenseAcceptance", bool.Parse(document.Get("RequiresLicenseAcceptance") ?? "false"));
                jsonWriter.WriteEndObject();
            }

            jsonWriter.WriteEndArray();
        }
        public static JToken MakeResultData(NuGetIndexSearcher searcher, string scheme, TopDocs topDocs, int skip, int take, NuGetSearcherManager searcherManager, bool includeExplanation, Query query)
        {
            Uri registrationBaseAddress = searcherManager.RegistrationBaseAddress[scheme];

            JArray array = new JArray();

            for (int i = skip; i < Math.Min(skip + take, topDocs.ScoreDocs.Length); i++)
            {
                ScoreDoc scoreDoc = topDocs.ScoreDocs[i];

                Document document = searcher.Doc(scoreDoc.Doc);

                string url = document.Get("Url");
                string id = document.Get("Id");
                string version = document.Get("Version");

                JObject obj = new JObject();
                obj["@id"] = new Uri(registrationBaseAddress, url).AbsoluteUri;
                obj["@type"] = "Package";
                obj["registration"] = new Uri(registrationBaseAddress, string.Format("{0}/index.json", id.ToLowerInvariant())).AbsoluteUri;
                obj["id"] = id;

                AddField(obj, document, "domain", "Domain");
                AddField(obj, document, "description", "Description");
                AddField(obj, document, "summary", "Summary");
                AddField(obj, document, "title", "Title");
                AddField(obj, document, "iconUrl", "IconUrl");
                AddField(obj, document, "licenseUrl", "LicenseUrl");
                AddField(obj, document, "projectUrl", "ProjectUrl");
                AddFieldAsArray(obj, document, "tags", "Tags");
                AddFieldAsArray(obj, document, "authors", "Authors");

                obj["version"] = version;
                obj["versions"] = searcherManager.GetVersions(searcher, scheme, scoreDoc.Doc);
                
                if (includeExplanation)
                {
                    Explanation explanation = searcher.Explain(query, scoreDoc.Doc);
                    obj["explanation"] = explanation.ToString();
                }

                array.Add(obj);
            }

            return array;
        }
        private static JToken MakeResults(NuGetIndexSearcher searcher, TopDocs topDocs, int skip, int take, Query boostedQuery, IDictionary<string, int> rankings, NuGetSearcherManager manager)
        {
            JObject obj = new JObject();
            obj.Add("TotalHits", topDocs.TotalHits);

            string timestamp;
            if (!searcher.IndexReader.CommitUserData.TryGetValue("commitTimeStamp", out timestamp))
            {
                timestamp = DateTime.MinValue.ToString();
            }            
            obj.Add("IndexTimestampUtc",timestamp);
          
            JArray array = new JArray();

            Tuple<OpenBitSet, OpenBitSet> latestBitSets = manager.GetBitSets(searcher, null);

            for (int i = skip; i < Math.Min(skip + take, topDocs.ScoreDocs.Length); i++)
            {
                ScoreDoc scoreDoc = topDocs.ScoreDocs[i];

                Document document = searcher.Doc(scoreDoc.Doc);

                Tuple<int, int> downloadCounts = manager.GetDownloadCounts(document.Get("Id"), document.Get("Version"));

                JObject packageObj = new JObject();

                JObject registrationObj = new JObject();

                registrationObj.Add("Id", document.Get("Id"));
                registrationObj.Add("DownloadCount", downloadCounts.Item1);                
                registrationObj.Add("Owners", JArray.Parse(document.Get("Owners")));

                packageObj.Add("PackageRegistration", registrationObj);

                packageObj.Add("Version", document.Get("OriginalVersion"));
                packageObj.Add("NormalizedVersion", document.Get("Version"));
                packageObj.Add("Title", document.Get("Title"));
                packageObj.Add("Description", document.Get("Description"));
                packageObj.Add("Summary", document.Get("Summary"));
                packageObj.Add("Authors", document.Get("Authors"));             
                packageObj.Add("Copyright", document.Get("Copyright"));
                packageObj.Add("Language", document.Get("Language"));
                packageObj.Add("Tags", document.Get("Tags"));
                packageObj.Add("ReleaseNotes", document.Get("ReleaseNotes"));
                packageObj.Add("ProjectUrl", document.Get("ProjectUrl"));
                packageObj.Add("IconUrl", document.Get("IconUrl"));
                packageObj.Add("IsLatestStable", latestBitSets.Item1.Get(scoreDoc.Doc));
                packageObj.Add("IsLatest", latestBitSets.Item2.Get(scoreDoc.Doc));
                packageObj.Add("Listed", bool.Parse(document.Get("Listed") ?? "true"));
                packageObj.Add("Created", document.Get("OriginalCreated"));
                packageObj.Add("Published", document.Get("OriginalPublished"));
                packageObj.Add("LastUpdated", document.Get("OriginalPublished"));
                packageObj.Add("LastEdited", document.Get("OriginalEditedDate"));
                packageObj.Add("DownloadCount", downloadCounts.Item2);
                packageObj.Add("FlattenedDependencies", document.Get("FlattenedDependencies"));                                         
                packageObj.Add("Dependencies", JArray.Parse(document.Get("Dependencies")));                                        
                packageObj.Add("SupportedFrameworks", JArray.Parse(document.Get("SupportedFrameworks")));                               
                packageObj.Add("MinClientVersion", document.Get("MinClientVersion"));
                packageObj.Add("Hash", document.Get("PackageHash"));
                packageObj.Add("HashAlgorithm", document.Get("PackageHashAlgorithm"));
                packageObj.Add("PackageFileSize", int.Parse(document.Get("PackageSize") ?? "0"));
                packageObj.Add("LicenseUrl", document.Get("LicenseUrl"));
                packageObj.Add("RequiresLicenseAcceptance", bool.Parse(document.Get("RequiresLicenseAcceptance") ?? "true"));
                packageObj.Add("LicenseNames", document.Get("LicenseNames"));
                packageObj.Add("LicenseReportUrl", document.Get("LicenseReportUrl"));
                packageObj.Add("HideLicenseReport", bool.Parse(document.Get("HideLicenseReport") ?? "true"));   //TODO: data is missing from index

                array.Add(packageObj);
            }
            obj.Add("Data", array);
            return obj;
        }