#ifndef COMPONENTS_COMMERCE_CORE_COMPARE_CLUSTER_MANAGER_H_
#define COMPONENTS_COMMERCE_CORE_COMPARE_CLUSTER_MANAGER_H_
#include <map>
#include <memory>
#include <set>
#include <vector>
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "base/scoped_observation.h"
#include "base/uuid.h"
#include "components/commerce/core/commerce_types.h"
#include "components/commerce/core/product_specifications/product_specifications_set.h"
#include "url/gurl.h"
namespace commerce {
class ClusterServerProxy;
class ProductSpecificationsService;
struct CandidateProduct;
struct ProductGroup;
class ClusterManager : public ProductSpecificationsSet::Observer {
public:
using GetProductInfoCallback =
base::RepeatingCallback<void(const GURL&, ProductInfoCallback)>;
using GetProductInfoBatchCallback =
base::RepeatingCallback<void(const std::vector<GURL>& urls,
ProductInfoBatchCallback)>;
using GetOpenUrlInfosCallback =
base::RepeatingCallback<const std::vector<UrlInfo>()>;
using GetEntryPointInfoCallback =
base::OnceCallback<void(std::optional<EntryPointInfo>)>;
class Observer : public base::CheckedObserver {
public:
virtual void OnClusterFinishedForNavigation(const GURL& url) {}
};
ClusterManager(ProductSpecificationsService* product_specification_service,
std::unique_ptr<ClusterServerProxy> cluster_server_proxy,
const GetProductInfoCallback& get_product_info_cb,
const GetProductInfoBatchCallback& get_product_info_batch_cb,
const GetOpenUrlInfosCallback& get_open_url_infos_cb);
~ClusterManager() override;
ClusterManager(const ClusterManager&) = delete;
ClusterManager& operator=(const ClusterManager&) = delete;
void OnProductSpecificationsSetAdded(
const ProductSpecificationsSet& product_specifications_set) override;
void OnProductSpecificationsSetUpdate(
const ProductSpecificationsSet& before,
const ProductSpecificationsSet& product_specifications_set) override;
void OnProductSpecificationsSetRemoved(
const ProductSpecificationsSet& set) override;
void WebWrapperDestroyed(const GURL& url);
void DidNavigatePrimaryMainFrame(const GURL& url);
void DidNavigateAway(const GURL& from_url);
virtual std::optional<ProductGroup> GetProductGroupForCandidateProduct(
const GURL& product_url);
virtual void GetEntryPointInfoForNavigation(
const GURL& url,
GetEntryPointInfoCallback callback);
virtual void GetEntryPointInfoForSelection(
const GURL& old_url,
const GURL& new_url,
GetEntryPointInfoCallback callback);
std::vector<GURL> FindSimilarCandidateProductsForProductGroup(
const base::Uuid& uuid);
virtual void GetComparableProducts(const EntryPointInfo& entry_point_info,
GetEntryPointInfoCallback callback);
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
private:
friend class ClusterManagerTest;
void OnGetAllProductSpecificationsSets(
const std::vector<ProductSpecificationsSet> sets);
void OnProductInfoRetrieved(
const GURL& url,
const std::optional<const ProductInfo>& product_info);
void OnAllCategoryDataRetrieved(
const base::Uuid& uuid,
const std::set<GURL>& urls,
const std::vector<CategoryData>& category_data);
void AddCandidateProduct(
const GURL& url,
const std::optional<const ProductInfo>& product_info);
void RemoveCandidateProductURLIfNotOpen(const GURL& url);
std::set<GURL> FindSimilarCandidateProducts(const GURL& product_url);
void OnGetComparableProducts(
const EntryPointInfo& entry_point_info,
GetEntryPointInfoCallback callback,
const std::vector<uint64_t>& cluster_product_ids);
void OnProductInfoFetchedForSimilarUrls(
GetEntryPointInfoCallback callback,
const std::map<GURL, std::optional<ProductInfo>> product_infos);
bool IsSetEligibleForClustering(const base::Uuid& uuid,
const base::Time& update_time);
void RemoveIneligibleGroupsForClustering();
std::unique_ptr<ClusterServerProxy> cluster_server_proxy_;
GetProductInfoCallback get_product_info_cb_;
GetProductInfoBatchCallback get_product_info_batch_cb_;
GetOpenUrlInfosCallback get_open_url_infos_cb_;
std::map<base::Uuid, std::unique_ptr<ProductGroup>> product_group_map_;
std::map<GURL, std::unique_ptr<CandidateProduct>> candidate_product_map_;
base::ScopedObservation<ProductSpecificationsService,
ProductSpecificationsSet::Observer>
obs_{this};
base::ObserverList<Observer> observers_;
base::WeakPtrFactory<ClusterManager> weak_ptr_factory_{this};
};
}
#endif