// Copyright 2014 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 "ui/events/ozone/evdev/event_factory_evdev.h"

#include "base/bind.h"
#include "base/task_runner.h"
#include "base/thread_task_runner_handle.h"
#include "base/threading/worker_pool.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "ui/events/devices/device_data_manager.h"
#include "ui/events/devices/input_device.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
#include "ui/events/ozone/device/device_event.h"
#include "ui/events/ozone/device/device_manager.h"
#include "ui/events/ozone/evdev/cursor_delegate_evdev.h"
#include "ui/events/ozone/evdev/input_controller_evdev.h"
#include "ui/events/ozone/evdev/input_device_factory_evdev.h"
#include "ui/events/ozone/evdev/input_device_factory_evdev_proxy.h"
#include "ui/events/ozone/evdev/input_injector_evdev.h"
#include "ui/events/ozone/evdev/touch_evdev_types.h"

namespace ui {

namespace {

// Thread safe dispatcher proxy for EventFactoryEvdev.
//
// This is used on the device I/O thread for dispatching to UI.
class ProxyDeviceEventDispatcher : public DeviceEventDispatcherEvdev {
 public:
  ProxyDeviceEventDispatcher(
      scoped_refptr<base::SingleThreadTaskRunner> ui_thread_runner,
      base::WeakPtr<EventFactoryEvdev> event_factory_evdev)
      : ui_thread_runner_(ui_thread_runner),
        event_factory_evdev_(event_factory_evdev) {}
  ~ProxyDeviceEventDispatcher() override {}

  // DeviceEventDispatcher:
  void DispatchKeyEvent(const KeyEventParams& params) override {
    ui_thread_runner_->PostTask(FROM_HERE,
                                base::Bind(&EventFactoryEvdev::DispatchKeyEvent,
                                           event_factory_evdev_, params));
  }

  void DispatchMouseMoveEvent(const MouseMoveEventParams& params) override {
    ui_thread_runner_->PostTask(
        FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchMouseMoveEvent,
                              event_factory_evdev_, params));
  }

  void DispatchMouseButtonEvent(const MouseButtonEventParams& params) override {
    ui_thread_runner_->PostTask(
        FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchMouseButtonEvent,
                              event_factory_evdev_, params));
  }

  void DispatchMouseWheelEvent(const MouseWheelEventParams& params) override {
    ui_thread_runner_->PostTask(
        FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchMouseWheelEvent,
                              event_factory_evdev_, params));
  }

  void DispatchScrollEvent(const ScrollEventParams& params) override {
    ui_thread_runner_->PostTask(
        FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchScrollEvent,
                              event_factory_evdev_, params));
  }

  void DispatchTouchEvent(const TouchEventParams& params) override {
    ui_thread_runner_->PostTask(
        FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchTouchEvent,
                              event_factory_evdev_, params));
  }

  void DispatchKeyboardDevicesUpdated(
      const std::vector<KeyboardDevice>& devices) override {
    ui_thread_runner_->PostTask(
        FROM_HERE,
        base::Bind(&EventFactoryEvdev::DispatchKeyboardDevicesUpdated,
                   event_factory_evdev_, devices));
  }
  void DispatchTouchscreenDevicesUpdated(
      const std::vector<TouchscreenDevice>& devices) override {
    ui_thread_runner_->PostTask(
        FROM_HERE,
        base::Bind(&EventFactoryEvdev::DispatchTouchscreenDevicesUpdated,
                   event_factory_evdev_, devices));
  }
  void DispatchMouseDevicesUpdated(
      const std::vector<InputDevice>& devices) override {
    ui_thread_runner_->PostTask(
        FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchMouseDevicesUpdated,
                              event_factory_evdev_, devices));
  }
  void DispatchTouchpadDevicesUpdated(
      const std::vector<InputDevice>& devices) override {
    ui_thread_runner_->PostTask(
        FROM_HERE,
        base::Bind(&EventFactoryEvdev::DispatchTouchpadDevicesUpdated,
                   event_factory_evdev_, devices));
  }
  void DispatchDeviceListsComplete() override {
    ui_thread_runner_->PostTask(
        FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchDeviceListsComplete,
                              event_factory_evdev_));
  }

 private:
  scoped_refptr<base::SingleThreadTaskRunner> ui_thread_runner_;
  base::WeakPtr<EventFactoryEvdev> event_factory_evdev_;
};

}  // namespace

