// 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/test/ash_test_base.h"

#include <map>
#include <memory>
#include <string>
#include <vector>

#include "ash/app_list/test/app_list_test_helper.h"
#include "ash/display/extended_mouse_warp_controller.h"
#include "ash/display/mouse_cursor_event_filter.h"
#include "ash/display/screen_orientation_controller_test_api.h"
#include "ash/display/unified_mouse_warp_controller.h"
#include "ash/display/window_tree_host_manager.h"
#include "ash/keyboard/ash_keyboard_controller.h"
#include "ash/public/cpp/window_properties.h"
#include "ash/root_window_controller.h"
#include "ash/session/session_controller.h"
#include "ash/session/test_session_controller_client.h"
#include "ash/shelf/shelf.h"
#include "ash/shell.h"
#include "ash/shell/toplevel_window.h"
#include "ash/system/status_area_widget.h"
#include "ash/test/ash_test_helper.h"
#include "ash/test_screenshot_delegate.h"
#include "ash/test_shell_delegate.h"
#include "ash/utility/screenshot_controller.h"
#include "ash/window_factory.h"
#include "ash/wm/top_level_window_factory.h"
#include "ash/wm/window_positioner.h"
#include "ash/ws/window_service_owner.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/test/scoped_task_environment.h"
#include "chromeos/dbus/fake_power_manager_client.h"
#include "components/account_id/account_id.h"
#include "components/user_manager/user_names.h"
#include "mojo/public/cpp/bindings/map.h"
#include "services/ws/public/cpp/property_type_converters.h"
#include "services/ws/public/mojom/window_manager.mojom.h"
#include "services/ws/public/mojom/window_tree_constants.mojom.h"
#include "services/ws/test_window_tree_client.h"
#include "services/ws/window_service.h"
#include "services/ws/window_tree.h"
#include "services/ws/window_tree_test_helper.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/window_parenting_client.h"
#include "ui/aura/env.h"
#include "ui/aura/mus/property_converter.h"
#include "ui/aura/test/aura_test_utils.h"
#include "ui/aura/test/env_test_helper.h"
#include "ui/aura/test/event_generator_delegate_aura.h"
#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/ime/input_method_initializer.h"
#include "ui/base/ui_base_features.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/display/test/display_manager_test_api.h"
#include "ui/display/types/display_constants.h"
#include "ui/events/gesture_detection/gesture_configuration.h"
#include "ui/gfx/geometry/point.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/core/coordinate_conversion.h"

using session_manager::SessionState;

