// Copyright (c) 2012 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 "ash/public/cpp/test/shell_test_api.h"

#include <memory>
#include <utility>

#include "ash/accelerators/accelerator_commands.h"
#include "ash/accelerators/accelerator_controller_impl.h"
#include "ash/accelerometer/accelerometer_reader.h"
#include "ash/app_list/app_list_controller_impl.h"
#include "ash/app_list/app_list_presenter_impl.h"
#include "ash/app_list/views/app_list_view.h"
#include "ash/hud_display/hud_display.h"
#include "ash/keyboard/keyboard_controller_impl.h"
#include "ash/public/cpp/autotest_private_api_utils.h"
#include "ash/public/cpp/tablet_mode_observer.h"
#include "ash/root_window_controller.h"
#include "ash/shell.h"
#include "ash/system/message_center/session_state_notification_blocker.h"
#include "ash/system/power/backlights_forced_off_setter.h"
#include "ash/system/power/power_button_controller.h"
#include "ash/wm/overview/overview_animation_state_waiter.h"
#include "ash/wm/overview/overview_controller.h"
#include "ash/wm/splitview/split_view_controller.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h"
#include "ash/wm/workspace_controller.h"
#include "base/bind.h"
#include "base/run_loop.h"
#include "components/prefs/testing_pref_service.h"
#include "ui/aura/window_tree_host.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/compositor_observer.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/display/manager/display_manager.h"
#include "ui/events/devices/device_data_manager_test_api.h"
#include "ui/events/gesture_detection/gesture_configuration.h"

namespace ash {
namespace {

// Wait for a WindowTreeHost to no longer be holding pointer events.
class PointerMoveLoopWaiter : public ui::CompositorObserver {
 public:
  explicit PointerMoveLoopWaiter(aura::WindowTreeHost* window_tree_host)
      : window_tree_host_(window_tree_host) {
    window_tree_host_->compositor()->AddObserver(this);
  }

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

  ~PointerMoveLoopWaiter() override {
    window_tree_host_->compositor()->RemoveObserver(this);
  }

  void Wait() {
    // Use a while loop as it's possible for releasing the lock to trigger
    // processing events, which again grabs the lock.
    while (window_tree_host_->holding_pointer_moves()) {
      run_loop_ = std::make_unique<base::RunLoop>(
          base::RunLoop::Type::kNestableTasksAllowed);
      run_loop_->Run();
      run_loop_.reset();
    }
  }

  // ui::CompositorObserver:
  void OnCompositingEnded(ui::Compositor* compositor) override {
    if (run_loop_)
      run_loop_->Quit();
  }

 private:
  aura::WindowTreeHost* window_tree_host_;
  std::unique_ptr<base::RunLoop> run_loop_;
};

class WindowAnimationWaiter : public ui::LayerAnimationObserver {
 public:
  explicit WindowAnimationWaiter(aura::Window* window)
      : animator_(window->layer()->GetAnimator()) {
    animator_->AddObserver(this);
  }
  ~WindowAnimationWaiter() override = default;

  WindowAnimationWaiter(const WindowAnimationWaiter& other) = delete;
  WindowAnimationWaiter& operator=(const WindowAnimationWaiter& rhs) = delete;

  // ui::LayerAnimationObserver:
  void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override {
    if (!animator_->is_animating()) {
      animator_->RemoveObserver(this);
      run_loop_.Quit();
    }
  }
  void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override {}
  void OnLayerAnimationScheduled(
      ui::LayerAnimationSequence* sequence) override {}

  void Wait() {
    run_loop_.Run();
  }

