// Copyright (c) 2013 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/display/mirror_window_controller.h"

#include "ash/display/mirror_window_test_api.h"
#include "ash/display/window_tree_host_manager.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "ash/wm/cursor_manager_test_api.h"
#include "base/command_line.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/env.h"
#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/test/test_windows.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/base/hit_test.h"
#include "ui/display/display_switches.h"
#include "ui/display/display_transform.h"
#include "ui/display/manager/display_manager.h"
#include "ui/display/test/display_manager_test_api.h"
#include "ui/display/types/display_constants.h"
#include "ui/events/test/event_generator.h"
#include "ui/gfx/overlay_transform.h"

namespace ash {

namespace {

display::ManagedDisplayInfo CreateDisplayInfo(int64_t id,
                                              const gfx::Rect& bounds,
                                              float scale = 1.f) {
  display::ManagedDisplayInfo info(
      id, base::StringPrintf("x-%d", static_cast<int>(id)), false);
  info.SetBounds(bounds);
  info.set_device_scale_factor(scale);
  return info;
}

class MirrorOnBootTest : public AshTestBase {
 public:
  MirrorOnBootTest() = default;
  ~MirrorOnBootTest() override = default;

  void SetUp() override {
    base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
        ::switches::kHostWindowBounds, "1+1-300x300,1+301-300x300");
    base::CommandLine::ForCurrentProcess()->AppendSwitch(
        ::switches::kEnableSoftwareMirroring);
    AshTestBase::SetUp();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(MirrorOnBootTest);
};

}  // namespace

using MirrorWindowControllerTest = AshTestBase;

// Make sure that the compositor based mirroring can switch
// from/to dock mode.
TEST_F(MirrorWindowControllerTest, DockMode) {
  const int64_t internal_id = 1;
  const int64_t external_id = 2;

  const display::ManagedDisplayInfo internal_display_info =
      CreateDisplayInfo(internal_id, gfx::Rect(0, 0, 500, 500));
  const display::ManagedDisplayInfo external_display_info =
      CreateDisplayInfo(external_id, gfx::Rect(1, 1, 100, 100));
  std::vector<display::ManagedDisplayInfo> display_info_list;

  // software mirroring.
  display_info_list.push_back(internal_display_info);
  display_info_list.push_back(external_display_info);
  display_manager()->OnNativeDisplaysChanged(display_info_list);
  const int64_t internal_display_id =
      display::test::DisplayManagerTestApi(display_manager())
          .SetFirstDisplayAsInternalDisplay();
  EXPECT_EQ(internal_id, internal_display_id);

  display_manager()->SetMirrorMode(display::MirrorMode::kNormal, base::nullopt);
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(1U, display_manager()->GetNumDisplays());
  EXPECT_TRUE(display_manager()->IsInSoftwareMirrorMode());
  EXPECT_EQ(external_id,
            display_manager()->GetMirroringDestinationDisplayIdList()[0]);

  // dock mode.
  display_info_list.clear();
  display_info_list.push_back(external_display_info);
  display_manager()->OnNativeDisplaysChanged(display_info_list);
  EXPECT_EQ(1U, display_manager()->GetNumDisplays());
  EXPECT_FALSE(display_manager()->IsInMirrorMode());

  // back to software mirroring.
  display_info_list.clear();
  display_info_list.push_back(internal_display_info);
  display_info_list.push_back(external_display_info);
  display_manager()->OnNativeDisplaysChanged(display_info_list);
  EXPECT_EQ(1U, display_manager()->GetNumDisplays());
  EXPECT_TRUE(display_manager()->IsInMirrorMode());
  EXPECT_EQ(external_id,
            display_manager()->GetMirroringDestinationDisplayIdList()[0]);
}

TEST_F(MirrorOnBootTest, MirrorOnBoot) {
  EXPECT_TRUE(display_manager()->IsInMirrorMode());

  base::RunLoop().RunUntilIdle();
  MirrorWindowTestApi test_api;
  EXPECT_EQ(1U, test_api.GetHosts().size());
}

class MirrorWindowControllerRotationAndPanelOrientationTest
    : public MirrorWindowControllerTest,
      public testing::WithParamInterface<
          std::tuple<display::Display::Rotation, display::PanelOrientation>> {};

// Test that the mirror display matches the size and rotation of the source.
TEST_P(MirrorWindowControllerRotationAndPanelOrientationTest, MirrorSize) {
  const int64_t primary_id = 1;
  const int64_t mirror_id = 2;

  const display::Display::Rotation active_rotation = std::get<0>(GetParam());
  const display::PanelOrientation panel_orientation = std::get<1>(GetParam());

  // Run the test with and without display scaling.
  int scale_factors[] = {1, 2};
  for (int scale : scale_factors) {
    display::ManagedDisplayInfo primary_display_info =
        CreateDisplayInfo(primary_id, gfx::Rect(0, 0, 400, 300), scale);
    primary_display_info.set_panel_orientation(panel_orientation);
    primary_display_info.SetRotation(active_rotation,
                                     display::Display::RotationSource::ACTIVE);

    const display::ManagedDisplayInfo mirror_display_info =
        CreateDisplayInfo(mirror_id, gfx::Rect(400, 0, 600, 500), scale);
    std::vector<display::ManagedDisplayInfo> display_info_list = {
        primary_display_info, mirror_display_info};

    // Start software mirroring.
    display_manager()->OnNativeDisplaysChanged(display_info_list);
    display_manager()->SetMirrorMode(display::MirrorMode::kNormal,
                                     base::nullopt);
    base::RunLoop().RunUntilIdle();
    EXPECT_EQ(1U, display_manager()->GetNumDisplays());
    EXPECT_TRUE(display_manager()->IsInSoftwareMirrorMode());

    // Check the size of the mirror window.
    const display::Display& primary_display =
        display_manager()->GetDisplayForId(primary_id);
    aura::Window* root_window = Shell::GetRootWindowForDisplayId(mirror_id);
    aura::Window* mirror_window = root_window->children()[0];
    EXPECT_EQ(primary_display.GetSizeInPixel(), root_window->bounds().size());
    EXPECT_EQ(primary_display.GetSizeInPixel(), mirror_window->bounds().size());

    // Mirror should have a display transform hint that matches the active
    // rotation (excluding the panel orientation) of the source.
    EXPECT_EQ(display::DisplayRotationToOverlayTransform(active_rotation),
              root_window->GetHost()->compositor()->display_transform_hint());
  }
}

INSTANTIATE_TEST_SUITE_P(
    All,
    MirrorWindowControllerRotationAndPanelOrientationTest,
    testing::Combine(testing::Values(display::Display::ROTATE_0,
                                     display::Display::ROTATE_90,
                                     display::Display::ROTATE_180,
                                     display::Display::ROTATE_270),
                     testing::Values(display::PanelOrientation::kNormal,
                                     display::PanelOrientation::kBottomUp,
                                     display::PanelOrientation::kLeftUp,
                                     display::PanelOrientation::kRightUp)));

}  // namespace ash
