/*
 * 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)),
      thread_("UdevWatcherThread") {}

UdevWatcher::~UdevWatcher() {
  // Post a task to reset FileDescriptorWatcher and explicitly call
  // Thread::Stop() to ensure it is completed before destroying fields.
  thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&UdevWatcher::StopOnThread, base::Unretained(this)));
  thread_.Stop();
}

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());

  watcher_ = base::FileDescriptorWatcher::WatchReadable(
      fd,
      base::BindRepeating(&UdevWatcher::OnReadable, base::Unretained(this)));
  if (!watcher_) {
    LOGF(ERROR) << "Failed to start watching a file descriptor";
    callback.Run(false);
    return;
  }

  callback.Run(true);
}

void UdevWatcher::StopOnThread() {
  watcher_ = nullptr;
}

void UdevWatcher::OnReadable() {
  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))));
}

}  // namespace cros
