// 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/drag_drop/drag_drop_tracker.h"

#include <memory>

#include "ash/common/scoped_root_window_for_new_windows.h"
#include "ash/common/wm_shell.h"
#include "ash/common/wm_window.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "ui/aura/test/test_windows.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/events/event_utils.h"

namespace ash {
namespace test {

class DragDropTrackerTest : public test::AshTestBase {
 public:
  void SetUp() override { AshTestBase::SetUp(); }

  aura::Window* CreateTestWindow(const gfx::Rect& bounds) {
    static int window_id = 0;
    return CreateTestWindowInShellWithDelegate(
        aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(),
        window_id++, bounds);
  }

  static aura::Window* GetTarget(const gfx::Point& location) {
    std::unique_ptr<DragDropTracker> tracker(
        new DragDropTracker(Shell::GetPrimaryRootWindow(), NULL));
    ui::MouseEvent e(ui::ET_MOUSE_DRAGGED, location, location,
                     ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
    aura::Window* target = tracker->GetTarget(e);
    return target;
  }

  static ui::LocatedEvent* ConvertEvent(aura::Window* target,
                                        const ui::MouseEvent& event) {
    std::unique_ptr<DragDropTracker> tracker(
        new DragDropTracker(Shell::GetPrimaryRootWindow(), NULL));
    ui::LocatedEvent* converted = tracker->ConvertEvent(target, event);
    return converted;
  }
};

TEST_F(DragDropTrackerTest, GetTarget) {
  UpdateDisplay("200x200,300x300");
  aura::Window::Windows root_windows = Shell::GetAllRootWindows();
  EXPECT_EQ(2U, root_windows.size());

  std::unique_ptr<aura::Window> window0(
      CreateTestWindow(gfx::Rect(0, 0, 100, 100)));
  window0->Show();

  std::unique_ptr<aura::Window> window1(
      CreateTestWindow(gfx::Rect(300, 100, 100, 100)));
  window1->Show();
  EXPECT_EQ(root_windows[0], window0->GetRootWindow());
  EXPECT_EQ(root_windows[1], window1->GetRootWindow());
  EXPECT_EQ("0,0 100x100", window0->GetBoundsInScreen().ToString());
  EXPECT_EQ("300,100 100x100", window1->GetBoundsInScreen().ToString());

  // RootWindow0 is active so the capture window is parented to it.
  EXPECT_EQ(WmWindow::Get(root_windows[0]),
            WmShell::Get()->GetRootWindowForNewWindows());

  // Start tracking from the RootWindow1 and check the point on RootWindow0 that
  // |window0| covers.
  EXPECT_EQ(window0.get(), GetTarget(gfx::Point(50, 50)));

  // Start tracking from the RootWindow0 and check the point on RootWindow0 that
  // neither |window0| nor |window1| covers.
  EXPECT_NE(window0.get(), GetTarget(gfx::Point(150, 150)));
  EXPECT_NE(window1.get(), GetTarget(gfx::Point(150, 150)));

  // Start tracking from the RootWindow0 and check the point on RootWindow1 that
  // |window1| covers.
  EXPECT_EQ(window1.get(), GetTarget(gfx::Point(350, 150)));

  // Start tracking from the RootWindow0 and check the point on RootWindow1 that
  // neither |window0| nor |window1| covers.
  EXPECT_NE(window0.get(), GetTarget(gfx::Point(50, 250)));
  EXPECT_NE(window1.get(), GetTarget(gfx::Point(50, 250)));

  // Make RootWindow1 active so that capture window is parented to it.
  ScopedRootWindowForNewWindows root_for_new_windows(
      WmWindow::Get(root_windows[1]));

  // Start tracking from the RootWindow1 and check the point on RootWindow0 that
  // |window0| covers.
  EXPECT_EQ(window0.get(), GetTarget(gfx::Point(-150, 50)));

  // Start tracking from the RootWindow1 and check the point on RootWindow0 that
  // neither |window0| nor |window1| covers.
  EXPECT_NE(window0.get(), GetTarget(gfx::Point(150, -50)));
  EXPECT_NE(window1.get(), GetTarget(gfx::Point(150, -50)));

  // Start tracking from the RootWindow1 and check the point on RootWindow1 that
  // |window1| covers.
  EXPECT_EQ(window1.get(), GetTarget(gfx::Point(150, 150)));

  // Start tracking from the RootWindow1 and check the point on RootWindow1 that
  // neither |window0| nor |window1| covers.
  EXPECT_NE(window0.get(), GetTarget(gfx::Point(50, 50)));
  EXPECT_NE(window1.get(), GetTarget(gfx::Point(50, 50)));
}

TEST_F(DragDropTrackerTest, ConvertEvent) {
  UpdateDisplay("200x200,300x300");
  aura::Window::Windows root_windows = Shell::GetAllRootWindows();
  EXPECT_EQ(2U, root_windows.size());

  std::unique_ptr<aura::Window> window0(
      CreateTestWindow(gfx::Rect(0, 0, 100, 100)));
  window0->Show();

  std::unique_ptr<aura::Window> window1(
      CreateTestWindow(gfx::Rect(300, 100, 100, 100)));
  window1->Show();

  // RootWindow0 is active so the capture window is parented to it.
  EXPECT_EQ(WmWindow::Get(root_windows[0]),
            WmShell::Get()->GetRootWindowForNewWindows());

  // Start tracking from the RootWindow0 and converts the mouse event into
  // |window0|'s coodinates.
  ui::MouseEvent original00(ui::ET_MOUSE_DRAGGED, gfx::Point(50, 50),
                            gfx::Point(50, 50), ui::EventTimeForNow(),
                            ui::EF_NONE, ui::EF_NONE);
  std::unique_ptr<ui::LocatedEvent> converted00(
      ConvertEvent(window0.get(), original00));
  EXPECT_EQ(original00.type(), converted00->type());
  EXPECT_EQ("50,50", converted00->location().ToString());
  EXPECT_EQ("50,50", converted00->root_location().ToString());
  EXPECT_EQ(original00.flags(), converted00->flags());

  // Start tracking from the RootWindow0 and converts the mouse event into
  // |window1|'s coodinates.
  ui::MouseEvent original01(ui::ET_MOUSE_DRAGGED, gfx::Point(350, 150),
                            gfx::Point(350, 150), ui::EventTimeForNow(),
                            ui::EF_NONE, ui::EF_NONE);
  std::unique_ptr<ui::LocatedEvent> converted01(
      ConvertEvent(window1.get(), original01));
  EXPECT_EQ(original01.type(), converted01->type());
  EXPECT_EQ("50,50", converted01->location().ToString());
  EXPECT_EQ("150,150", converted01->root_location().ToString());
  EXPECT_EQ(original01.flags(), converted01->flags());

  // Make RootWindow1 active so that capture window is parented to it.
  ScopedRootWindowForNewWindows root_for_new_windows(
      WmWindow::Get(root_windows[1]));

  // Start tracking from the RootWindow1 and converts the mouse event into
  // |window0|'s coodinates.
  ui::MouseEvent original10(ui::ET_MOUSE_DRAGGED, gfx::Point(-150, 50),
                            gfx::Point(-150, 50), ui::EventTimeForNow(),
                            ui::EF_NONE, ui::EF_NONE);
  std::unique_ptr<ui::LocatedEvent> converted10(
      ConvertEvent(window0.get(), original10));
  EXPECT_EQ(original10.type(), converted10->type());
  EXPECT_EQ("50,50", converted10->location().ToString());
  EXPECT_EQ("50,50", converted10->root_location().ToString());
  EXPECT_EQ(original10.flags(), converted10->flags());

  // Start tracking from the RootWindow1 and converts the mouse event into
  // |window1|'s coodinates.
  ui::MouseEvent original11(ui::ET_MOUSE_DRAGGED, gfx::Point(150, 150),
                            gfx::Point(150, 150), ui::EventTimeForNow(),
                            ui::EF_NONE, ui::EF_NONE);
  std::unique_ptr<ui::LocatedEvent> converted11(
      ConvertEvent(window1.get(), original11));
  EXPECT_EQ(original11.type(), converted11->type());
  EXPECT_EQ("50,50", converted11->location().ToString());
  EXPECT_EQ("150,150", converted11->root_location().ToString());
  EXPECT_EQ(original11.flags(), converted11->flags());
}

}  // namespace test
}  // namespace aura
