public CatalogSearchResult Search(
            CatalogSearchQuery searchQuery,
            ProductLoadFlags loadFlags = ProductLoadFlags.None,
            bool direct = false)
        {
            Guard.NotNull(searchQuery, nameof(searchQuery));
            Guard.NotNegative(searchQuery.Take, nameof(searchQuery.Take));

            var provider = _indexManager.GetIndexProvider("Catalog");

            if (!direct && provider != null)
            {
                var indexStore = provider.GetIndexStore("Catalog");
                if (indexStore.Exists)
                {
                    var searchEngine = provider.GetSearchEngine(indexStore, searchQuery);
                    var stepPrefix   = searchEngine.GetType().Name + " - ";

                    int      totalCount = 0;
                    string[] spellCheckerSuggestions = null;
                    IEnumerable <ISearchHit>         searchHits;
                    Func <IList <Product> >          hitsFactory = null;
                    IDictionary <string, FacetGroup> facets      = null;

                    _services.EventPublisher.Publish(new CatalogSearchingEvent(searchQuery, false));

                    if (searchQuery.Take > 0)
                    {
                        using (_services.Chronometer.Step(stepPrefix + "Search"))
                        {
                            totalCount = searchEngine.Count();
                            // Fix paging boundaries
                            if (searchQuery.Skip > 0 && searchQuery.Skip >= totalCount)
                            {
                                searchQuery.Slice((totalCount / searchQuery.Take) * searchQuery.Take, searchQuery.Take);
                            }
                        }

                        if (searchQuery.ResultFlags.HasFlag(SearchResultFlags.WithHits))
                        {
                            using (_services.Chronometer.Step(stepPrefix + "Hits"))
                            {
                                searchHits = searchEngine.Search();
                            }

                            using (_services.Chronometer.Step(stepPrefix + "Collect"))
                            {
                                var productIds = searchHits.Select(x => x.EntityId).ToArray();
                                hitsFactory = () => _productService.Value.GetProductsByIds(productIds, loadFlags);
                            }
                        }

                        if (searchQuery.ResultFlags.HasFlag(SearchResultFlags.WithFacets))
                        {
                            try
                            {
                                using (_services.Chronometer.Step(stepPrefix + "Facets"))
                                {
                                    facets = searchEngine.GetFacetMap();
                                    ApplyFacetLabels(facets);
                                }
                            }
                            catch (Exception ex)
                            {
                                _logger.Error(ex);
                            }
                        }
                    }

                    if (searchQuery.ResultFlags.HasFlag(SearchResultFlags.WithSuggestions))
                    {
                        try
                        {
                            using (_services.Chronometer.Step(stepPrefix + "Spellcheck"))
                            {
                                spellCheckerSuggestions = searchEngine.CheckSpelling();
                            }
                        }
                        catch (Exception ex)
                        {
                            // Spell checking should not break the search.
                            _logger.Error(ex);
                        }
                    }

                    var result = new CatalogSearchResult(
                        searchEngine,
                        searchQuery,
                        totalCount,
                        hitsFactory,
                        spellCheckerSuggestions,
                        facets);

                    var searchedEvent = new CatalogSearchedEvent(searchQuery, result);
                    _services.EventPublisher.Publish(searchedEvent);

                    return(searchedEvent.Result);
                }
                else if (searchQuery.Origin.IsCaseInsensitiveEqual("Search/Search"))
                {
                    IndexingRequiredNotification(_services, _urlHelper);
                }
            }

            return(SearchDirect(searchQuery));
        }