EventFactoryEvdev::EventFactoryEvdev(CursorDelegateEvdev* cursor,
                                     DeviceManager* device_manager,
                                     KeyboardLayoutEngine* keyboard_layout)
    : device_manager_(device_manager),
      keyboard_(&modifiers_,
                keyboard_layout,
                base::Bind(&EventFactoryEvdev::DispatchUiEvent,
                           base::Unretained(this))),
      cursor_(cursor),
      input_controller_(&keyboard_, &button_map_),
      touch_id_generator_(0),
      weak_ptr_factory_(this) {
  DCHECK(device_manager_);
}

EventFactoryEvdev::~EventFactoryEvdev() {
}

void EventFactoryEvdev::Init() {
  DCHECK(!initialized_);

  StartThread();

  initialized_ = true;
}

scoped_ptr<SystemInputInjector> EventFactoryEvdev::CreateSystemInputInjector() {
  // Use forwarding dispatcher for the injector rather than dispatching
  // directly. We cannot assume it is safe to (re-)enter ui::Event dispatch
  // synchronously from the injection point.
  scoped_ptr<DeviceEventDispatcherEvdev> proxy_dispatcher(
      new ProxyDeviceEventDispatcher(base::ThreadTaskRunnerHandle::Get(),
                                     weak_ptr_factory_.GetWeakPtr()));
  return make_scoped_ptr(
      new InputInjectorEvdev(proxy_dispatcher.Pass(), cursor_));
}

void EventFactoryEvdev::DispatchKeyEvent(const KeyEventParams& params) {
  TRACE_EVENT1("evdev", "EventFactoryEvdev::DispatchKeyEvent", "device",
               params.device_id);
  keyboard_.OnKeyChange(params.code, params.down, params.suppress_auto_repeat,
                        params.timestamp, params.device_id);
}

void EventFactoryEvdev::DispatchMouseMoveEvent(
    const MouseMoveEventParams& params) {
  TRACE_EVENT1("evdev", "EventFactoryEvdev::DispatchMouseMoveEvent", "device",
               params.device_id);
  MouseEvent event(ui::ET_MOUSE_MOVED, params.location, params.location,
                   params.timestamp, modifiers_.GetModifierFlags(),
                   /* changed_button_flags */ 0);
  event.set_source_device_id(params.device_id);
  DispatchUiEvent(&event);
}

void EventFactoryEvdev::DispatchMouseButtonEvent(
    const MouseButtonEventParams& params) {
  TRACE_EVENT1("evdev", "EventFactoryEvdev::DispatchMouseButtonEvent", "device",
               params.device_id);

  // Mouse buttons can be remapped, touchpad taps & clicks cannot.
  unsigned int button = params.button;
  if (params.allow_remap)
    button = button_map_.GetMappedButton(button);

  int modifier = EVDEV_MODIFIER_NONE;
  switch (button) {
    case BTN_LEFT:
      modifier = EVDEV_MODIFIER_LEFT_MOUSE_BUTTON;
      break;
    case BTN_RIGHT:
      modifier = EVDEV_MODIFIER_RIGHT_MOUSE_BUTTON;
      break;
    case BTN_MIDDLE:
      modifier = EVDEV_MODIFIER_MIDDLE_MOUSE_BUTTON;
      break;
    case BTN_BACK:
      modifier = EVDEV_MODIFIER_BACK_MOUSE_BUTTON;
      break;
    case BTN_FORWARD:
      modifier = EVDEV_MODIFIER_FORWARD_MOUSE_BUTTON;
      break;
    default:
      return;
  }

  int flag = modifiers_.GetEventFlagFromModifier(modifier);
  bool was_down = modifiers_.GetModifierFlags() & flag;
  modifiers_.UpdateModifier(modifier, params.down);
  bool down = modifiers_.GetModifierFlags() & flag;

  // Suppress nested clicks. EventModifiersEvdev counts presses, we only
  // dispatch an event on 0-1 (first press) and 1-0 (last release) transitions.
  if (down == was_down)
    return;

  MouseEvent event(params.down ? ui::ET_MOUSE_PRESSED : ui::ET_MOUSE_RELEASED,
                   params.location, params.location, params.timestamp,
                   modifiers_.GetModifierFlags() | flag,
                   /* changed_button_flags */ flag);
  event.set_source_device_id(params.device_id);
  DispatchUiEvent(&event);
}

