public async Task <IActionResult> GetSearchResultPage(string[] org, string[] repo, string query, bool isRegex, [FromQuery] Dictionary <string, List <string> > filters = null)
        {
            void CheckArgs()
            {
                if (org == null)
                {
                    throw new ArgumentNullException(nameof(org));
                }
                if (repo == null)
                {
                    throw new ArgumentNullException(nameof(repo));
                }
            }

            CheckArgs();
            if (org.Length != repo.Length)
            {
                this.TempData["Error"] = $"Number of org parameters does not match the number of repo parameters. Orgs: {string.Join(", ", org)}. Repos: {string.Join(", ", repo)}";
                return(this.RedirectToAction("Error", "Home"));
            }
            SearchIndexViewModel model = new SearchIndexViewModel
            {
                Repositories = await this.GetRepositoriesSelectList().ConfigureAwait(false),
                Query        = query,
                IsRegex      = isRegex
            };
            IReadOnlyCollection <RepositoryQueryParameter> parameters = RepositoryQueryParameter.ConvertFromArrays(org, repo);

            ManifestQueryResultViewModel queryResultViewModel = await this.GetQueryResultViewModel(parameters, query, isRegex, filters).ConfigureAwait(false);

            model.Result = queryResultViewModel;
            return(this.View("Index", model));
        }
        private async Task <ManifestQueryResultViewModel> GetQueryResultViewModel(
            IReadOnlyCollection <RepositoryQueryParameter> parameters, string query, bool isRegex,
            Dictionary <string, List <string> > filters)
        {
            List <RepositoryInfo> repositories = (await this.repositoryService.GetRepositories(parameters)).ToList();

            var downloadStatsTask = this.statisticsService.GetDownloadStatistics(repositories);
            var projectsTask      = this.repositoryService.GetCurrentProjects(repositories, query, isRegex);
            await Task.WhenAll(downloadStatsTask, projectsTask);

            var flattenedDownloadStats = downloadStatsTask.Result.SelectMany(x => x.ProjectDownloadData).ToList();
            ManifestQueryResultViewModel queryResultViewModel = this.mapper.Map <ManifestQueryResultViewModel>(projectsTask.Result);

            IEnumerable <Project> sortedProjects = this.sorter.Sort(projectsTask.Result.Projects, projectsTask.Result.Tokens);

            queryResultViewModel.ProjectsTable         = new ProjectsTableModel(this.mapper.Map <List <ProjectInfoViewModel> >(sortedProjects), this.IsMultipleRepos(parameters), true);
            queryResultViewModel.ProjectsTable.Filters = filters;

            foreach (ProjectInfoViewModel projectInfoViewModel in queryResultViewModel.ProjectsTable.Projects)
            {
                projectInfoViewModel.DownloadsCount =
                    flattenedDownloadStats.FirstOrDefault(x =>
                                                          x.ProjectKey == projectInfoViewModel.ProjectUri)?.DownloadCount ?? 0;
            }
            return(queryResultViewModel);
        }
        public async Task <IActionResult> Search(string[] org, string[] repo, string query, bool isRegex, [FromQuery] Dictionary <string, List <string> > filters = null)
        {
            if (org == null)
            {
                throw new ArgumentNullException(nameof(org));
            }
            if (repo == null)
            {
                throw new ArgumentNullException(nameof(repo));
            }
            if (org.Length != repo.Length)
            {
                this.TempData["Error"] = $"Number of org parameters does not match the number of repo parameters. Orgs: {string.Join(", ", org)}. Repos: {string.Join(", ", repo)}";
                return(this.RedirectToAction("Error", "Home"));
            }

            IReadOnlyCollection <RepositoryQueryParameter> parameters = RepositoryQueryParameter.ConvertFromArrays(org, repo);

            BackgroundJob.Enqueue(() => this.UpdateSearchStatistics(parameters, query));

            ManifestQueryResultViewModel queryResultViewModel = await this.GetQueryResultViewModel(parameters, query, isRegex, filters).ConfigureAwait(false);

            this.telemetryClient.TrackSearch(parameters, query, isRegex, queryResultViewModel.ProjectsTable.Projects.Count, queryResultViewModel.Elapsed);
            return(this.PartialView("_SearchResultPartial", queryResultViewModel));
        }