 private:
  ui::LayerAnimator* animator_;
  base::RunLoop run_loop_;
};

}  // namespace

ShellTestApi::ShellTestApi() : shell_(Shell::Get()) {}
ShellTestApi::~ShellTestApi() = default;

// static
void ShellTestApi::SetTabletControllerUseScreenshotForTest(
    bool use_screenshot) {
  TabletModeController::SetUseScreenshotForTest(use_screenshot);
}

// static
void ShellTestApi::SetUseLoginNotificationDelayForTest(bool use_delay) {
  SessionStateNotificationBlocker::SetUseLoginNotificationDelayForTest(
      use_delay);
}

// static
void ShellTestApi::SetShouldShowShortcutNotificationForTest(
    bool show_notification) {
  AcceleratorControllerImpl::SetShouldShowShortcutNotificationForTest(
      show_notification);
}

MessageCenterController* ShellTestApi::message_center_controller() {
  return shell_->message_center_controller_.get();
}

WorkspaceController* ShellTestApi::workspace_controller() {
  // TODO(afakhry): Split this into two, one for root, and one for context.
  return GetActiveWorkspaceController(shell_->GetPrimaryRootWindow());
}

ScreenPositionController* ShellTestApi::screen_position_controller() {
  return shell_->screen_position_controller_.get();
}

NativeCursorManagerAsh* ShellTestApi::native_cursor_manager_ash() {
  return shell_->native_cursor_manager_;
}

DragDropController* ShellTestApi::drag_drop_controller() {
  return shell_->drag_drop_controller_.get();
}

PowerPrefs* ShellTestApi::power_prefs() {
  return shell_->power_prefs_.get();
}

display::DisplayManager* ShellTestApi::display_manager() {
  return shell_->display_manager();
}

void ShellTestApi::ResetPowerButtonControllerForTest() {
  shell_->backlights_forced_off_setter_->ResetForTest();
  shell_->power_button_controller_ = std::make_unique<PowerButtonController>(
      shell_->backlights_forced_off_setter_.get());
}

void ShellTestApi::SimulateModalWindowOpenForTest(bool modal_window_open) {
  shell_->simulate_modal_window_open_for_test_ = modal_window_open;
}

bool ShellTestApi::IsSystemModalWindowOpen() {
  return Shell::IsSystemModalWindowOpen();
}

void ShellTestApi::SetTabletModeEnabledForTest(bool enable) {
  // Detach mouse devices, so we can enter tablet mode.
  // Calling RunUntilIdle() here is necessary before setting the mouse devices
  // to prevent the callback from evdev thread from overwriting whatever we set
  // here below. See `InputDeviceFactoryEvdevProxy::OnStartupScanComplete()`.
  base::RunLoop().RunUntilIdle();
  ui::DeviceDataManagerTestApi().OnDeviceListsComplete();
  ui::DeviceDataManagerTestApi().SetMouseDevices({});

  TabletMode::Waiter waiter(enable);
  shell_->tablet_mode_controller()->SetEnabledForTest(enable);
  waiter.Wait();
}

void ShellTestApi::EnableVirtualKeyboard() {
  shell_->keyboard_controller()->SetEnableFlag(
      keyboard::KeyboardEnableFlag::kCommandLineEnabled);
}

void ShellTestApi::ToggleFullscreen() {
  accelerators::ToggleFullscreen();
}

void ShellTestApi::AddRemoveDisplay() {
  shell_->display_manager()->AddRemoveDisplay();
}

void ShellTestApi::WaitForNoPointerHoldLock() {
  aura::WindowTreeHost* primary_host =
      Shell::GetPrimaryRootWindowController()->GetHost();
  if (primary_host->holding_pointer_moves())
    PointerMoveLoopWaiter(primary_host).Wait();
}

void ShellTestApi::WaitForNextFrame(base::OnceClosure closure) {
  Shell::GetPrimaryRootWindowController()
      ->GetHost()
      ->compositor()
      ->RequestPresentationTimeForNextFrame(base::BindOnce(
          [](base::OnceClosure closure,
             const gfx::PresentationFeedback& feedback) {
            std::move(closure).Run();
          },
          std::move(closure)));
}

void ShellTestApi::WaitForOverviewAnimationState(OverviewAnimationState state) {
  auto* overview_controller = shell_->overview_controller();
  if (state == OverviewAnimationState::kEnterAnimationComplete &&
      overview_controller->InOverviewSession() &&
      !overview_controller->IsInStartAnimation()) {
    // If there is no animation applied, call the callback immediately.
    return;
  }
  if (state == OverviewAnimationState::kExitAnimationComplete &&
      !overview_controller->InOverviewSession() &&
      !overview_controller->IsCompletingShutdownAnimations()) {
    // If there is no animation applied, call the callback immediately.
    return;
  }
  base::RunLoop run_loop;
  new OverviewAnimationStateWaiter(
      state, base::BindOnce([](base::RunLoop* run_loop,
                               bool finished) { run_loop->QuitWhenIdle(); },
                            base::Unretained(&run_loop)));
  run_loop.Run();
}

void ShellTestApi::WaitForLauncherAnimationState(
    AppListViewState target_state) {
  base::RunLoop run_loop;
  WaitForLauncherState(target_state, run_loop.QuitWhenIdleClosure());
  run_loop.Run();
}

void ShellTestApi::WaitForWindowFinishAnimating(aura::Window* window) {
  WindowAnimationWaiter waiter(window);
  waiter.Wait();
}

base::OnceClosure ShellTestApi::CreateWaiterForFinishingWindowAnimation(
    aura::Window* window) {
  auto waiter = std::make_unique<WindowAnimationWaiter>(window);
  return base::BindOnce(&WindowAnimationWaiter::Wait, std::move(waiter));
}

PaginationModel* ShellTestApi::GetAppListPaginationModel() {
  AppListView* view =
      Shell::Get()->app_list_controller()->presenter()->GetView();
  if (!view)
    return nullptr;
  return view->GetAppsPaginationModel();
}

bool ShellTestApi::IsContextMenuShown() const {
  return Shell::GetPrimaryRootWindowController()->IsContextMenuShown();
}

bool ShellTestApi::IsActionForAcceleratorEnabled(
    const ui::Accelerator& accelerator) const {
  auto* controller = Shell::Get()->accelerator_controller();
  return AcceleratorControllerImpl::TestApi(controller)
      .IsActionForAcceleratorEnabled(accelerator);
}

bool ShellTestApi::PressAccelerator(const ui::Accelerator& accelerator) {
  return Shell::Get()->accelerator_controller()->AcceleratorPressed(
      accelerator);
}

bool ShellTestApi::IsHUDShown() {
  return hud_display::HUDDisplayView::IsShown();
}

}  // namespace ash