void EventFactoryEvdev::DispatchMouseWheelEvent(
    const MouseWheelEventParams& params) {
  TRACE_EVENT1("evdev", "EventFactoryEvdev::DispatchMouseWheelEvent", "device",
               params.device_id);
  MouseWheelEvent event(params.delta, params.location, params.location,
                        params.timestamp, modifiers_.GetModifierFlags(),
                        0 /* changed_button_flags */);
  event.set_source_device_id(params.device_id);
  DispatchUiEvent(&event);
}

void EventFactoryEvdev::DispatchScrollEvent(const ScrollEventParams& params) {
  TRACE_EVENT1("evdev", "EventFactoryEvdev::DispatchScrollEvent", "device",
               params.device_id);
  ScrollEvent event(params.type, params.location, params.timestamp,
                    modifiers_.GetModifierFlags(), params.delta.x(),
                    params.delta.y(), params.ordinal_delta.x(),
                    params.ordinal_delta.y(), params.finger_count);
  event.set_source_device_id(params.device_id);
  DispatchUiEvent(&event);
}

void EventFactoryEvdev::DispatchTouchEvent(const TouchEventParams& params) {
  TRACE_EVENT1("evdev", "EventFactoryEvdev::DispatchTouchEvent", "device",
               params.device_id);

  float x = params.location.x();
  float y = params.location.y();
  double radius_x = params.radii.x();
  double radius_y = params.radii.y();

  // Transform the event to align touches to the image based on display mode.
  DeviceDataManager::GetInstance()->ApplyTouchTransformer(params.device_id, &x,
                                                          &y);
  DeviceDataManager::GetInstance()->ApplyTouchRadiusScale(params.device_id,
                                                          &radius_x);
  DeviceDataManager::GetInstance()->ApplyTouchRadiusScale(params.device_id,
                                                          &radius_y);

  // params.slot is guaranteed to be < kNumTouchEvdevSlots.
  int touch_id = touch_id_generator_.GetGeneratedID(
      params.device_id * kNumTouchEvdevSlots + params.slot);
  TouchEvent touch_event(params.type, gfx::PointF(x, y),
                         modifiers_.GetModifierFlags(), touch_id,
                         params.timestamp, radius_x, radius_y,
                         /* angle */ 0.f, params.pressure);
  touch_event.set_source_device_id(params.device_id);
  DispatchUiEvent(&touch_event);

  if (params.type == ET_TOUCH_RELEASED || params.type == ET_TOUCH_CANCELLED) {
    touch_id_generator_.ReleaseGeneratedID(touch_event.touch_id());
  }
}

void EventFactoryEvdev::DispatchUiEvent(Event* event) {
  // DispatchEvent takes PlatformEvent which is void*. This function
  // wraps it with the real type.
  DispatchEvent(event);
}

void EventFactoryEvdev::DispatchKeyboardDevicesUpdated(
    const std::vector<KeyboardDevice>& devices) {
  TRACE_EVENT0("evdev", "EventFactoryEvdev::DispatchKeyboardDevicesUpdated");
  DeviceHotplugEventObserver* observer = DeviceDataManager::GetInstance();
  observer->OnKeyboardDevicesUpdated(devices);
}

void EventFactoryEvdev::DispatchTouchscreenDevicesUpdated(
    const std::vector<TouchscreenDevice>& devices) {
  TRACE_EVENT0("evdev", "EventFactoryEvdev::DispatchTouchscreenDevicesUpdated");
  DeviceHotplugEventObserver* observer = DeviceDataManager::GetInstance();
  observer->OnTouchscreenDevicesUpdated(devices);
}

