// 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 "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();
}

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
