// 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 <libudev.h>

#include "base/bind.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/threading/thread_restrictions.h"
#include "device/hid/input_service_linux.h"

namespace device {

namespace {

const char kSubsystemHid[] = "hid";
const char kSubsystemInput[] = "input";
const char kTypeBluetooth[] = "bluetooth";
const char kTypeUsb[] = "usb";
const char kTypeSerio[] = "serio";
const char kIdInputAccelerometer[] = "ID_INPUT_ACCELEROMETER";
const char kIdInputJoystick[] = "ID_INPUT_JOYSTICK";
const char kIdInputKey[] = "ID_INPUT_KEY";
const char kIdInputKeyboard[] = "ID_INPUT_KEYBOARD";
const char kIdInputMouse[] = "ID_INPUT_MOUSE";
const char kIdInputTablet[] = "ID_INPUT_TABLET";
const char kIdInputTouchpad[] = "ID_INPUT_TOUCHPAD";
const char kIdInputTouchscreen[] = "ID_INPUT_TOUCHSCREEN";

// The instance will be reset when message loop destroys.
base::LazyInstance<scoped_ptr<InputServiceLinux> >::Leaky
    g_input_service_linux_ptr = LAZY_INSTANCE_INITIALIZER;

bool GetBoolProperty(udev_device* device, const char* key) {
  CHECK(device);
  CHECK(key);
  const char* property = udev_device_get_property_value(device, key);
  if (!property)
    return false;
  int value;
  if (!base::StringToInt(property, &value)) {
    LOG(ERROR) << "Not an integer value for " << key << " property";
    return false;
  }
  return (value != 0);
}

InputServiceLinux::InputDeviceInfo::Type GetDeviceType(udev_device* device) {
  if (udev_device_get_parent_with_subsystem_devtype(
          device, kTypeBluetooth, NULL)) {
    return InputServiceLinux::InputDeviceInfo::TYPE_BLUETOOTH;
  }
  if (udev_device_get_parent_with_subsystem_devtype(device, kTypeUsb, NULL))
    return InputServiceLinux::InputDeviceInfo::TYPE_USB;
  if (udev_device_get_parent_with_subsystem_devtype(device, kTypeSerio, NULL))
    return InputServiceLinux::InputDeviceInfo::TYPE_SERIO;
  return InputServiceLinux::InputDeviceInfo::TYPE_UNKNOWN;
}

std::string GetParentDeviceName(udev_device* device, const char* subsystem) {
  udev_device* parent =
      udev_device_get_parent_with_subsystem_devtype(device, subsystem, NULL);
  if (!parent)
    return std::string();
  const char* name = udev_device_get_property_value(parent, "NAME");
  if (!name)
    return std::string();
  std::string result;
  base::TrimString(name, "\"", &result);
  return result;
}

class InputServiceLinuxImpl : public InputServiceLinux,
                              public DeviceMonitorLinux::Observer {
 public:
  // Implements DeviceMonitorLinux::Observer:
  virtual void OnDeviceAdded(udev_device* device) OVERRIDE;
  virtual void OnDeviceRemoved(udev_device* device) OVERRIDE;

 private:
  friend class InputServiceLinux;

  InputServiceLinuxImpl();
  virtual ~InputServiceLinuxImpl();

  DISALLOW_COPY_AND_ASSIGN(InputServiceLinuxImpl);
};

InputServiceLinuxImpl::InputServiceLinuxImpl() {
  DeviceMonitorLinux::GetInstance()->AddObserver(this);
  DeviceMonitorLinux::GetInstance()->Enumerate(base::Bind(
      &InputServiceLinuxImpl::OnDeviceAdded, base::Unretained(this)));
}

InputServiceLinuxImpl::~InputServiceLinuxImpl() {
  if (DeviceMonitorLinux::HasInstance())
    DeviceMonitorLinux::GetInstance()->RemoveObserver(this);
}

void InputServiceLinuxImpl::OnDeviceAdded(udev_device* device) {
  DCHECK(CalledOnValidThread());
  if (!device)
    return;
  const char* devnode = udev_device_get_devnode(device);
  if (!devnode)
    return;

  InputDeviceInfo info;
  info.id = devnode;

  const char* subsystem = udev_device_get_subsystem(device);
  if (!subsystem)
    return;
  if (strcmp(subsystem, kSubsystemHid) == 0) {
    info.subsystem = InputServiceLinux::InputDeviceInfo::SUBSYSTEM_HID;
    info.name = GetParentDeviceName(device, kSubsystemHid);
  } else if (strcmp(subsystem, kSubsystemInput) == 0) {
    info.subsystem = InputServiceLinux::InputDeviceInfo::SUBSYSTEM_INPUT;
    info.name = GetParentDeviceName(device, kSubsystemInput);
  } else {
    return;
  }

  info.type = GetDeviceType(device);

  info.is_accelerometer = GetBoolProperty(device, kIdInputAccelerometer);
  info.is_joystick = GetBoolProperty(device, kIdInputJoystick);
  info.is_key = GetBoolProperty(device, kIdInputKey);
  info.is_keyboard = GetBoolProperty(device, kIdInputKeyboard);
  info.is_mouse = GetBoolProperty(device, kIdInputMouse);
  info.is_tablet = GetBoolProperty(device, kIdInputTablet);
  info.is_touchpad = GetBoolProperty(device, kIdInputTouchpad);
  info.is_touchscreen = GetBoolProperty(device, kIdInputTouchscreen);

  AddDevice(info);
}

void InputServiceLinuxImpl::OnDeviceRemoved(udev_device* device) {
  DCHECK(CalledOnValidThread());
  if (!device)
    return;
  const char* devnode = udev_device_get_devnode(device);
  if (devnode)
    RemoveDevice(devnode);
}

}  // namespace

InputServiceLinux::InputDeviceInfo::InputDeviceInfo()
    : subsystem(SUBSYSTEM_UNKNOWN),
      type(TYPE_UNKNOWN),
      is_accelerometer(false),
      is_joystick(false),
      is_key(false),
      is_keyboard(false),
      is_mouse(false),
      is_tablet(false),
      is_touchpad(false),
      is_touchscreen(false) {}

InputServiceLinux::InputServiceLinux() {
  base::ThreadRestrictions::AssertIOAllowed();
  base::MessageLoop::current()->AddDestructionObserver(this);
}

InputServiceLinux::~InputServiceLinux() {
  DCHECK(CalledOnValidThread());
  base::MessageLoop::current()->RemoveDestructionObserver(this);
}

// static
InputServiceLinux* InputServiceLinux::GetInstance() {
  if (!HasInstance())
    g_input_service_linux_ptr.Get().reset(new InputServiceLinuxImpl());
  return g_input_service_linux_ptr.Get().get();
}

// static
bool InputServiceLinux::HasInstance() {
  return g_input_service_linux_ptr.Get().get();
}

// static
void InputServiceLinux::SetForTesting(InputServiceLinux* service) {
  g_input_service_linux_ptr.Get().reset(service);
}

void InputServiceLinux::AddObserver(Observer* observer) {
  DCHECK(CalledOnValidThread());
  if (observer)
    observers_.AddObserver(observer);
}

void InputServiceLinux::RemoveObserver(Observer* observer) {
  DCHECK(CalledOnValidThread());
  if (observer)
    observers_.RemoveObserver(observer);
}

void InputServiceLinux::GetDevices(std::vector<InputDeviceInfo>* devices) {
  DCHECK(CalledOnValidThread());
  for (DeviceMap::iterator it = devices_.begin(), ie = devices_.end(); it != ie;
       ++it) {
    devices->push_back(it->second);
  }
}

bool InputServiceLinux::GetDeviceInfo(const std::string& id,
                                      InputDeviceInfo* info) const {
  DCHECK(CalledOnValidThread());
  DeviceMap::const_iterator it = devices_.find(id);
  if (it == devices_.end())
    return false;
  *info = it->second;
  return true;
}

void InputServiceLinux::WillDestroyCurrentMessageLoop() {
  DCHECK(CalledOnValidThread());
  g_input_service_linux_ptr.Get().reset(NULL);
}

void InputServiceLinux::AddDevice(const InputDeviceInfo& info) {
  devices_[info.id] = info;
  FOR_EACH_OBSERVER(Observer, observers_, OnInputDeviceAdded(info));
}

void InputServiceLinux::RemoveDevice(const std::string& id) {
  devices_.erase(id);
  FOR_EACH_OBSERVER(Observer, observers_, OnInputDeviceRemoved(id));
}

bool InputServiceLinux::CalledOnValidThread() const {
  return thread_checker_.CalledOnValidThread();
}

}  // namespace device
