// 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 <fcntl.h>
#include <linux/input.h>

#include "base/debug/trace_event.h"
#include "base/stl_util.h"
#include "base/task_runner.h"
#include "base/thread_task_runner_handle.h"
#include "base/threading/worker_pool.h"
#include "ui/events/device_data_manager.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/event_device_info.h"
#include "ui/events/ozone/evdev/key_event_converter_evdev.h"
#include "ui/events/ozone/evdev/touch_event_converter_evdev.h"

#if defined(USE_EVDEV_GESTURES)
#include "ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.h"
#include "ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.h"
#include "ui/events/ozone/evdev/libgestures_glue/gesture_property_provider.h"
#endif

#ifndef EVIOCSCLOCKID
#define EVIOCSCLOCKID  _IOW('E', 0xa0, int)
#endif

namespace ui {

namespace {

typedef base::Callback<void(scoped_ptr<EventConverterEvdev>)>
    OpenInputDeviceReplyCallback;

struct OpenInputDeviceParams {
  // Unique identifier for the new device.
  int id;

  // Device path to open.
  base::FilePath path;

  // Callback for dispatching events. Call on UI thread only.
  EventDispatchCallback dispatch_callback;

  // State shared between devices. Must not be dereferenced on worker thread.
  EventModifiersEvdev* modifiers;
  KeyboardEvdev* keyboard;
  CursorDelegateEvdev* cursor;
#if defined(USE_EVDEV_GESTURES)
  GesturePropertyProvider* gesture_property_provider;
#endif
};

#if defined(USE_EVDEV_GESTURES)
bool UseGesturesLibraryForDevice(const EventDeviceInfo& devinfo) {
  if (devinfo.HasAbsXY() && !devinfo.IsMappedToScreen())
    return true;  // touchpad

  if (devinfo.HasRelXY())
    return true;  // mouse

  return false;
}
#endif

scoped_ptr<EventConverterEvdev> CreateConverter(
    const OpenInputDeviceParams& params,
    int fd,
    const EventDeviceInfo& devinfo) {
#if defined(USE_EVDEV_GESTURES)
  // Touchpad or mouse: use gestures library.
  // EventReaderLibevdevCros -> GestureInterpreterLibevdevCros -> DispatchEvent
  if (UseGesturesLibraryForDevice(devinfo)) {
    scoped_ptr<GestureInterpreterLibevdevCros> gesture_interp = make_scoped_ptr(
        new GestureInterpreterLibevdevCros(params.id,
                                           params.modifiers,
                                           params.cursor,
                                           params.keyboard,
                                           params.gesture_property_provider,
                                           params.dispatch_callback));
    return make_scoped_ptr(new EventReaderLibevdevCros(
          fd, params.path, params.id, gesture_interp.Pass()));
  }
#endif

  // Touchscreen: use TouchEventConverterEvdev.
  scoped_ptr<EventConverterEvdev> converter;
  if (devinfo.HasAbsXY())
    return make_scoped_ptr<EventConverterEvdev>(new TouchEventConverterEvdev(
        fd, params.path, params.id, devinfo, params.dispatch_callback));

  // Everything else: use KeyEventConverterEvdev.
  return make_scoped_ptr<EventConverterEvdev>(
      new KeyEventConverterEvdev(fd, params.path, params.id, params.keyboard));
}

// Open an input device. Opening may put the calling thread to sleep, and
// therefore should be run on a thread where latency is not critical. We
// run it on a thread from the worker pool.
//
// This takes a TaskRunner and runs the reply on that thread, so that we
// can hop threads if necessary (back to the UI thread).
void OpenInputDevice(scoped_ptr<OpenInputDeviceParams> params,
                     scoped_refptr<base::TaskRunner> reply_runner,
                     const OpenInputDeviceReplyCallback& reply_callback) {
  const base::FilePath& path = params->path;

  TRACE_EVENT1("ozone", "OpenInputDevice", "path", path.value());

  int fd = open(path.value().c_str(), O_RDONLY | O_NONBLOCK);
  if (fd < 0) {
    PLOG(ERROR) << "Cannot open '" << path.value();
    return;
  }

  // Use monotonic timestamps for events. The touch code in particular
  // expects event timestamps to correlate to the monotonic clock
  // (base::TimeTicks).
  unsigned int clk = CLOCK_MONOTONIC;
  if (ioctl(fd, EVIOCSCLOCKID, &clk))
    PLOG(ERROR) << "failed to set CLOCK_MONOTONIC";

  EventDeviceInfo devinfo;
  if (!devinfo.Initialize(fd)) {
    LOG(ERROR) << "failed to get device information for " << path.value();
    close(fd);
    return;
  }

  scoped_ptr<EventConverterEvdev> converter =
      CreateConverter(*params, fd, devinfo);

  // Reply with the constructed converter.
  reply_runner->PostTask(FROM_HERE,
                         base::Bind(reply_callback, base::Passed(&converter)));
}

// Close an input device. Closing may put the calling thread to sleep, and
// therefore should be run on a thread where latency is not critical. We
// run it on the FILE thread.
void CloseInputDevice(const base::FilePath& path,
                      scoped_ptr<EventConverterEvdev> converter) {
  TRACE_EVENT1("ozone", "CloseInputDevice", "path", path.value());
  converter.reset();
}

}  // namespace

EventFactoryEvdev::EventFactoryEvdev(CursorDelegateEvdev* cursor,
                                     DeviceManager* device_manager)
    : last_device_id_(0),
      device_manager_(device_manager),
      dispatch_callback_(
          base::Bind(&EventFactoryEvdev::PostUiEvent, base::Unretained(this))),
      keyboard_(&modifiers_, dispatch_callback_),
      cursor_(cursor),
#if defined(USE_EVDEV_GESTURES)
      gesture_property_provider_(new GesturePropertyProvider),
#endif
      weak_ptr_factory_(this) {
  DCHECK(device_manager_);
}

EventFactoryEvdev::~EventFactoryEvdev() { STLDeleteValues(&converters_); }

void EventFactoryEvdev::PostUiEvent(scoped_ptr<Event> event) {
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE,
      base::Bind(&EventFactoryEvdev::DispatchUiEventTask,
                 weak_ptr_factory_.GetWeakPtr(),
                 base::Passed(&event)));
}

