// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/exo/extended_drag_source.h"

#include <memory>
#include <string>

#include "ash/public/cpp/window_properties.h"
#include "ash/shell.h"
#include "ash/wm/toplevel_window_event_handler.h"
#include "base/check.h"
#include "base/check_op.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/notreached.h"
#include "components/exo/data_source.h"
#include "components/exo/surface.h"
#include "components/exo/surface_observer.h"
#include "components/exo/wm_helper.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/screen_position_client.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_observer.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-shared.h"
#include "ui/base/hit_test.h"
#include "ui/events/event.h"
#include "ui/events/event_target.h"
#include "ui/events/event_utils.h"
#include "ui/events/types/event_type.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/vector2d.h"
#include "ui/wm/core/coordinate_conversion.h"
#include "ui/wm/public/window_move_client.h"

namespace exo {

using ::ui::mojom::DragOperation;

// static
ExtendedDragSource* ExtendedDragSource::instance_ = nullptr;

// Internal representation of a toplevel window, backed by an Exo shell surface,
// which is being dragged. It supports both already mapped/visible windows as
// well as newly created ones (i.e: not added to a root window yet), in which
// case OnDraggedWindowVisibilityChanging callback is called to notify when it
// has just got visible.
class ExtendedDragSource::DraggedWindowHolder : public aura::WindowObserver,
                                                public SurfaceObserver {
 public:
  DraggedWindowHolder(Surface* surface,
                      const gfx::Vector2d& drag_offset,
                      ExtendedDragSource* source)
      : surface_(surface), drag_offset_(drag_offset), source_(source) {
    DCHECK(surface_);
    DCHECK(surface_->window());
    surface_->AddSurfaceObserver(this);
    if (!FindToplevelWindow()) {
      DVLOG(1) << "Dragged window not added to root window yet.";
      surface_->window()->AddObserver(this);
    }
  }

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

  ~DraggedWindowHolder() override {
    if (toplevel_window_) {
      toplevel_window_->RemoveObserver(this);
      toplevel_window_ = nullptr;
    } else if (surface_) {
      surface_->window()->RemoveObserver(this);
    }

    if (surface_)
      surface_->RemoveSurfaceObserver(this);
  }

  aura::Window* toplevel_window() { return toplevel_window_; }
  const gfx::Vector2d& offset() const { return drag_offset_; }

 private:
  // aura::WindowObserver:
  void OnWindowAddedToRootWindow(aura::Window* window) override {
    if (toplevel_window_)
      return;

    DCHECK_EQ(window, surface_->window());
    FindToplevelWindow();
    DCHECK(toplevel_window_);
    surface_->window()->RemoveObserver(this);
  }

  void OnWindowVisibilityChanging(aura::Window* window, bool visible) override {
    DCHECK(window);
    if (window == toplevel_window_)
      source_->OnDraggedWindowVisibilityChanging(visible);
  }

  void OnWindowDestroying(aura::Window* window) override {
    DCHECK(window);
    if (window == toplevel_window_) {
      toplevel_window_->RemoveObserver(this);
      toplevel_window_ = nullptr;
    }
  }

  // SurfaceObserver:
  void OnSurfaceDestroying(Surface* surface) override {
    if (surface_ == surface) {
      surface_->RemoveSurfaceObserver(this);
      surface_ = nullptr;
    }
  }

  bool FindToplevelWindow() {
    if (!surface_->window()->GetRootWindow())
      return false;

    toplevel_window_ = surface_->window()->GetToplevelWindow();
    toplevel_window_->AddObserver(this);

    // Disable visibility change animations on the dragged window.
    toplevel_window_->SetProperty(aura::client::kAnimationsDisabledKey, true);
    return true;
  }

  raw_ptr<Surface, ExperimentalAsh> surface_;
  gfx::Vector2d drag_offset_;
  const raw_ptr<ExtendedDragSource, ExperimentalAsh> source_;
  raw_ptr<aura::Window, ExperimentalAsh> toplevel_window_ = nullptr;
};

// static
ExtendedDragSource* ExtendedDragSource::Get() {
  return instance_;
}

ExtendedDragSource::ExtendedDragSource(DataSource* source, Delegate* delegate)
    : source_(source), delegate_(delegate) {
  DCHECK(source_);
  DCHECK(delegate_);

  source_->AddObserver(this);

  DCHECK(!instance_);
  instance_ = this;
}

ExtendedDragSource::~ExtendedDragSource() {
  delegate_->OnDataSourceDestroying();
  for (auto& observer : observers_)
    observer.OnExtendedDragSourceDestroying(this);

  if (source_)
    source_->RemoveObserver(this);

  if (drag_source_window_)
    drag_source_window_->RemoveObserver(this);

  DCHECK_EQ(instance_, this);
  instance_ = nullptr;
}

void ExtendedDragSource::AddObserver(Observer* observer) {
  DCHECK(observer);
  observers_.AddObserver(observer);
}

void ExtendedDragSource::RemoveObserver(Observer* observer) {
  DCHECK(observer);
  observers_.RemoveObserver(observer);
}

void ExtendedDragSource::Drag(Surface* dragged_surface,
                              const gfx::Vector2d& drag_offset) {
  // Associated data source already destroyed.
  if (!source_)
    return;

  if (!dragged_surface) {
    DVLOG(1) << "Unsetting dragged surface.";
    dragged_window_holder_.reset();
    return;
  }

  DVLOG(1) << "Dragged surface changed:"
           << " surface=" << dragged_surface
           << " offset=" << drag_offset.ToString();

  // Ensure that the surface already has a "role" assigned.
  DCHECK(dragged_surface->HasSurfaceDelegate());
  dragged_window_holder_ =
      std::make_unique<DraggedWindowHolder>(dragged_surface, drag_offset, this);

  // Drag process will be started once OnToplevelWindowDragStarted() gets
  // called, unless it is called (raced) prior to this one. In this case, we
  // trigger the dragging here.
  //
  // TODO(https://crrev.com/1360884: Unify where tab-dragging is initiated.
  if (pending_drag_start_ &&
      dragged_window_holder_->toplevel_window() == drag_source_window_) {
    StartDrag(dragged_window_holder_->toplevel_window());
    pending_drag_start_ = false;
  }
}

bool ExtendedDragSource::IsActive() const {
  return !!source_;
}

void ExtendedDragSource::OnToplevelWindowDragStarted(
    const gfx::PointF& start_location,
    ui::mojom::DragEventSource source,
    aura::Window* drag_source_window) {
  pointer_location_ = start_location;
  drag_event_source_ = source;
  drag_source_window_ =
      drag_source_window ? drag_source_window->GetToplevelWindow() : nullptr;
  if (drag_source_window_)
    drag_source_window_->AddObserver(this);
  MaybeLockCursor();
  if (dragged_window_holder_ && dragged_window_holder_->toplevel_window() &&
      dragged_window_holder_->toplevel_window()->IsVisible()) {
    StartDrag(dragged_window_holder_->toplevel_window());
  } else {
    pending_drag_start_ = true;
  }
}

DragOperation ExtendedDragSource::OnToplevelWindowDragDropped() {
  DVLOG(1) << "OnDragDropped()";
  Cleanup();
  return delegate_->ShouldAllowDropAnywhere() ? DragOperation::kMove
                                              : DragOperation::kNone;
}

void ExtendedDragSource::OnToplevelWindowDragCancelled() {
  DVLOG(1) << "OnDragCancelled()";
  auto* handler = ash::Shell::Get()->toplevel_window_event_handler();
  handler->RevertDrag();

  Cleanup();
}

void ExtendedDragSource::OnToplevelWindowDragEvent(ui::LocatedEvent* event) {
  pointer_location_ = event->root_location_f();

  if (!dragged_window_holder_)
    return;

  DCHECK(event);
  aura::Window* target = static_cast<aura::Window*>(event->target());
  wm::ConvertPointToScreen(target->GetRootWindow(), &pointer_location_);

  auto* handler = ash::Shell::Get()->toplevel_window_event_handler();
  if (event->IsMouseEvent()) {
    handler->OnMouseEvent(event->AsMouseEvent());
    return;
  }

  if (event->IsGestureEvent()) {
    handler->OnGestureEvent(event->AsGestureEvent());
    return;
  }

  NOTREACHED() << "Only mouse and touch events are supported.";
}

void ExtendedDragSource::OnDataSourceDestroying(DataSource* source) {
  DCHECK_EQ(source, source_);
  source_->RemoveObserver(this);
  source_ = nullptr;
}

void ExtendedDragSource::OnWindowDestroyed(aura::Window* window) {
  if (drag_source_window_ == window)
    drag_source_window_ = nullptr;
}

void ExtendedDragSource::MaybeLockCursor() {
  if (delegate_->ShouldLockCursor()) {
    ash::Shell::Get()->cursor_manager()->LockCursor();
    cursor_locked_ = true;
  }
}

void ExtendedDragSource::UnlockCursor() {
  if (cursor_locked_) {
    ash::Shell::Get()->cursor_manager()->UnlockCursor();
    cursor_locked_ = false;
  }
}

void ExtendedDragSource::StartDrag(aura::Window* toplevel) {
  DCHECK(!event_blocker_);
  // Ensure |toplevel| window does skip events while it's being dragged.
  event_blocker_ =
      std::make_unique<aura::ScopedWindowEventTargetingBlocker>(toplevel);

  DVLOG(1) << "Starting drag. pointer_loc=" << pointer_location_.ToString();
  auto* toplevel_handler = ash::Shell::Get()->toplevel_window_event_handler();
  auto move_source = drag_event_source_ == ui::mojom::DragEventSource::kTouch
                         ? ::wm::WINDOW_MOVE_SOURCE_TOUCH
                         : ::wm::WINDOW_MOVE_SOURCE_MOUSE;

  auto end_closure = base::BindOnce(
      [](base::WeakPtr<ExtendedDragSource> self,
         ash::ToplevelWindowEventHandler::DragResult result) {
        if (!self)
          return;
        if (auto* window_holder = self->dragged_window_holder_.get()) {
          if (auto* toplevel = window_holder->toplevel_window()) {
            toplevel->ClearProperty(ash::kIsDraggingTabsKey);
          }
        }
        self->dragged_window_holder_.reset();
        self->event_blocker_.reset();
      },
      weak_factory_.GetWeakPtr());

  // TODO(crbug.com/1167581): Experiment setting |update_gesture_target| back
  // to true when capture is removed from drag and drop.

  gfx::PointF pointer_location_in_parent(pointer_location_);
  wm::ConvertPointFromScreen(toplevel->parent(), &pointer_location_in_parent);

  toplevel_handler->AttemptToStartDrag(
      toplevel, pointer_location_in_parent, HTCAPTION, move_source,
      std::move(end_closure),
      /*update_gesture_target=*/false,
      /*grab_capture =*/
      drag_event_source_ != ui::mojom::DragEventSource::kTouch);
}

void ExtendedDragSource::OnDraggedWindowVisibilityChanging(bool visible) {
  DCHECK(dragged_window_holder_);
  DVLOG(1) << "Dragged window visibility changing. visible=" << visible;

  if (!visible) {
    dragged_window_holder_.reset();
    return;
  }

  aura::Window* toplevel = dragged_window_holder_->toplevel_window();
  DCHECK(toplevel);
  toplevel->SetProperty(ash::kIsDraggingTabsKey, true);

  // The |toplevel| window for the dragged surface has just been created and
  // it's about to be mapped. Calculate and set its position based on
  // |drag_offset_| and |pointer_location_| before starting the actual drag.
  auto screen_location =
      gfx::ToFlooredPoint(pointer_location_ - dragged_window_holder_->offset());

  auto toplevel_bounds =
      gfx::Rect({screen_location, toplevel->bounds().size()});
  auto display = display::Screen::GetScreen()->GetDisplayNearestWindow(
      drag_source_window_ ? drag_source_window_.get() : toplevel);
  toplevel->SetBoundsInScreen(toplevel_bounds, display);

  DVLOG(1) << "Dragged window mapped. toplevel=" << toplevel
           << " origin=" << screen_location.ToString();

  StartDrag(toplevel);
}

void ExtendedDragSource::Cleanup() {
  if (dragged_window_holder_ && dragged_window_holder_->toplevel_window()) {
    dragged_window_holder_->toplevel_window()->ClearProperty(
        aura::client::kAnimationsDisabledKey);
  }
  event_blocker_.reset();
  if (drag_source_window_)
    drag_source_window_->RemoveObserver(this);
  drag_source_window_ = nullptr;
  pending_drag_start_ = false;
  UnlockCursor();
}

aura::Window* ExtendedDragSource::GetDraggedWindowForTesting() {
  return dragged_window_holder_ ? dragged_window_holder_->toplevel_window()
                                : nullptr;
}

absl::optional<gfx::Vector2d> ExtendedDragSource::GetDragOffsetForTesting()
    const {
  return dragged_window_holder_
             ? absl::optional<gfx::Vector2d>(dragged_window_holder_->offset())
             : absl::nullopt;
}

aura::Window* ExtendedDragSource::GetDragSourceWindowForTesting() {
  return drag_source_window_;
}

}  // namespace exo
