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

#include "extensions/shell/browser/shell_desktop_controller_aura.h"

#include <algorithm>
#include <string>

#include "base/logging.h"
#include "base/run_loop.h"
#include "components/keep_alive_registry/keep_alive_registry.h"
#include "extensions/browser/app_window/app_window.h"
#include "extensions/browser/app_window/native_app_window.h"
#include "extensions/shell/browser/shell_app_window_client.h"
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/image_cursors.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/ime/input_method_factory.h"
#include "ui/display/screen.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/wm/core/base_focus_rules.h"
#include "ui/wm/core/compound_event_filter.h"
#include "ui/wm/core/cursor_manager.h"
#include "ui/wm/core/focus_controller.h"
#include "ui/wm/core/native_cursor_manager.h"
#include "ui/wm/core/native_cursor_manager_delegate.h"

#if defined(OS_CHROMEOS)
#include "base/command_line.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "extensions/shell/browser/shell_screen.h"
#include "extensions/shell/common/switches.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
#include "ui/base/user_activity/user_activity_detector.h"
#include "ui/chromeos/user_activity_power_manager_notifier.h"
#include "ui/display/types/display_mode.h"
#include "ui/display/types/display_snapshot.h"
#include "ui/display/types/native_display_delegate.h"
#include "ui/ozone/public/ozone_platform.h"  // nogncheck
#else
#include "ui/views/widget/desktop_aura/desktop_screen.h"
#endif  // defined(OS_CHROMEOS)

namespace extensions {
namespace {

// A class that bridges the gap between CursorManager and Aura. It borrows
// heavily from NativeCursorManagerAsh.
class ShellNativeCursorManager : public wm::NativeCursorManager {
 public:
  explicit ShellNativeCursorManager(
      ShellDesktopControllerAura* desktop_controller)
      : desktop_controller_(desktop_controller),
        image_cursors_(new ui::ImageCursors) {}
  ~ShellNativeCursorManager() override {}

  // wm::NativeCursorManager overrides.
  void SetDisplay(const display::Display& display,
                  wm::NativeCursorManagerDelegate* delegate) override {
    if (image_cursors_->SetDisplay(display, display.device_scale_factor()))
      SetCursor(delegate->GetCursor(), delegate);
  }

  void SetCursor(gfx::NativeCursor cursor,
                 wm::NativeCursorManagerDelegate* delegate) override {
    image_cursors_->SetPlatformCursor(&cursor);
    cursor.set_device_scale_factor(image_cursors_->GetScale());
    delegate->CommitCursor(cursor);

    if (delegate->IsCursorVisible())
      SetCursorOnAllRootWindows(cursor);
  }

  void SetVisibility(bool visible,
                     wm::NativeCursorManagerDelegate* delegate) override {
    delegate->CommitVisibility(visible);

    if (visible) {
      SetCursor(delegate->GetCursor(), delegate);
    } else {
      gfx::NativeCursor invisible_cursor(ui::CursorType::kNone);
      image_cursors_->SetPlatformCursor(&invisible_cursor);
      SetCursorOnAllRootWindows(invisible_cursor);
    }
  }

  void SetCursorSize(ui::CursorSize cursor_size,
                     wm::NativeCursorManagerDelegate* delegate) override {
    image_cursors_->SetCursorSize(cursor_size);
    delegate->CommitCursorSize(cursor_size);
    if (delegate->IsCursorVisible())
      SetCursor(delegate->GetCursor(), delegate);
  }

  void SetMouseEventsEnabled(
      bool enabled,
      wm::NativeCursorManagerDelegate* delegate) override {
    delegate->CommitMouseEventsEnabled(enabled);
    SetVisibility(delegate->IsCursorVisible(), delegate);
  }

 private:
  // Sets |cursor| as the active cursor within Aura.
  void SetCursorOnAllRootWindows(gfx::NativeCursor cursor) {
    for (auto* window : desktop_controller_->GetAllRootWindows())
      window->GetHost()->SetCursor(cursor);
  }