void EventFactoryEvdev::DispatchUiEventTask(scoped_ptr<Event> event) {
  DispatchEvent(event.get());
}

void EventFactoryEvdev::AttachInputDevice(
    scoped_ptr<EventConverterEvdev> converter) {
  const base::FilePath& path = converter->path();

  TRACE_EVENT1("ozone", "AttachInputDevice", "path", path.value());
  DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());

  // If we have an existing device, detach it. We don't want two
  // devices with the same name open at the same time.
  if (converters_[path])
    DetachInputDevice(path);

  // Add initialized device to map.
  converters_[path] = converter.release();
  converters_[path]->Start();

  NotifyHotplugEventObserver(*converters_[path]);
}

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("ozone", "OnDeviceAdded", "path", event.path().value());

      scoped_ptr<OpenInputDeviceParams> params(new OpenInputDeviceParams);
      params->id = NextDeviceId();
      params->path = event.path();
      params->dispatch_callback = dispatch_callback_;
      params->modifiers = &modifiers_;
      params->keyboard = &keyboard_;
      params->cursor = cursor_;
#if defined(USE_EVDEV_GESTURES)
      params->gesture_property_provider = gesture_property_provider_.get();
#endif

      OpenInputDeviceReplyCallback reply_callback =
          base::Bind(&EventFactoryEvdev::AttachInputDevice,
                     weak_ptr_factory_.GetWeakPtr());

      // Dispatch task to open from the worker pool, since open may block.
      base::WorkerPool::PostTask(FROM_HERE,
                                 base::Bind(&OpenInputDevice,
                                            base::Passed(&params),
                                            ui_task_runner_,
                                            reply_callback),
                                 true /* task_is_slow */);
    }
      break;
    case DeviceEvent::REMOVE: {
      TRACE_EVENT1("ozone", "OnDeviceRemoved", "path", event.path().value());
      DetachInputDevice(event.path());
    }
      break;
  }
}

void EventFactoryEvdev::OnDispatcherListChanged() {
  if (!ui_task_runner_.get()) {
    ui_task_runner_ = base::ThreadTaskRunnerHandle::Get();
    // Scan & monitor devices.
    device_manager_->AddObserver(this);
    device_manager_->ScanDevices(this);
  }
}

void EventFactoryEvdev::DetachInputDevice(const base::FilePath& path) {
  TRACE_EVENT1("ozone", "DetachInputDevice", "path", path.value());
  DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());

  // Remove device from map.
  scoped_ptr<EventConverterEvdev> converter(converters_[path]);
  converters_.erase(path);

  if (converter) {
    // Cancel libevent notifications from this converter. This part must be
    // on UI since the polling happens on UI.
    converter->Stop();

    NotifyHotplugEventObserver(*converter);

    // Dispatch task to close from the worker pool, since close may block.
    base::WorkerPool::PostTask(
        FROM_HERE,
        base::Bind(&CloseInputDevice, path, base::Passed(&converter)),
        true);
  }
}

void EventFactoryEvdev::WarpCursorTo(gfx::AcceleratedWidget widget,
                                     const gfx::PointF& location) {
  if (cursor_) {
    cursor_->MoveCursorTo(widget, location);
    PostUiEvent(make_scoped_ptr(new MouseEvent(ET_MOUSE_MOVED,
                                               cursor_->location(),
                                               cursor_->location(),
                                               modifiers_.GetModifierFlags(),
                                               /* changed_button_flags */ 0)));
  }
}

void EventFactoryEvdev::NotifyHotplugEventObserver(
    const EventConverterEvdev& converter) {
  // For now the only information propagated is related to touchscreens. Ignore
  // events for everything but touchscreens.
  if (!converter.HasTouchscreen())
    return;

  DeviceHotplugEventObserver* observer = DeviceDataManager::GetInstance();
  std::vector<TouchscreenDevice> touchscreens;
  for (auto it = converters_.begin(); it != converters_.end(); ++it) {
    if (it->second->HasTouchscreen()) {
      touchscreens.push_back(TouchscreenDevice(it->second->id(),
                                               it->second->GetTouchscreenSize(),
                                               false /* is_internal */));
    }
  }

  observer->OnTouchscreenDevicesUpdated(touchscreens);
}

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

}  // namespace ui
