// Copyright 2014 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 <brillo/dbus/dbus_object.h>

#include <memory>
#include <utility>
#include <vector>

#include <base/bind.h>
#include <base/bind_helpers.h>
#include <base/logging.h>
#include <brillo/dbus/async_event_sequencer.h>
#include <brillo/dbus/exported_object_manager.h>
#include <brillo/dbus/exported_property_set.h>
#include <dbus/property.h>

namespace brillo {
namespace dbus_utils {

namespace {

void SetupDefaultPropertyHandlers(DBusInterface* prop_interface,
                                  ExportedPropertySet* property_set) {
  prop_interface->AddSimpleMethodHandler(dbus::kPropertiesGetAll,
                                         base::Unretained(property_set),
                                         &ExportedPropertySet::HandleGetAll);
  prop_interface->AddSimpleMethodHandlerWithError(
      dbus::kPropertiesGet, base::Unretained(property_set),
      &ExportedPropertySet::HandleGet);
  prop_interface->AddSimpleMethodHandlerWithError(
      dbus::kPropertiesSet, base::Unretained(property_set),
      &ExportedPropertySet::HandleSet);
}

}  // namespace

//////////////////////////////////////////////////////////////////////////////

DBusInterface::DBusInterface(DBusObject* dbus_object,
                             const std::string& interface_name)
    : dbus_object_(dbus_object),
      interface_name_(interface_name),
      release_interface_cb_(base::DoNothing()) {}

void DBusInterface::AddProperty(const std::string& property_name,
                                ExportedPropertyBase* prop_base) {
  dbus_object_->property_set_.RegisterProperty(interface_name_, property_name,
                                               prop_base);
}

void DBusInterface::RemoveProperty(const std::string& property_name) {
  dbus_object_->property_set_.UnregisterProperty(interface_name_,
                                                 property_name);
}

void DBusInterface::ExportAsync(
    ExportedObjectManager* object_manager,
    dbus::Bus* /* bus */,
    dbus::ExportedObject* exported_object,
    const dbus::ObjectPath& object_path,
    const AsyncEventSequencer::CompletionAction& completion_callback) {
  VLOG(1) << "Registering D-Bus interface '" << interface_name_ << "' for '"
          << object_path.value() << "'";
  scoped_refptr<AsyncEventSequencer> sequencer(new AsyncEventSequencer());
  for (const auto& pair : handlers_) {
    std::string method_name = pair.first;
    VLOG(1) << "Exporting method: " << interface_name_ << "." << method_name;
    std::string export_error = "Failed exporting " + method_name + " method";
    auto export_handler = sequencer->GetExportHandler(
        interface_name_, method_name, export_error, true);
    auto method_handler =
        base::Bind(&DBusInterface::HandleMethodCall, base::Unretained(this));
    exported_object->ExportMethod(interface_name_, method_name, method_handler,
                                  export_handler);
  }

  std::vector<AsyncEventSequencer::CompletionAction> actions;
  if (object_manager) {
    auto property_writer_callback =
        dbus_object_->property_set_.GetPropertyWriter(interface_name_);
    actions.push_back(base::Bind(
        &DBusInterface::ClaimInterface, weak_factory_.GetWeakPtr(),
        object_manager->AsWeakPtr(), object_path, property_writer_callback));
  }
  actions.push_back(completion_callback);
  sequencer->OnAllTasksCompletedCall(actions);
}

void DBusInterface::ExportAndBlock(ExportedObjectManager* object_manager,
                                   dbus::Bus* /* bus */,
                                   dbus::ExportedObject* exported_object,
                                   const dbus::ObjectPath& object_path) {
  VLOG(1) << "Registering D-Bus interface '" << interface_name_ << "' for '"
          << object_path.value() << "'";
  for (const auto& pair : handlers_) {
    std::string method_name = pair.first;
    VLOG(1) << "Exporting method: " << interface_name_ << "." << method_name;
    auto method_handler =
        base::Bind(&DBusInterface::HandleMethodCall, base::Unretained(this));
    if (!exported_object->ExportMethodAndBlock(interface_name_, method_name,
                                               method_handler)) {
      LOG(FATAL) << "Failed exporting " << method_name << " method";
    }
  }

  if (object_manager) {
    auto property_writer_callback =
        dbus_object_->property_set_.GetPropertyWriter(interface_name_);
    ClaimInterface(object_manager->AsWeakPtr(), object_path,
                   property_writer_callback, true);
  }
}

void DBusInterface::UnexportAsync(
    ExportedObjectManager* object_manager,
    dbus::ExportedObject* exported_object,
    const dbus::ObjectPath& object_path,
    const AsyncEventSequencer::CompletionAction& completion_callback) {
  VLOG(1) << "Unexporting D-Bus interface " << interface_name_ << " for "
          << object_path.value();

  // Release the interface.
  release_interface_cb_.RunAndReset();

  // Unexport all method handlers.
  scoped_refptr<AsyncEventSequencer> sequencer(new AsyncEventSequencer());
  for (const auto& pair : handlers_) {
    std::string method_name = pair.first;
    VLOG(1) << "Unexporting method: " << interface_name_ << "." << method_name;
    std::string export_error = "Failed unexporting " + method_name + " method";
    auto export_handler = sequencer->GetExportHandler(
        interface_name_, method_name, export_error, true);
    exported_object->UnexportMethod(interface_name_, method_name,
                                    export_handler);
  }

  sequencer->OnAllTasksCompletedCall({completion_callback});
}

void DBusInterface::UnexportAndBlock(ExportedObjectManager* object_manager,
                                     dbus::ExportedObject* exported_object,
                                     const dbus::ObjectPath& object_path) {
  VLOG(1) << "Unexporting D-Bus interface " << interface_name_ << " for "
          << object_path.value();

  // Release the interface.
  release_interface_cb_.RunAndReset();

  // Unexport all method handlers.
  for (const auto& pair : handlers_) {
    std::string method_name = pair.first;
    VLOG(1) << "Unexporting method: " << interface_name_ << "." << method_name;
    if (!exported_object->UnexportMethodAndBlock(interface_name_, method_name))
      LOG(FATAL) << "Failed unexporting " << method_name << " method";
  }
}

void DBusInterface::ClaimInterface(
    base::WeakPtr<ExportedObjectManager> object_manager,
    const dbus::ObjectPath& object_path,
    const ExportedPropertySet::PropertyWriter& writer,
    bool all_succeeded) {
  if (!all_succeeded || !object_manager) {
    LOG(ERROR) << "Skipping claiming interface: " << interface_name_;
    return;
  }
  object_manager->ClaimInterface(object_path, interface_name_, writer);
  release_interface_cb_.RunAndReset();
  release_interface_cb_.ReplaceClosure(
      base::Bind(&ExportedObjectManager::ReleaseInterface, object_manager,
                 object_path, interface_name_));
}

void DBusInterface::HandleMethodCall(dbus::MethodCall* method_call,
                                     ResponseSender sender) {
  std::string method_name = method_call->GetMember();
  // Make a local copy of |interface_name_| because calling HandleMethod()
  // can potentially kill this interface object...
  std::string interface_name = interface_name_;
  VLOG(1) << "Received method call request: " << interface_name << "."
          << method_name << "(" << method_call->GetSignature() << ")";
  auto pair = handlers_.find(method_name);
  if (pair == handlers_.end()) {
    auto response = dbus::ErrorResponse::FromMethodCall(
        method_call, DBUS_ERROR_UNKNOWN_METHOD,
        "Unknown method: " + method_name);
    std::move(sender).Run(std::move(response));
    return;
  }
  VLOG(1) << "Dispatching DBus method call: " << method_name;
  pair->second->HandleMethod(method_call, std::move(sender));
}

void DBusInterface::AddHandlerImpl(
    const std::string& method_name,
    std::unique_ptr<DBusInterfaceMethodHandlerInterface> handler) {
  VLOG(1) << "Declaring method handler: " << interface_name_ << "."
          << method_name;
  auto res = handlers_.insert(std::make_pair(method_name, std::move(handler)));
  CHECK(res.second) << "Method '" << method_name << "' already exists";
}

void DBusInterface::AddSignalImpl(
    const std::string& signal_name,
    const std::shared_ptr<DBusSignalBase>& signal) {
  VLOG(1) << "Declaring a signal sink: " << interface_name_ << "."
          << signal_name;
  CHECK(signals_.insert(std::make_pair(signal_name, signal)).second)
      << "The signal '" << signal_name << "' is already registered";
}

///////////////////////////////////////////////////////////////////////////////

DBusObject::DBusObject(ExportedObjectManager* object_manager,
                       const scoped_refptr<dbus::Bus>& bus,
                       const dbus::ObjectPath& object_path)
    : DBusObject::DBusObject(object_manager,
                             bus,
                             object_path,
                             base::Bind(&SetupDefaultPropertyHandlers)) {}

DBusObject::DBusObject(
    ExportedObjectManager* object_manager,
    const scoped_refptr<dbus::Bus>& bus,
    const dbus::ObjectPath& object_path,
    PropertyHandlerSetupCallback property_handler_setup_callback)
    : property_set_(bus.get()),
      bus_(bus),
      object_path_(object_path),
      property_handler_setup_callback_(
          std::move(property_handler_setup_callback)) {
  if (object_manager)
    object_manager_ = object_manager->AsWeakPtr();
}

DBusObject::~DBusObject() {
  if (exported_object_)
    exported_object_->Unregister();
}

DBusInterface* DBusObject::AddOrGetInterface(
    const std::string& interface_name) {
  auto iter = interfaces_.find(interface_name);
  if (iter == interfaces_.end()) {
    VLOG(1) << "Adding an interface '" << interface_name << "' to object '"
            << object_path_.value() << "'.";
    // Interface doesn't exist yet. Create one...
    std::unique_ptr<DBusInterface> new_itf(
        new DBusInterface(this, interface_name));
    iter =
        interfaces_.insert(std::make_pair(interface_name, std::move(new_itf)))
            .first;
  }
  return iter->second.get();
}

DBusInterface* DBusObject::FindInterface(
    const std::string& interface_name) const {
  auto itf_iter = interfaces_.find(interface_name);
  return (itf_iter == interfaces_.end()) ? nullptr : itf_iter->second.get();
}

void DBusObject::RemoveInterface(const std::string& interface_name) {
  auto itf_iter = interfaces_.find(interface_name);
  CHECK(itf_iter != interfaces_.end())
      << "Interface " << interface_name << " has not been added.";
  interfaces_.erase(itf_iter);
}

void DBusObject::ExportInterfaceAsync(
    const std::string& interface_name,
    const AsyncEventSequencer::CompletionAction& completion_callback) {
  AddOrGetInterface(interface_name)
      ->ExportAsync(object_manager_.get(), bus_.get(), exported_object_,
                    object_path_, completion_callback);
}

void DBusObject::ExportInterfaceAndBlock(const std::string& interface_name) {
  AddOrGetInterface(interface_name)
      ->ExportAndBlock(object_manager_.get(), bus_.get(), exported_object_,
                       object_path_);
}

void DBusObject::UnexportInterfaceAsync(
    const std::string& interface_name,
    const AsyncEventSequencer::CompletionAction& completion_callback) {
  AddOrGetInterface(interface_name)
      ->UnexportAsync(object_manager_.get(), exported_object_, object_path_,
                      completion_callback);
}

void DBusObject::UnexportInterfaceAndBlock(const std::string& interface_name) {
  AddOrGetInterface(interface_name)
      ->UnexportAndBlock(object_manager_.get(), exported_object_, object_path_);
}

void DBusObject::RegisterAsync(
    const AsyncEventSequencer::CompletionAction& completion_callback) {
  VLOG(1) << "Registering D-Bus object '" << object_path_.value() << "'.";
  CHECK(exported_object_ == nullptr) << "Object already registered.";
  scoped_refptr<AsyncEventSequencer> sequencer(new AsyncEventSequencer());
  exported_object_ = bus_->GetExportedObject(object_path_);

  RegisterPropertiesInterface();

  // Export interface methods
  for (const auto& pair : interfaces_) {
    pair.second->ExportAsync(
        object_manager_.get(), bus_.get(), exported_object_, object_path_,
        sequencer->GetHandler("Failed to export interface " + pair.first,
                              false));
  }

  sequencer->OnAllTasksCompletedCall({completion_callback});
}

void DBusObject::RegisterAndBlock() {
  VLOG(1) << "Registering D-Bus object '" << object_path_.value() << "'.";
  CHECK(exported_object_ == nullptr) << "Object already registered.";
  exported_object_ = bus_->GetExportedObject(object_path_);

  RegisterPropertiesInterface();

  // Export interface methods
  for (const auto& pair : interfaces_) {
    pair.second->ExportAndBlock(object_manager_.get(), bus_.get(),
                                exported_object_, object_path_);
  }
}

void DBusObject::UnregisterAsync() {
  VLOG(1) << "Unregistering D-Bus object '" << object_path_.value() << "'.";
  CHECK(exported_object_ != nullptr) << "Object not registered.";

  // This will unregister the object path from the bus.
  exported_object_->Unregister();
  // This will remove |exported_object_| from bus's object table. This function
  // will also post a task to unregister |exported_object_| (same as the call
  // above), which will be a no-op since it is already done by then.
  // By doing both in here, the object path is guarantee to be reusable upon
  // return from this function.
  bus_->UnregisterExportedObject(object_path_);
  exported_object_ = nullptr;
}

bool DBusObject::SendSignal(dbus::Signal* signal) {
  if (exported_object_) {
    exported_object_->SendSignal(signal);
    return true;
  }
  LOG(ERROR) << "Trying to send a signal from an object that is not exported";
  return false;
}

void DBusObject::RegisterPropertiesInterface() {
  DBusInterface* prop_interface = AddOrGetInterface(dbus::kPropertiesInterface);
  property_handler_setup_callback_.Run(prop_interface, &property_set_);
  property_set_.OnPropertiesInterfaceExported(prop_interface);
}

}  // namespace dbus_utils
}  // namespace brillo