void EventFactoryEvdev::DispatchMouseDevicesUpdated(
    const std::vector<InputDevice>& devices) {
  TRACE_EVENT0("evdev", "EventFactoryEvdev::DispatchMouseDevicesUpdated");

  // There's no list of mice in DeviceDataManager.
  input_controller_.set_has_mouse(devices.size() != 0);
  DeviceHotplugEventObserver* observer = DeviceDataManager::GetInstance();
  observer->OnMouseDevicesUpdated(devices);
}

void EventFactoryEvdev::DispatchTouchpadDevicesUpdated(
    const std::vector<InputDevice>& devices) {
  TRACE_EVENT0("evdev", "EventFactoryEvdev::DispatchTouchpadDevicesUpdated");

  // There's no list of touchpads in DeviceDataManager.
  input_controller_.set_has_touchpad(devices.size() != 0);
  DeviceHotplugEventObserver* observer = DeviceDataManager::GetInstance();
  observer->OnTouchpadDevicesUpdated(devices);
}

void EventFactoryEvdev::DispatchDeviceListsComplete() {
  TRACE_EVENT0("evdev", "EventFactoryEvdev::DispatchDeviceListsComplete");
  DeviceHotplugEventObserver* observer = DeviceDataManager::GetInstance();
  observer->OnDeviceListsComplete();
}

void EventFactoryEvdev::OnDeviceEvent(const DeviceEvent& event) {
  if (event.device_type() != DeviceEvent::INPUT)
    return;

  switch (event.action_type()) {
    case DeviceEvent::ADD:
    case DeviceEvent::CHANGE: {
      TRACE_EVENT1("evdev", "EventFactoryEvdev::OnDeviceAdded", "path",
                   event.path().value());
      input_device_factory_proxy_->AddInputDevice(NextDeviceId(), event.path());
      break;
    }
    case DeviceEvent::REMOVE: {
      TRACE_EVENT1("evdev", "EventFactoryEvdev::OnDeviceRemoved", "path",
                   event.path().value());
      input_device_factory_proxy_->RemoveInputDevice(event.path());
      break;
    }
  }
}

void EventFactoryEvdev::OnDispatcherListChanged() {
  if (!initialized_)
    Init();
}

void EventFactoryEvdev::WarpCursorTo(gfx::AcceleratedWidget widget,
                                     const gfx::PointF& location) {
  if (!cursor_)
    return;

  cursor_->MoveCursorTo(widget, location);

  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchMouseMoveEvent,
                            weak_ptr_factory_.GetWeakPtr(),
                            MouseMoveEventParams(-1 /* device_id */,
                                                 cursor_->GetLocation(),
                                                 EventTimeForNow())));
}

int EventFactoryEvdev::NextDeviceId() {
  return ++last_device_id_;
}

void EventFactoryEvdev::StartThread() {
  // Set up device factory.
  scoped_ptr<DeviceEventDispatcherEvdev> proxy_dispatcher(
      new ProxyDeviceEventDispatcher(base::ThreadTaskRunnerHandle::Get(),
                                     weak_ptr_factory_.GetWeakPtr()));
  thread_.Start(proxy_dispatcher.Pass(), cursor_,
                base::Bind(&EventFactoryEvdev::OnThreadStarted,
                           weak_ptr_factory_.GetWeakPtr()));
}

void EventFactoryEvdev::OnThreadStarted(
    scoped_ptr<InputDeviceFactoryEvdevProxy> input_device_factory) {
  TRACE_EVENT0("evdev", "EventFactoryEvdev::OnThreadStarted");
  input_device_factory_proxy_ = input_device_factory.Pass();

  // Hook up device configuration.
  input_controller_.SetInputDeviceFactory(input_device_factory_proxy_.get());

  // Scan & monitor devices.
  device_manager_->AddObserver(this);
  device_manager_->ScanDevices(this);

  // Notify device thread that initial scan is done.
  input_device_factory_proxy_->OnStartupScanComplete();
}

}  // namespace ui
