// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_CONTEXTUAL_TASKS_ACTIVE_TASK_CONTEXT_PROVIDER_IMPL_H_
#define CHROME_BROWSER_CONTEXTUAL_TASKS_ACTIVE_TASK_CONTEXT_PROVIDER_IMPL_H_

#include <map>
#include <set>

#include "base/callback_list.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/scoped_observation.h"
#include "base/unguessable_token.h"
#include "base/uuid.h"
#include "chrome/browser/contextual_tasks/active_task_context_provider.h"
#include "chrome/browser/tab_list/tab_list_interface_observer.h"
#include "components/contextual_tasks/public/contextual_tasks_service.h"
#include "components/tabs/public/tab_interface.h"
#include "content/public/browser/web_contents_observer.h"

class BrowserWindowInterface;

namespace contextual_search {
class ContextualSearchSessionHandle;
}

namespace contextual_tasks {
class ContextualTask;
struct ContextualTaskContext;
class ContextualTasksPanelController;

class ActiveTaskContextProviderImpl : public ActiveTaskContextProvider,
                                      public TabListInterfaceObserver,
                                      public ContextualTasksService::Observer,
                                      public content::WebContentsObserver {
 public:
  explicit ActiveTaskContextProviderImpl(
      BrowserWindowInterface* browser_window,
      ContextualTasksService* contextual_tasks_service);
  ~ActiveTaskContextProviderImpl() override;

  ActiveTaskContextProviderImpl(const ActiveTaskContextProviderImpl&) = delete;
  ActiveTaskContextProviderImpl& operator=(
      const ActiveTaskContextProviderImpl&) = delete;

  // ActiveTaskContextProvider implementation.
  void RefreshContext() override;
  void SetContextualTasksPanelController(
      ContextualTasksPanelController* contextual_tasks_panel_controller)
      override;
  void AddLocalTabUnderline(tabs::TabHandle tab_handle) override;
  void RemoveLocalTabUnderline(tabs::TabHandle tab_handle) override;
  void ClearAllLocalTabUnderlines() override;
  void AddObserver(ActiveTaskContextProvider::Observer* observer) override;
  void RemoveObserver(ActiveTaskContextProvider::Observer* observer) override;

  // ContextualTasksService::Observer implementation.
  void OnTaskAdded(const ContextualTask& task,
                   ContextualTasksService::TriggerSource source) override;
  void OnTaskUpdated(const ContextualTask& task,
                     ContextualTasksService::TriggerSource source) override;
  void OnTaskRemoved(const base::Uuid& task_id,
                     ContextualTasksService::TriggerSource source) override;
  void OnTaskAssociatedToTab(const base::Uuid& task_id,
                             SessionID tab_id) override;
  void OnTaskDisassociatedFromTab(const base::Uuid& task_id,
                                  SessionID tab_id) override;
  void PrimaryPageChanged(content::Page& page) override;

 private:
  // TabListInterfaceObserver overrides:
  void OnActiveTabChanged(TabListInterface& tab_list,
                          tabs::TabInterface* tab) override;

  // Callback for when GetContextForTask() completes.
  void OnGetContextForTask(int callback_id,
                           std::unique_ptr<ContextualTaskContext> context);

  void ResetStateAndNotifyObservers();
  void NotifyObservers();

  raw_ptr<BrowserWindowInterface> browser_window_;
  raw_ptr<ContextualTasksService> contextual_tasks_service_;
  raw_ptr<ContextualTasksPanelController> contextual_tasks_panel_controller_;
  std::map<tabs::TabHandle, std::set<tabs::TabHandle>> local_tab_underlines_;
  std::set<tabs::TabHandle> backend_context_tabs_;
  base::WeakPtr<contextual_search::ContextualSearchSessionHandle>
      session_handle_;

  // The task associated with the currently active tab.
  std::optional<base::Uuid> active_task_id_;

  // An autoincrementing callback ID to filter out stale requests.
  int callback_id_ = 0;

  base::ObserverList<ActiveTaskContextProvider::Observer> observers_;

  // Scoped observation for contextual_tasks_service_.
  base::ScopedObservation<ContextualTasksService,
                          ContextualTasksService::Observer>
      contextual_tasks_service_observation_{this};

  ui::ScopedUnownedUserData<ActiveTaskContextProvider>
      scoped_unowned_user_data_;

  base::WeakPtrFactory<ActiveTaskContextProviderImpl> weak_ptr_factory_{this};
};

}  // namespace contextual_tasks

#endif  // CHROME_BROWSER_CONTEXTUAL_TASKS_ACTIVE_TASK_CONTEXT_PROVIDER_IMPL_H_
