// Copyright 2012 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_EXTENSIONS_API_TABS_WINDOWS_EVENT_ROUTER_H_
#define CHROME_BROWSER_EXTENSIONS_API_TABS_WINDOWS_EVENT_ROUTER_H_

#include <memory>
#include <string>

#include "base/memory/raw_ptr.h"
#include "base/scoped_observation.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/window_controller_list.h"
#include "chrome/browser/extensions/window_controller_list_observer.h"
#include "extensions/browser/extension_event_histogram_value.h"
#include "extensions/buildflags/buildflags.h"

#if BUILDFLAG(ENABLE_PLATFORM_APPS)
#include "chrome/browser/extensions/api/tabs/app_window_helper.h"
#endif

#if defined(TOOLKIT_VIEWS) && !BUILDFLAG(IS_MAC)
#include "ui/views/focus/native_view_focus_manager.h"  // nogncheck
#endif

#if BUILDFLAG(IS_MAC)
#include "chrome/browser/mac/key_window_notifier.h"
#endif

static_assert(BUILDFLAG(ENABLE_EXTENSIONS_CORE));

class Profile;

namespace extensions {

// The WindowsEventRouter sends chrome.windows.* events to listeners
// inside extension process renderers. The router listens to *all* events,
// but will only route events within a profile to extension processes in the
// same profile.
class WindowsEventRouter :
#if BUILDFLAG(IS_MAC)
    public KeyWindowNotifier::Observer,
#elif defined(TOOLKIT_VIEWS)
    public views::NativeViewFocusChangeListener,
#endif
    public WindowControllerListObserver {
 public:
  explicit WindowsEventRouter(Profile* profile);

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

  ~WindowsEventRouter() override;

  // `window_controller` is NULL to indicate a focused window has lost focus.
  void OnActiveWindowChanged(WindowController* window_controller);

 private:
  // WindowControllerListObserver methods:
  void OnWindowControllerAdded(WindowController* window_controller) override;
  void OnWindowControllerRemoved(WindowController* window) override;
  void OnWindowBoundsChanged(WindowController* window_controller) override;
  void OnWindowFocusChanged(WindowController* window_controller,
                            bool has_focus) override;

#if defined(TOOLKIT_VIEWS) && !BUILDFLAG(IS_MAC)
  void OnNativeFocusChanged(gfx::NativeView focused_now) override;
#endif

#if BUILDFLAG(IS_MAC)
  // KeyWindowNotifier::Observer:
  void OnNoKeyWindow() override;
#endif

  void DispatchEvent(events::HistogramValue histogram_value,
                     const std::string& event_name,
                     WindowController* window_controller,
                     base::ListValue args);
  bool HasEventListener(const std::string& event_name);

  // The main profile that owns this event router.
  raw_ptr<Profile, DanglingUntriaged> profile_;

#if BUILDFLAG(ENABLE_PLATFORM_APPS)
  AppWindowHelper app_window_helper_;
#endif

  // The currently focused window. We keep this so as to avoid sending multiple
  // windows.onFocusChanged events with the same windowId.
  int focused_window_id_;

  // Observed WindowControllerList.
  base::ScopedObservation<WindowControllerList, WindowControllerListObserver>
      observed_controller_list_{this};

#if BUILDFLAG(IS_MAC)
  base::ScopedObservation<KeyWindowNotifier, KeyWindowNotifier::Observer>
      observed_key_window_notifier_{this};
#endif
};

}  // namespace extensions

#endif  // CHROME_BROWSER_EXTENSIONS_API_TABS_WINDOWS_EVENT_ROUTER_H_