  ShellDesktopControllerAura* desktop_controller_;  // Not owned.

  std::unique_ptr<ui::ImageCursors> image_cursors_;

  DISALLOW_COPY_AND_ASSIGN(ShellNativeCursorManager);
};

class AppsFocusRules : public wm::BaseFocusRules {
 public:
  AppsFocusRules() {}
  ~AppsFocusRules() override {}

  bool SupportsChildActivation(const aura::Window* window) const override {
    return true;
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(AppsFocusRules);
};

}  // namespace

ShellDesktopControllerAura::ShellDesktopControllerAura(
    content::BrowserContext* browser_context)
    : browser_context_(browser_context),
      app_window_client_(new ShellAppWindowClient) {
  extensions::AppWindowClient::Set(app_window_client_.get());

#if defined(OS_CHROMEOS)
  chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver(
      this);
  display_configurator_.reset(new display::DisplayConfigurator);
  display_configurator_->Init(
      ui::OzonePlatform::GetInstance()->CreateNativeDisplayDelegate(), false);
  display_configurator_->ForceInitialConfigure();
  display_configurator_->AddObserver(this);
#endif

  InitWindowManager();
}

ShellDesktopControllerAura::~ShellDesktopControllerAura() {
  TearDownWindowManager();
#if defined(OS_CHROMEOS)
  chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver(
      this);
#endif
  extensions::AppWindowClient::Set(NULL);
}

void ShellDesktopControllerAura::Run() {
  KeepAliveRegistry::GetInstance()->AddObserver(this);

  base::RunLoop run_loop;
  run_loop_ = &run_loop;
  run_loop.Run();
  run_loop_ = nullptr;

  KeepAliveRegistry::GetInstance()->SetIsShuttingDown(true);
  KeepAliveRegistry::GetInstance()->RemoveObserver(this);
}

void ShellDesktopControllerAura::AddAppWindow(AppWindow* app_window,
                                              gfx::NativeWindow window) {
  // Find the closest display to the specified bounds.
  const display::Display& display =
      display::Screen::GetScreen()->GetDisplayMatching(
          window->GetBoundsInScreen());

  // Create a RootWindowController for the display if necessary.
  if (root_window_controllers_.count(display.id()) == 0) {
    root_window_controllers_[display.id()] =
        CreateRootWindowControllerForDisplay(display);
  }
  root_window_controllers_[display.id()]->AddAppWindow(app_window, window);
}

void ShellDesktopControllerAura::CloseAppWindows() {
  for (auto& pair : root_window_controllers_)
    pair.second->CloseAppWindows();
}

void ShellDesktopControllerAura::CloseRootWindowController(
    RootWindowController* root_window_controller) {
  const auto it = std::find_if(
      root_window_controllers_.cbegin(), root_window_controllers_.cend(),
      [root_window_controller](const auto& candidate_pair) {
        return candidate_pair.second.get() == root_window_controller;
      });
  DCHECK(it != root_window_controllers_.end());
  TearDownRootWindowController(it->second.get());
  root_window_controllers_.erase(it);

  MaybeQuit();
}

#if defined(OS_CHROMEOS)
void ShellDesktopControllerAura::PowerButtonEventReceived(
    bool down,
    const base::TimeTicks& timestamp) {
  if (down) {
    chromeos::DBusThreadManager::Get()
        ->GetPowerManagerClient()
        ->RequestShutdown(power_manager::REQUEST_SHUTDOWN_FOR_USER,
                          "AppShell power button");
  }
}

void ShellDesktopControllerAura::OnDisplayModeChanged(
    const display::DisplayConfigurator::DisplayStateList& displays) {
  for (const display::DisplaySnapshot* display_mode : displays) {
    if (!display_mode->current_mode())
      continue;
    auto it = root_window_controllers_.find(display_mode->display_id());
    if (it != root_window_controllers_.end())
      it->second->UpdateSize(display_mode->current_mode()->size());
  }
}
#endif

ui::EventDispatchDetails ShellDesktopControllerAura::DispatchKeyEventPostIME(
    ui::KeyEvent* key_event,
    base::OnceCallback<void(bool)> ack_callback) {
  if (key_event->target()) {
    aura::WindowTreeHost* host = static_cast<aura::Window*>(key_event->target())
                                     ->GetRootWindow()
                                     ->GetHost();
    return host->DispatchKeyEventPostIME(key_event, std::move(ack_callback));
  }

  // Send the key event to the focused window.
  aura::Window* active_window =
      const_cast<aura::Window*>(focus_controller_->GetActiveWindow());
  if (active_window) {
    return active_window->GetRootWindow()->GetHost()->DispatchKeyEventPostIME(
        key_event, std::move(ack_callback));
  }

  return GetPrimaryHost()->DispatchKeyEventPostIME(key_event,
                                                   std::move(ack_callback));
}

void ShellDesktopControllerAura::OnKeepAliveStateChanged(
    bool is_keeping_alive) {
  if (!is_keeping_alive)
    MaybeQuit();
}

void ShellDesktopControllerAura::OnKeepAliveRestartStateChanged(
    bool can_restart) {}

aura::WindowTreeHost* ShellDesktopControllerAura::GetPrimaryHost() {
  if (root_window_controllers_.empty())
    return nullptr;

  const display::Display& display =
      display::Screen::GetScreen()->GetPrimaryDisplay();
  if (root_window_controllers_.count(display.id()) == 1)
    return root_window_controllers_[display.id()]->host();

  // Fall back to an existing host.
  return root_window_controllers_.begin()->second->host();
}

aura::Window::Windows ShellDesktopControllerAura::GetAllRootWindows() {
  aura::Window::Windows windows;
  for (auto& pair : root_window_controllers_)
    windows.push_back(pair.second->host()->window());
  return windows;
}

void ShellDesktopControllerAura::SetWindowBoundsInScreen(
    AppWindow* app_window,
    const gfx::Rect& bounds) {
  display::Display display =
      display::Screen::GetScreen()->GetDisplayMatching(bounds);

  // Create a RootWindowController for the display if necessary.
  if (root_window_controllers_.count(display.id()) == 0) {
    root_window_controllers_[display.id()] =
        CreateRootWindowControllerForDisplay(display);
  }

  // Check if the window is parented to a different RootWindowController.
  if (app_window->GetNativeWindow()->GetRootWindow() !=
      root_window_controllers_[display.id()]->host()->window()) {
    // Move the window to the appropriate RootWindowController for the display.
    for (const auto& it : root_window_controllers_) {
      if (it.second->host()->window() ==
          app_window->GetNativeWindow()->GetRootWindow()) {
        it.second->RemoveAppWindow(app_window);
        break;
      }
    }
    root_window_controllers_[display.id()]->AddAppWindow(
        app_window, app_window->GetNativeWindow());
  }

  app_window->GetNativeWindow()->SetBoundsInScreen(bounds, display);
}

void ShellDesktopControllerAura::InitWindowManager() {
  root_window_event_filter_ = std::make_unique<wm::CompoundEventFilter>();

  // Screen may be initialized in tests.
  if (!display::Screen::GetScreen()) {
#if defined(OS_CHROMEOS)
    screen_ = std::make_unique<ShellScreen>(this, GetStartingWindowSize());
#else
    // TODO(crbug.com/756680): Refactor DesktopScreen out of views.
    screen_.reset(views::CreateDesktopScreen());
#endif
    display::Screen::SetScreenInstance(screen_.get());
  }

  focus_controller_ =
      std::make_unique<wm::FocusController>(new AppsFocusRules());
  cursor_manager_ = std::make_unique<wm::CursorManager>(
      std::make_unique<ShellNativeCursorManager>(this));
  cursor_manager_->SetDisplay(
      display::Screen::GetScreen()->GetPrimaryDisplay());
  cursor_manager_->SetCursor(ui::CursorType::kPointer);

#if defined(OS_CHROMEOS)
  user_activity_detector_ = std::make_unique<ui::UserActivityDetector>();
  user_activity_notifier_ =
      std::make_unique<ui::UserActivityPowerManagerNotifier>(
          user_activity_detector_.get(), nullptr /*connector*/);
#endif
}

void ShellDesktopControllerAura::TearDownWindowManager() {
  for (auto& pair : root_window_controllers_)
    TearDownRootWindowController(pair.second.get());
  root_window_controllers_.clear();

#if defined(OS_CHROMEOS)
  user_activity_notifier_.reset();
  user_activity_detector_.reset();
#endif
  cursor_manager_.reset();
  focus_controller_.reset();
  if (screen_) {
    display::Screen::SetScreenInstance(nullptr);
    screen_.reset();
  }
  root_window_event_filter_.reset();
}

std::unique_ptr<RootWindowController>
ShellDesktopControllerAura::CreateRootWindowControllerForDisplay(
    const display::Display& display) {
  // Convert display's bounds from DIP to physical pixels for WindowTreeHost.
  gfx::Rect bounds(gfx::ScaleToFlooredPoint(display.bounds().origin(),
                                            display.device_scale_factor()),
                   display.GetSizeInPixel());
  std::unique_ptr<RootWindowController> root_window_controller =
      std::make_unique<RootWindowController>(this, bounds, browser_context_);

  // Initialize the root window with our clients.
  aura::Window* root_window = root_window_controller->host()->window();
  root_window->AddPreTargetHandler(root_window_event_filter_.get());
  aura::client::SetFocusClient(root_window, focus_controller_.get());
  root_window->AddPreTargetHandler(focus_controller_.get());
  wm::SetActivationClient(root_window, focus_controller_.get());
  aura::client::SetCursorClient(root_window, cursor_manager_.get());

  if (!input_method_) {
    // Create an input method and become its delegate.
    input_method_ = ui::CreateInputMethod(
        this, root_window_controller->host()->GetAcceleratedWidget());
    root_window_controller->host()->SetSharedInputMethod(input_method_.get());
  }

  return root_window_controller;
}

void ShellDesktopControllerAura::TearDownRootWindowController(
    RootWindowController* root) {
  root->host()->window()->RemovePreTargetHandler(
      root_window_event_filter_.get());
  root->host()->window()->RemovePreTargetHandler(focus_controller_.get());
}

void ShellDesktopControllerAura::MaybeQuit() {
  // run_loop_ may be null in tests.
  if (!run_loop_)
    return;

  // Quit if there are no app windows open and no keep-alives waiting for apps
  // to relaunch.
  if (root_window_controllers_.empty() &&
      !KeepAliveRegistry::GetInstance()->IsKeepingAlive()) {
    run_loop_->QuitWhenIdle();
  }
}

#if defined(OS_CHROMEOS)
gfx::Size ShellDesktopControllerAura::GetStartingWindowSize() {
  gfx::Size size;
  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
  if (command_line->HasSwitch(switches::kAppShellHostWindowSize)) {
    const std::string size_str =
        command_line->GetSwitchValueASCII(switches::kAppShellHostWindowSize);
    int width, height;
    CHECK_EQ(2, sscanf(size_str.c_str(), "%dx%d", &width, &height));
    size = gfx::Size(width, height);
  } else {
    size = GetPrimaryDisplaySize();
  }
  if (size.IsEmpty())
    size = gfx::Size(1920, 1080);
  return size;
}

gfx::Size ShellDesktopControllerAura::GetPrimaryDisplaySize() {
  const display::DisplayConfigurator::DisplayStateList& displays =
      display_configurator_->cached_displays();
  if (displays.empty())
    return gfx::Size();
  const display::DisplayMode* mode = displays[0]->current_mode();
  return mode ? mode->size() : gfx::Size();
  return gfx::Size();
}
#endif

}  // namespace extensions
