/*
 * Copyright 2018 The Chromium OS 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 "cros-camera/udev_watcher.h"

#include <string>
#include <utility>

#include <libudev.h>

#include <base/threading/thread.h>
#include <base/threading/thread_task_runner_handle.h>

#include "cros-camera/common.h"
#include "cros-camera/future.h"

namespace cros {

UdevWatcher::Observer::~Observer() = default;

void UdevWatcher::Observer::OnDeviceAdded(ScopedUdevDevicePtr /*device*/) {}

void UdevWatcher::Observer::OnDeviceRemoved(ScopedUdevDevicePtr /*device*/) {}

UdevWatcher::UdevWatcher(Observer* observer, std::string subsystem)
    : observer_(observer),
      subsystem_(std::move(subsystem)),
      fd_watcher_(FROM_HERE),
      thread_("UdevWatcherThread") {}

bool UdevWatcher::Start(
    scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
  udev_.reset(udev_new());
  if (!udev_) {
    LOGF(ERROR) << "udev_new failed";
    return false;
  }

  mon_.reset(udev_monitor_new_from_netlink(udev_.get(), "udev"));
  if (!mon_) {
    LOGF(ERROR) << "udev_monitor_new_from_netlink failed";
    return false;
  }

  if (udev_monitor_filter_add_match_subsystem_devtype(
          mon_.get(), subsystem_.c_str(), nullptr) < 0) {
    LOGF(ERROR) << "udev_monitor_filter_add_match_subsystem_devtype failed";
    return false;
  }

  if (udev_monitor_enable_receiving(mon_.get()) < 0) {
    LOGF(ERROR) << "udev_monitor_enable_receiving failed";
    return false;
  }

  int fd = udev_monitor_get_fd(mon_.get());
  if (fd < 0) {
    LOGF(ERROR) << "udev_monitor_get_fd failed";
    return false;
  }

  if (!thread_.StartWithOptions(
          base::Thread::Options(base::MessageLoop::TYPE_IO, 0))) {
    LOGF(ERROR) << "thread start failed";
    return false;
  }

  callback_task_runner_ = task_runner;

  auto future = cros::Future<bool>::Create(nullptr);
  thread_.task_runner()->PostTask(
      FROM_HERE, base::Bind(&UdevWatcher::StartOnThread, base::Unretained(this),
                            fd, cros::GetFutureCallback(future)));
  return future->Get();
}

bool UdevWatcher::EnumerateExistingDevices() {
  DCHECK(callback_task_runner_) << "Start() shuold be called first";
  DCHECK(callback_task_runner_->BelongsToCurrentThread());

  ScopedUdevEnumeratePtr enumerate(udev_enumerate_new(udev_.get()));
  if (!enumerate) {
    LOGF(ERROR) << "udev_enumerate_new failed";
    return false;
  }

  if (udev_enumerate_add_match_subsystem(enumerate.get(), subsystem_.c_str()) <
      0) {
    LOGF(ERROR) << "udev_enumerate_add_match_subsystem failed";
    return false;
  }

  if (udev_enumerate_scan_devices(enumerate.get()) < 0) {
    LOGF(ERROR) << "udev_enumerate_scan_devices failed";
    return false;
  }

  for (udev_list_entry* entry = udev_enumerate_get_list_entry(enumerate.get());
       entry != nullptr; entry = udev_list_entry_get_next(entry)) {
    // We simply ignore errors in some entries here, and keep enumerating.

    const char* name = udev_list_entry_get_name(entry);
    if (!name) {
      LOGF(WARNING) << "udev_list_entry_get_name failed";
      continue;
    }

    ScopedUdevDevicePtr dev(udev_device_new_from_syspath(udev_.get(), name));
    if (!dev) {
      LOGF(WARNING) << "udev_device_new_from_syspath failed";
      continue;
    }

    observer_->OnDeviceAdded(std::move(dev));
  }

  return true;
}

void UdevWatcher::StartOnThread(int fd, base::Callback<void(bool)> callback) {
  DCHECK(thread_.task_runner()->BelongsToCurrentThread());

  if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
          fd, /*persistent=*/true, base::MessageLoopForIO::WATCH_READ,
          &fd_watcher_, this)) {
    LOGF(ERROR) << "WatchFileDescriptor failed";
    callback.Run(false);
    return;
  }

  callback.Run(true);
}

void UdevWatcher::OnFileCanReadWithoutBlocking(int /*fd*/) {
  DCHECK(thread_.task_runner()->BelongsToCurrentThread());

  ScopedUdevDevicePtr dev(udev_monitor_receive_device(mon_.get()));
  if (!dev) {
    LOGF(ERROR) << "udev_monitor_receive_device failed";
    return;
  }

  const char* action = udev_device_get_action(dev.get());
  if (!action) {
    LOGF(ERROR) << "udev_device_get_action failed";
    return;
  }

  decltype(&Observer::OnDeviceAdded) callback;
  if (strcmp(action, "add") == 0) {
    callback = &Observer::OnDeviceAdded;
  } else if (strcmp(action, "remove") == 0) {
    callback = &Observer::OnDeviceRemoved;
  } else {
    NOTREACHED() << "Unexpected action " << action;
    return;
  }

  callback_task_runner_->PostTask(
      FROM_HERE, base::Bind(callback, base::Unretained(observer_),
                            base::Passed(std::move(dev))));
}

void UdevWatcher::OnFileCanWriteWithoutBlocking(int fd) {
  DCHECK(thread_.task_runner()->BelongsToCurrentThread());
  NOTREACHED() << "Unexpected non-blocking write notification for fd " << fd;
}

}  // namespace cros
