// Copyright 2015 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/touch.h"

#include <algorithm>

#include "base/trace_event/trace_event.h"
#include "components/exo/input_trace.h"
#include "components/exo/seat.h"
#include "components/exo/shell_surface_util.h"
#include "components/exo/surface.h"
#include "components/exo/touch_delegate.h"
#include "components/exo/touch_stylus_delegate.h"
#include "components/exo/wm_helper.h"
#include "ui/aura/window.h"
#include "ui/compositor/layer.h"
#include "ui/events/event.h"
#include "ui/wm/core/capture_controller.h"
#include "ui/wm/core/window_util.h"

namespace exo {
namespace {

gfx::PointF EventLocationInWindow(ui::TouchEvent* event, aura::Window* window) {
  ui::Layer* root = window->GetRootWindow()->layer();
  ui::Layer* target = window->layer();

  gfx::Transform transform;
  target->GetTargetTransformRelativeTo(root, &transform);
  gfx::PointF point = event->root_location_f();
  return transform.InverseMapPoint(point).value_or(point);
}

}  // namespace

////////////////////////////////////////////////////////////////////////////////
// Touch, public:

Touch::Touch(TouchDelegate* delegate, Seat* seat)
    : delegate_(delegate), seat_(seat) {
  ash::Shell::Get()->AddShellObserver(this);
  for (aura::Window* root : ash::Shell::GetAllRootWindows()) {
    root->AddPreTargetHandler(this);
  }
}

Touch::~Touch() {
  ash::Shell::Get()->RemoveShellObserver(this);
  for (aura::Window* root : ash::Shell::GetAllRootWindows()) {
    root->RemovePreTargetHandler(this);
  }
  delegate_->OnTouchDestroying(this);
  if (HasStylusDelegate())
    stylus_delegate_->OnTouchDestroying(this);
  CancelAllTouches();
}

void Touch::SetStylusDelegate(TouchStylusDelegate* delegate) {
  stylus_delegate_ = delegate;
}

bool Touch::HasStylusDelegate() const {
  return !!stylus_delegate_;
}

////////////////////////////////////////////////////////////////////////////////
// ui::EventHandler overrides:

void Touch::OnTouchEvent(ui::TouchEvent* event) {
  if (seat_->was_shutdown() || event->handled()) {
    return;
  }

  // TODO(crbug.com/40061238): Investigate if we need to do something similar to
  // the filter in `Pointer::OnMouseEvent` when dragging. (not sending touch
  // events during drag)

  bool send_details = false;

  auto event_type = event->type();
  if ((event->flags() & ui::EF_RESERVED_FOR_GESTURE) != 0) {
    event_type = ui::EventType::kTouchCancelled;
  }

  const int touch_pointer_id = event->pointer_details().id;
  switch (event_type) {
    case ui::EventType::kTouchPressed: {
      // Early out if event doesn't contain a valid target for touch device.
      // TODO(b/147848270): Verify GetEffectiveTargetForEvent gets the correct
      // surface when input is captured.
      Surface* target = GetEffectiveTargetForEvent(event);
      if (!target)
        return;

      TRACE_EXO_INPUT_EVENT(event);
      DCHECK(touch_points_surface_map_.find(touch_pointer_id) ==
             touch_points_surface_map_.end());

      touch_points_surface_map_.emplace(touch_pointer_id, target);

      // Update the count of pointers on the target surface.
      auto it = surface_touch_count_map_.find(target);
      if (it == surface_touch_count_map_.end()) {
        target->AddSurfaceObserver(this);
        surface_touch_count_map_.emplace(target, 1);
      } else {
        it->second++;
      }

      // Convert location to target surface coordinate space.
      const gfx::PointF location =
          EventLocationInWindow(event, target->window());

      // Generate a touch down event for the target surface.
      delegate_->OnTouchDown(target, event->time_stamp(), touch_pointer_id,
                             location);
      if (stylus_delegate_ && event->pointer_details().pointer_type !=
                                  ui::EventPointerType::kTouch) {
        stylus_delegate_->OnTouchTool(touch_pointer_id,
                                      event->pointer_details().pointer_type);
      }
      send_details = true;
    } break;
    case ui::EventType::kTouchReleased: {
      auto it = touch_points_surface_map_.find(touch_pointer_id);
      if (it == touch_points_surface_map_.end())
        return;

      Surface* target = it->second;
      DCHECK(target);

      TRACE_EXO_INPUT_EVENT(event);

      touch_points_surface_map_.erase(it);

      // Update the count of pointers on the target surface.
      auto count_it = surface_touch_count_map_.find(target);
      if (count_it == surface_touch_count_map_.end())
        return;
      if ((--count_it->second) <= 0) {
        surface_touch_count_map_.erase(target);
        target->RemoveSurfaceObserver(this);
      }

      delegate_->OnTouchUp(event->time_stamp(), touch_pointer_id);
      seat_->AbortPendingDragOperation();
    } break;
    case ui::EventType::kTouchMoved: {
      auto it = touch_points_surface_map_.find(touch_pointer_id);
      if (it == touch_points_surface_map_.end())
        return;

      Surface* target = it->second;
      DCHECK(target);

      TRACE_EXO_INPUT_EVENT(event);

      // Convert location to focus surface coordinate space.
      gfx::PointF location = EventLocationInWindow(event, target->window());
      delegate_->OnTouchMotion(event->time_stamp(), touch_pointer_id, location);
      send_details = true;
    } break;
    case ui::EventType::kTouchCancelled: {
      TRACE_EXO_INPUT_EVENT(event);
      // Cancel the full set of touch sequences as soon as one is canceled.
      CancelAllTouches();
      delegate_->OnTouchCancel();

      seat_->AbortPendingDragOperation();
    } break;
    default:
      NOTREACHED();
  }
  if (send_details) {
    // Some devices do not report radius_y/minor. We assume a circular shape
    // in that case.
    float major = event->pointer_details().radius_x * 2.0f;
    float minor = event->pointer_details().radius_y * 2.0f;
    if (!minor)
      minor = major;
    delegate_->OnTouchShape(touch_pointer_id, major, minor);

    if (stylus_delegate_ &&
        event->pointer_details().pointer_type != ui::EventPointerType::kTouch) {
      if (!std::isnan(event->pointer_details().force)) {
        stylus_delegate_->OnTouchForce(event->time_stamp(), touch_pointer_id,
                                       event->pointer_details().force);
      }
      stylus_delegate_->OnTouchTilt(
          event->time_stamp(), touch_pointer_id,
          gfx::Vector2dF(event->pointer_details().tilt_x,
                         event->pointer_details().tilt_y));
    }
  }
  // TODO(denniskempin): Extend ui::TouchEvent to signal end of sequence of
  // touch events to send TouchFrame once after all touches have been updated.
  delegate_->OnTouchFrame();
}

////////////////////////////////////////////////////////////////////////////////
// SurfaceObserver overrides:

void Touch::OnSurfaceDestroying(Surface* surface) {
  // TODO(b/147848407): Do not cancel touches on surfaces of different clients
  // when this surface dies.
  CancelAllTouches();
  delegate_->OnTouchCancel();
}

// ash::ShellObserver:
void Touch::OnRootWindowAdded(aura::Window* root_window) {
  root_window->AddPreTargetHandler(this);
}

void Touch::OnRootWindowWillShutdown(aura::Window* root_window) {
  root_window->RemovePreTargetHandler(this);
}

////////////////////////////////////////////////////////////////////////////////
// Touch, private:

Surface* Touch::GetEffectiveTargetForEvent(ui::LocatedEvent* event) const {
  Surface* target = GetTargetSurfaceForLocatedEvent(event);

  if (!target)
    return nullptr;

  return delegate_->CanAcceptTouchEventsForSurface(target) ? target : nullptr;
}

void Touch::CancelAllTouches() {
  std::ranges::for_each(surface_touch_count_map_, [this](auto& it) {
    it.first->RemoveSurfaceObserver(this);
  });
  touch_points_surface_map_.clear();
  surface_touch_count_map_.clear();
}

}  // namespace exo