namespace ash {
namespace {

class AshEventGeneratorDelegate
    : public aura::test::EventGeneratorDelegateAura {
 public:
  AshEventGeneratorDelegate() = default;
  ~AshEventGeneratorDelegate() override = default;

  // aura::test::EventGeneratorDelegateAura overrides:
  ui::EventTarget* GetTargetAt(const gfx::Point& point_in_screen) override {
    display::Screen* screen = display::Screen::GetScreen();
    display::Display display = screen->GetDisplayNearestPoint(point_in_screen);
    return Shell::GetRootWindowForDisplayId(display.id())->GetHost()->window();
  }

  ui::EventDispatchDetails DispatchKeyEventToIME(ui::EventTarget* target,
                                                 ui::KeyEvent* event) override {
    // In Ash environment, the key event will be processed by event rewriters
    // first.
    return ui::EventDispatchDetails();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(AshEventGeneratorDelegate);
};

ws::mojom::WindowType MusWindowTypeFromWindowType(
    aura::client::WindowType window_type) {
  switch (window_type) {
    case aura::client::WINDOW_TYPE_UNKNOWN:
      break;

    case aura::client::WINDOW_TYPE_NORMAL:
      return ws::mojom::WindowType::WINDOW;

    case aura::client::WINDOW_TYPE_POPUP:
      return ws::mojom::WindowType::POPUP;

    case aura::client::WINDOW_TYPE_CONTROL:
      return ws::mojom::WindowType::CONTROL;

    case aura::client::WINDOW_TYPE_MENU:
      return ws::mojom::WindowType::MENU;

    case aura::client::WINDOW_TYPE_TOOLTIP:
      return ws::mojom::WindowType::TOOLTIP;
  }

  NOTREACHED();
  return ws::mojom::WindowType::CONTROL;
}

}  // namespace

/////////////////////////////////////////////////////////////////////////////

AshTestBase::AshTestBase()
    : scoped_task_environment_(
          std::make_unique<base::test::ScopedTaskEnvironment>(
              base::test::ScopedTaskEnvironment::MainThreadType::UI)) {
  // Must initialize |ash_test_helper_| here because some tests rely on
  // AshTestBase methods before they call AshTestBase::SetUp().
  ash_test_helper_ = std::make_unique<AshTestHelper>();
}

AshTestBase::~AshTestBase() {
  CHECK(setup_called_)
      << "You have overridden SetUp but never called AshTestBase::SetUp";
  CHECK(teardown_called_)
      << "You have overridden TearDown but never called AshTestBase::TearDown";
}

void AshTestBase::SetUp() {
  setup_called_ = true;

  // Clears the saved state so that test doesn't use on the wrong
  // default state.
  shell::ToplevelWindow::ClearSavedStateForTest();

  ash_test_helper_->SetUp(start_session_, provide_local_state_);

  Shell::GetPrimaryRootWindow()->Show();
  Shell::GetPrimaryRootWindow()->GetHost()->Show();
  // Move the mouse cursor to far away so that native events doesn't
  // interfere test expectations.
  Shell::GetPrimaryRootWindow()->MoveCursorTo(gfx::Point(-1000, -1000));
  Shell::Get()->cursor_manager()->EnableMouseEvents();

  // Changing GestureConfiguration shouldn't make tests fail. These values
  // prevent unexpected events from being generated during tests. Such as
  // delayed events which create race conditions on slower tests.
  ui::GestureConfiguration* gesture_config =
      ui::GestureConfiguration::GetInstance();
  gesture_config->set_max_touch_down_duration_for_click_in_ms(800);
  gesture_config->set_long_press_time_in_ms(1000);
  gesture_config->set_max_touch_move_in_pixels_for_click(5);
}

void AshTestBase::TearDown() {
  teardown_called_ = true;
  Shell::Get()->session_controller()->NotifyChromeTerminating();

  // These depend upon WindowService, which is owned by Shell, so they must
  // be destroyed before the Shell (owned by AshTestHelper).
  window_tree_test_helper_.reset();
  window_tree_.reset();

  // Flush the message loop to finish pending release tasks.
  base::RunLoop().RunUntilIdle();

  ash_test_helper_->TearDown();

  event_generator_.reset();
  // Some tests set an internal display id,
  // reset it here, so other tests will continue in a clean environment.
  display::Display::SetInternalDisplayId(display::kInvalidDisplayId);
}

// static
Shelf* AshTestBase::GetPrimaryShelf() {
  return Shell::GetPrimaryRootWindowController()->shelf();
}

void AshTestBase::DestroyScopedTaskEnvironment() {
  scoped_task_environment_.reset();
}

// static
UnifiedSystemTray* AshTestBase::GetPrimaryUnifiedSystemTray() {
  return GetPrimaryShelf()->GetStatusAreaWidget()->unified_system_tray();
}

ui::test::EventGenerator* AshTestBase::GetEventGenerator() {
  if (!event_generator_) {
    event_generator_ = std::make_unique<ui::test::EventGenerator>(
        std::make_unique<AshEventGeneratorDelegate>());
  }
  return event_generator_.get();
}

// static
display::Display::Rotation AshTestBase::GetActiveDisplayRotation(int64_t id) {
  return Shell::Get()
      ->display_manager()
      ->GetDisplayInfo(id)
      .GetActiveRotation();
}

// static
display::Display::Rotation AshTestBase::GetCurrentInternalDisplayRotation() {
  return GetActiveDisplayRotation(display::Display::InternalDisplayId());
}

void AshTestBase::UpdateDisplay(const std::string& display_specs) {
  display::test::DisplayManagerTestApi(Shell::Get()->display_manager())
      .UpdateDisplay(display_specs);
  ScreenOrientationControllerTestApi(
      Shell::Get()->screen_orientation_controller())
      .UpdateNaturalOrientation();
}

void AshTestBase::SetRunningOutsideAsh() {
  ash_test_helper_->SetRunningOutsideAsh();
}

aura::Window* AshTestBase::CurrentContext() {
  return ash_test_helper_->CurrentContext();
}

// static
std::unique_ptr<views::Widget> AshTestBase::CreateTestWidget(
    views::WidgetDelegate* delegate,
    int container_id,
    const gfx::Rect& bounds) {
  std::unique_ptr<views::Widget> widget(new views::Widget);
  views::Widget::InitParams params;
  params.delegate = delegate;
  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
  params.bounds = bounds;
  params.parent = Shell::GetPrimaryRootWindow()->GetChildById(container_id);
  widget->Init(params);
  widget->Show();
  return widget;
}

std::map<std::string, std::vector<uint8_t>>
AshTestBase::CreatePropertiesForProxyWindow(const gfx::Rect& bounds_in_screen,
                                            aura::client::WindowType type) {
  // The following simulates what happens when a client creates a window.
  std::map<std::string, std::vector<uint8_t>> properties;
  if (!bounds_in_screen.IsEmpty()) {
    properties[ws::mojom::WindowManager::kBounds_InitProperty] =
        mojo::ConvertTo<std::vector<uint8_t>>(bounds_in_screen);
  }

  properties[ws::mojom::WindowManager::kResizeBehavior_Property] =
      mojo::ConvertTo<std::vector<uint8_t>>(
          static_cast<aura::PropertyConverter::PrimitiveType>(
              ws::mojom::kResizeBehaviorCanResize |
              ws::mojom::kResizeBehaviorCanMaximize |
              ws::mojom::kResizeBehaviorCanMinimize));

  const ws::mojom::WindowType mus_window_type =
      MusWindowTypeFromWindowType(type);
  properties[ws::mojom::WindowManager::kWindowType_InitProperty] =
      mojo::ConvertTo<std::vector<uint8_t>>(
          static_cast<int32_t>(mus_window_type));
  return properties;
}

std::unique_ptr<aura::Window> AshTestBase::CreateTestWindow(
    const gfx::Rect& bounds_in_screen,
    aura::client::WindowType type,
    int shell_window_id) {
  // WindowTreeTestHelper maps 0 to a unique id.
  std::unique_ptr<aura::Window> window(
      GetWindowTreeTestHelper()->NewTopLevelWindow(mojo::MapToFlatMap(
          CreatePropertiesForProxyWindow(bounds_in_screen, type))));
  window->set_id(shell_window_id);
  window->Show();
  return window;
}

std::unique_ptr<aura::Window> AshTestBase::CreateToplevelTestWindow(
    const gfx::Rect& bounds_in_screen,
    int shell_window_id) {
  aura::test::TestWindowDelegate* delegate =
      aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate();
  return base::WrapUnique<aura::Window>(
      CreateTestWindowInShellWithDelegateAndType(
          delegate, aura::client::WINDOW_TYPE_NORMAL, shell_window_id,
          bounds_in_screen));
}

aura::Window* AshTestBase::CreateTestWindowInShellWithId(int id) {
  return CreateTestWindowInShellWithDelegate(NULL, id, gfx::Rect());
}

aura::Window* AshTestBase::CreateTestWindowInShellWithBounds(
    const gfx::Rect& bounds) {
  return CreateTestWindowInShellWithDelegate(NULL, 0, bounds);
}

aura::Window* AshTestBase::CreateTestWindowInShell(SkColor color,
                                                   int id,
                                                   const gfx::Rect& bounds) {
  return CreateTestWindowInShellWithDelegate(
      new aura::test::ColorTestWindowDelegate(color), id, bounds);
}

std::unique_ptr<aura::Window> AshTestBase::CreateChildWindow(
    aura::Window* parent,
    const gfx::Rect& bounds,
    int shell_window_id) {
  std::unique_ptr<aura::Window> window =
      window_factory::NewWindow(nullptr, aura::client::WINDOW_TYPE_NORMAL);
  window->Init(ui::LAYER_NOT_DRAWN);
  window->SetBounds(bounds);
  window->set_id(shell_window_id);
  parent->AddChild(window.get());
  window->Show();
  return window;
}

aura::Window* AshTestBase::CreateTestWindowInShellWithDelegate(
    aura::WindowDelegate* delegate,
    int id,
    const gfx::Rect& bounds) {
  return CreateTestWindowInShellWithDelegateAndType(
      delegate, aura::client::WINDOW_TYPE_NORMAL, id, bounds);
}

aura::Window* AshTestBase::CreateTestWindowInShellWithDelegateAndType(
    aura::WindowDelegate* delegate,
    aura::client::WindowType type,
    int id,
    const gfx::Rect& bounds) {
  aura::Window* window = window_factory::NewWindow(delegate).release();
  window->set_id(id);
  window->SetType(type);
  window->Init(ui::LAYER_TEXTURED);

  if (bounds.IsEmpty()) {
    ParentWindowInPrimaryRootWindow(window);
  } else {
    display::Display display =
        display::Screen::GetScreen()->GetDisplayMatching(bounds);
    aura::Window* root = Shell::GetRootWindowForDisplayId(display.id());
    gfx::Point origin = bounds.origin();
    ::wm::ConvertPointFromScreen(root, &origin);
    window->SetBounds(gfx::Rect(origin, bounds.size()));
    aura::client::ParentWindowWithContext(window, root, bounds);
  }
  window->Show();

  window->SetProperty(aura::client::kResizeBehaviorKey,
                      ws::mojom::kResizeBehaviorCanMaximize |
                          ws::mojom::kResizeBehaviorCanMinimize |
                          ws::mojom::kResizeBehaviorCanResize);
  return window;
}

void AshTestBase::ParentWindowInPrimaryRootWindow(aura::Window* window) {
  aura::client::ParentWindowWithContext(window, Shell::GetPrimaryRootWindow(),
                                        gfx::Rect());
}

TestScreenshotDelegate* AshTestBase::GetScreenshotDelegate() {
  return static_cast<TestScreenshotDelegate*>(
      Shell::Get()->screenshot_controller()->screenshot_delegate_.get());
}

TestSessionControllerClient* AshTestBase::GetSessionControllerClient() {
  return ash_test_helper_->test_session_controller_client();
}

AppListTestHelper* AshTestBase::GetAppListTestHelper() {
  return ash_test_helper_->app_list_test_helper();
}

void AshTestBase::CreateUserSessions(int n) {
  GetSessionControllerClient()->CreatePredefinedUserSessions(n);
}

void AshTestBase::SimulateUserLogin(const std::string& user_email) {
  TestSessionControllerClient* const session_controller_client =
      GetSessionControllerClient();
  session_controller_client->AddUserSession(user_email);
  session_controller_client->SwitchActiveUser(
      AccountId::FromUserEmail(user_email));
  session_controller_client->SetSessionState(SessionState::ACTIVE);
}

void AshTestBase::SimulateNewUserFirstLogin(const std::string& user_email) {
  TestSessionControllerClient* const session_controller_client =
      GetSessionControllerClient();
  session_controller_client->AddUserSession(
      user_email, user_manager::USER_TYPE_REGULAR, true /* enable_settings */,
      true /* provide_pref_service */, true /* is_new_profile */);
  session_controller_client->SwitchActiveUser(
      AccountId::FromUserEmail(user_email));
  session_controller_client->SetSessionState(
      session_manager::SessionState::ACTIVE);
}

void AshTestBase::SimulateGuestLogin() {
  const std::string guest = user_manager::kGuestUserName;
  TestSessionControllerClient* session = GetSessionControllerClient();
  session->AddUserSession(guest, user_manager::USER_TYPE_GUEST);
  session->SwitchActiveUser(AccountId::FromUserEmail(guest));
  session->SetSessionState(SessionState::ACTIVE);
}

void AshTestBase::SimulateKioskMode(user_manager::UserType user_type) {
  DCHECK(user_type == user_manager::USER_TYPE_ARC_KIOSK_APP ||
         user_type == user_manager::USER_TYPE_KIOSK_APP);

  const std::string user_email = "fake_kiosk@kioks-apps.device-local.localhost";
  TestSessionControllerClient* session = GetSessionControllerClient();
  session->SetIsRunningInAppMode(true);
  session->AddUserSession(user_email, user_type);
  session->SwitchActiveUser(AccountId::FromUserEmail(user_email));
  session->SetSessionState(SessionState::ACTIVE);
}

void AshTestBase::ClearLogin() {
  GetSessionControllerClient()->Reset();
}

void AshTestBase::SetCanLockScreen(bool can_lock) {
  GetSessionControllerClient()->SetCanLockScreen(can_lock);
}

void AshTestBase::SetShouldLockScreenAutomatically(bool should_lock) {
  GetSessionControllerClient()->SetShouldLockScreenAutomatically(should_lock);
}

void AshTestBase::SetUserAddingScreenRunning(bool user_adding_screen_running) {
  GetSessionControllerClient()->SetSessionState(
      user_adding_screen_running ? SessionState::LOGIN_SECONDARY
                                 : SessionState::ACTIVE);
}

void AshTestBase::BlockUserSession(UserSessionBlockReason block_reason) {
  switch (block_reason) {
    case BLOCKED_BY_LOCK_SCREEN:
      CreateUserSessions(1);
      Shell::Get()->session_controller()->LockScreenAndFlushForTest();
      break;
    case BLOCKED_BY_LOGIN_SCREEN:
      ClearLogin();
      break;
    case BLOCKED_BY_USER_ADDING_SCREEN:
      SetUserAddingScreenRunning(true);
      break;
    default:
      NOTREACHED();
      break;
  }
}

void AshTestBase::UnblockUserSession() {
  CreateUserSessions(1);
  GetSessionControllerClient()->UnlockScreen();
}

void AshTestBase::SetTouchKeyboardEnabled(bool enabled) {
  auto flag = keyboard::mojom::KeyboardEnableFlag::kTouchEnabled;
  if (enabled)
    Shell::Get()->ash_keyboard_controller()->SetEnableFlag(flag);
  else
    Shell::Get()->ash_keyboard_controller()->ClearEnableFlag(flag);
  // Ensure that observer methods and mojo calls between AshKeyboardController,
  // keyboard::KeyboardController, and AshKeyboardUI complete.
  base::RunLoop().RunUntilIdle();
}

void AshTestBase::DisableIME() {
  aura::test::DisableIME(Shell::GetPrimaryRootWindow()->GetHost());
}

display::DisplayManager* AshTestBase::display_manager() {
  return Shell::Get()->display_manager();
}

chromeos::FakePowerManagerClient* AshTestBase::power_manager_client() const {
  return chromeos::FakePowerManagerClient::Get();
}

bool AshTestBase::TestIfMouseWarpsAt(ui::test::EventGenerator* event_generator,
                                     const gfx::Point& point_in_screen) {
  DCHECK(!Shell::Get()->display_manager()->IsInUnifiedMode());
  static_cast<ExtendedMouseWarpController*>(
      Shell::Get()->mouse_cursor_filter()->mouse_warp_controller_for_test())
      ->allow_non_native_event_for_test();
  display::Screen* screen = display::Screen::GetScreen();
  display::Display original_display =
      screen->GetDisplayNearestPoint(point_in_screen);
  event_generator->MoveMouseTo(point_in_screen);
  return original_display.id() !=
         screen
             ->GetDisplayNearestPoint(
                 Shell::Get()->aura_env()->last_mouse_location())
             .id();
}

void AshTestBase::SwapPrimaryDisplay() {
  if (display::Screen::GetScreen()->GetNumDisplays() <= 1)
    return;
  Shell::Get()->window_tree_host_manager()->SetPrimaryDisplayId(
      display_manager()->GetSecondaryDisplay().id());
}

display::Display AshTestBase::GetPrimaryDisplay() {
  return display::Screen::GetScreen()->GetDisplayNearestWindow(
      Shell::GetPrimaryRootWindow());
}

display::Display AshTestBase::GetSecondaryDisplay() {
  return ash_test_helper_->GetSecondaryDisplay();
}

ws::WindowTreeTestHelper* AshTestBase::GetWindowTreeTestHelper() {
  CreateWindowTreeIfNecessary();
  return window_tree_test_helper_.get();
}

ws::TestWindowTreeClient* AshTestBase::GetTestWindowTreeClient() {
  CreateWindowTreeIfNecessary();
  return window_tree_client_.get();
}

ws::WindowTree* AshTestBase::GetWindowTree() {
  CreateWindowTreeIfNecessary();
  return window_tree_.get();
}

void AshTestBase::CreateWindowTreeIfNecessary() {
  if (window_tree_client_)
    return;

  // Lazily create a single client.
  window_tree_client_ = std::make_unique<ws::TestWindowTreeClient>();
  window_tree_ =
      Shell::Get()->window_service_owner()->window_service()->CreateWindowTree(
          window_tree_client_.get());
  window_tree_->InitFromFactory();
  window_tree_test_helper_ =
      std::make_unique<ws::WindowTreeTestHelper>(window_tree_.get());
}

SingleProcessMashTestBase::SingleProcessMashTestBase() = default;

SingleProcessMashTestBase::~SingleProcessMashTestBase() = default;

void SingleProcessMashTestBase::SetUp() {
  original_aura_env_mode_ =
      aura::test::EnvTestHelper().SetMode(aura::Env::Mode::MUS);
  feature_list_.InitWithFeatures({::features::kSingleProcessMash}, {});
  AshTestBase::SetUp();

  // TabletModeController calls to PowerManagerClient with a callback that is
  // run via a posted task. Run the loop now so that we know the task is
  // processed. Without this, the task gets processed later on, which may
  // interfer with things.
  base::RunLoop().RunUntilIdle();

  // This test configures views with mus, which means it triggers some of the
  // DCHECKs ensuring Shell's Env is used.
  SetRunningOutsideAsh();

  ash_test_helper()->CreateMusClient();
}

void SingleProcessMashTestBase::TearDown() {
  AshTestBase::TearDown();
  aura::test::EnvTestHelper().SetMode(original_aura_env_mode_);
}

}  // namespace ash
