// Copyright (c) 2009 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.

#ifndef LIBBRILLO_BRILLO_GLIB_DBUS_H_
#define LIBBRILLO_BRILLO_GLIB_DBUS_H_

// IMPORTANT: Do not use this in new code. Instead, use libchrome's D-Bus
// bindings. See https://goo.gl/EH3MmR for more details.

#include <dbus/dbus-glib.h>
#include <glib-object.h>

#include <algorithm>
#include <string>
#include <utility>

#include "base/logging.h"
#include <brillo/brillo_export.h>
#include <brillo/glib/object.h>

struct DBusMessage;
struct DBusConnection;

namespace brillo {

namespace dbus {

// \brief   BusConnection manages the ref-count for a ::DBusGConnection*.
//
// A BusConnection has reference semantics bound to a particular communication
// bus.
//
// \models Copyable, Assignable
// \related GetSystemBusConnection()

class BRILLO_EXPORT BusConnection {
 public:
  typedef ::DBusGConnection* value_type;

  BusConnection(const BusConnection& x) : object_(x.object_) {
    if (object_)
      ::dbus_g_connection_ref(object_);
  }

  ~BusConnection() {
    if (object_)
      ::dbus_g_connection_unref(object_);
  }

  BusConnection& operator=(BusConnection x) {
    swap(*this, x);
    return *this;
  }

  const value_type& g_connection() const {
    DCHECK(object_) << "referencing an empty connection";
    return object_;
  }

  operator bool() const { return object_; }

  bool HasConnection() const { return object_; }

 private:
  friend void swap(BusConnection& x, BusConnection& y);

  friend class Proxy;
  friend BusConnection GetSystemBusConnection();
  friend BusConnection GetPrivateBusConnection(const char* address);

  // Constructor takes ownership
  BRILLO_PRIVATE explicit BusConnection(::DBusGConnection* x) : object_(x) {}

  value_type object_;
};

inline void swap(BusConnection& x, BusConnection& y) {
  std::swap(x.object_, y.object_);
}

// \brief Proxy manages the ref-count for a ::DBusGProxy*.
//
// Proxy has reference semantics and represents a connection to on object on
// the bus. A proxy object is constructed with a connection to a bus, a name
// to an entity on the bus, a path to an object owned by the entity, and an
// interface protocol name used to communicate with the object.

class BRILLO_EXPORT Proxy {
 public:
  typedef ::DBusGProxy* value_type;

  Proxy();

  // Set |connect_to_name_owner| true if you'd like to use
  // dbus_g_proxy_new_for_name_owner() rather than dbus_g_proxy_new_for_name().
  Proxy(const BusConnection& connection,
        const char* name,
        const char* path,
        const char* interface,
        bool connect_to_name_owner);

  // Equivalent to Proxy(connection, name, path, interface, false).
  Proxy(const BusConnection& connection,
        const char* name,
        const char* path,
        const char* interface);

  // Creates a peer proxy using dbus_g_proxy_new_for_peer.
  Proxy(const BusConnection& connection,
        const char* path,
        const char* interface);

  Proxy(const Proxy& x);

  ~Proxy();

  Proxy& operator=(Proxy x) {
    swap(*this, x);
    return *this;
  }

  const char* path() const {
    DCHECK(object_) << "referencing an empty proxy";
    return ::dbus_g_proxy_get_path(object_);
  }

  // gproxy() returns a reference to the underlying ::DBusGProxy*. As this
  // library evolves, the gproxy() will be moved to be private.

  const value_type& gproxy() const {
    DCHECK(object_) << "referencing an empty proxy";
    return object_;
  }

  operator bool() const { return object_; }

 private:
  BRILLO_PRIVATE static value_type GetGProxy(const BusConnection& connection,
                                             const char* name,
                                             const char* path,
                                             const char* interface,
                                             bool connect_to_name_owner);

  BRILLO_PRIVATE static value_type GetGPeerProxy(
      const BusConnection& connection, const char* path, const char* interface);

  BRILLO_PRIVATE operator int() const;  // for safe bool cast
  friend void swap(Proxy& x, Proxy& y);

  value_type object_;
};

inline void swap(Proxy& x, Proxy& y) {
  std::swap(x.object_, y.object_);
}

// \brief RegisterExclusiveService configures a GObject to run as a service on
//  a supplied ::BusConnection.
//
//  RegisterExclusiveService encapsulates the process of configuring the
//  supplied \param object at \param service_path on the \param connection.
//  Exclusivity is ensured by replacing any existing services at that named
//  location and confirming that the connection is the primary owner.
//
//  Type information for the \param object must be installed with
//  dbus_g_object_type_install_info prior to use.

BRILLO_EXPORT bool RegisterExclusiveService(const BusConnection& connection,
                                            const char* interface_name,
                                            const char* service_name,
                                            const char* service_path,
                                            GObject* object);

template <typename F>  // F is a function signature
class MonitorConnection;

template <typename A1>
class MonitorConnection<void(A1)> {
 public:
  MonitorConnection(const Proxy& proxy,
                    const char* name,
                    void (*monitor)(void*, A1),
                    void* object)
      : proxy_(proxy), name_(name), monitor_(monitor), object_(object) {}

  static void Run(::DBusGProxy*, A1 x, MonitorConnection* self) {
    self->monitor_(self->object_, x);
  }
  const Proxy& proxy() const { return proxy_; }
  const std::string& name() const { return name_; }

 private:
  Proxy proxy_;
  std::string name_;
  void (*monitor_)(void*, A1);
  void* object_;
};

template <typename A1, typename A2>
class MonitorConnection<void(A1, A2)> {
 public:
  MonitorConnection(const Proxy& proxy,
                    const char* name,
                    void (*monitor)(void*, A1, A2),
                    void* object)
      : proxy_(proxy), name_(name), monitor_(monitor), object_(object) {}

  static void Run(::DBusGProxy*, A1 x, A2 y, MonitorConnection* self) {
    self->monitor_(self->object_, x, y);
  }
  const Proxy& proxy() const { return proxy_; }
  const std::string& name() const { return name_; }

 private:
  Proxy proxy_;
  std::string name_;
  void (*monitor_)(void*, A1, A2);
  void* object_;
};

template <typename A1, typename A2, typename A3>
class MonitorConnection<void(A1, A2, A3)> {
 public:
  MonitorConnection(const Proxy& proxy,
                    const char* name,
                    void (*monitor)(void*, A1, A2, A3),
                    void* object)
      : proxy_(proxy), name_(name), monitor_(monitor), object_(object) {}

  static void Run(::DBusGProxy*, A1 x, A2 y, A3 z, MonitorConnection* self) {
    self->monitor_(self->object_, x, y, z);
  }
  const Proxy& proxy() const { return proxy_; }
  const std::string& name() const { return name_; }

 private:
  Proxy proxy_;
  std::string name_;
  void (*monitor_)(void*, A1, A2, A3);
  void* object_;
};

template <typename A1, typename A2, typename A3, typename A4>
class MonitorConnection<void(A1, A2, A3, A4)> {
 public:
  MonitorConnection(const Proxy& proxy,
                    const char* name,
                    void (*monitor)(void*, A1, A2, A3, A4),
                    void* object)
      : proxy_(proxy), name_(name), monitor_(monitor), object_(object) {}

  static void Run(
      ::DBusGProxy*, A1 x, A2 y, A3 z, A4 w, MonitorConnection* self) {
    self->monitor_(self->object_, x, y, z, w);
  }
  const Proxy& proxy() const { return proxy_; }
  const std::string& name() const { return name_; }

 private:
  Proxy proxy_;
  std::string name_;
  void (*monitor_)(void*, A1, A2, A3, A4);
  void* object_;
};

template <typename A1>
MonitorConnection<void(A1)>* Monitor(const Proxy& proxy,
                                     const char* name,
                                     void (*monitor)(void*, A1),
                                     void* object) {
  typedef MonitorConnection<void(A1)> ConnectionType;

  ConnectionType* result = new ConnectionType(proxy, name, monitor, object);

  ::dbus_g_proxy_add_signal(proxy.gproxy(), name, glib::type_to_gtypeid<A1>(),
                            G_TYPE_INVALID);
  ::dbus_g_proxy_connect_signal(
      proxy.gproxy(), name, G_CALLBACK(&ConnectionType::Run), result, nullptr);
  return result;
}

template <typename A1, typename A2>
MonitorConnection<void(A1, A2)>* Monitor(const Proxy& proxy,
                                         const char* name,
                                         void (*monitor)(void*, A1, A2),
                                         void* object) {
  typedef MonitorConnection<void(A1, A2)> ConnectionType;

  ConnectionType* result = new ConnectionType(proxy, name, monitor, object);

  ::dbus_g_proxy_add_signal(proxy.gproxy(), name, glib::type_to_gtypeid<A1>(),
                            glib::type_to_gtypeid<A2>(), G_TYPE_INVALID);
  ::dbus_g_proxy_connect_signal(
      proxy.gproxy(), name, G_CALLBACK(&ConnectionType::Run), result, nullptr);
  return result;
}

template <typename A1, typename A2, typename A3>
MonitorConnection<void(A1, A2, A3)>* Monitor(const Proxy& proxy,
                                             const char* name,
                                             void (*monitor)(void*, A1, A2, A3),
                                             void* object) {
  typedef MonitorConnection<void(A1, A2, A3)> ConnectionType;

  ConnectionType* result = new ConnectionType(proxy, name, monitor, object);

  ::dbus_g_proxy_add_signal(proxy.gproxy(), name, glib::type_to_gtypeid<A1>(),
                            glib::type_to_gtypeid<A2>(),
                            glib::type_to_gtypeid<A3>(), G_TYPE_INVALID);
  ::dbus_g_proxy_connect_signal(
      proxy.gproxy(), name, G_CALLBACK(&ConnectionType::Run), result, nullptr);
  return result;
}

template <typename A1, typename A2, typename A3, typename A4>
MonitorConnection<void(A1, A2, A3, A4)>* Monitor(
    const Proxy& proxy,
    const char* name,
    void (*monitor)(void*, A1, A2, A3, A4),
    void* object) {
  typedef MonitorConnection<void(A1, A2, A3, A4)> ConnectionType;

  ConnectionType* result = new ConnectionType(proxy, name, monitor, object);

  ::dbus_g_proxy_add_signal(proxy.gproxy(), name, glib::type_to_gtypeid<A1>(),
                            glib::type_to_gtypeid<A2>(),
                            glib::type_to_gtypeid<A3>(),
                            glib::type_to_gtypeid<A4>(), G_TYPE_INVALID);
  ::dbus_g_proxy_connect_signal(
      proxy.gproxy(), name, G_CALLBACK(&ConnectionType::Run), result, nullptr);
  return result;
}

template <typename F>
void Disconnect(MonitorConnection<F>* connection) {
  typedef MonitorConnection<F> ConnectionType;

  ::dbus_g_proxy_disconnect_signal(
      connection->proxy().gproxy(), connection->name().c_str(),
      G_CALLBACK(&ConnectionType::Run), connection);
  delete connection;
}

// \brief call_PtrArray() invokes a method on a proxy returning a
//  glib::PtrArray.
//
// CallPtrArray is the first instance of what is likely to be a general
// way to make method calls to a proxy. It will likely be replaced with
// something like Call(proxy, method, arg1, arg2, ..., ResultType*) in the
// future. However, I don't yet have enough cases to generalize from.

BRILLO_EXPORT bool CallPtrArray(const Proxy& proxy,
                                const char* method,
                                glib::ScopedPtrArray<const char*>* result);

// \brief RetrieveProperty() retrieves a property of an object associated with a
//  proxy.
//
// Given a proxy to an object supporting the org.freedesktop.DBus.Properties
// interface, the RetrieveProperty() call will retrieve a property of the
// specified interface on the object storing it in \param result and returning
// \true. If the dbus call fails or the object returned is not of type \param T,
// then \false is returned and \param result is unchanged.
//
// \example
// Proxy proxy(GetSystemBusConnection(),
//             "org.freedesktop.DeviceKit.Power", // A named entity on the bus
//             battery_name,  // Path to a battery on the bus
//             "org.freedesktop.DBus.Properties") // Properties interface
//
// double x;
// if (RetrieveProperty(proxy,
//                      "org.freedesktop.DeviceKit.Power.Device",
//                      "percentage")
//   std::cout << "Battery charge is " << x << "% of capacity.";
// \end_example

template <typename T>
inline bool RetrieveProperty(const Proxy& proxy,
                             const char* interface,
                             const char* property,
                             T* result) {
  glib::ScopedError error;
  glib::Value value;

  if (!::dbus_g_proxy_call(proxy.gproxy(), "Get", &Resetter(&error).lvalue(),
                           G_TYPE_STRING, interface, G_TYPE_STRING, property,
                           G_TYPE_INVALID, G_TYPE_VALUE, &value,
                           G_TYPE_INVALID)) {
    LOG(ERROR) << "Getting property failed: "
               << (error->message ? error->message : "Unknown Error.");
    return false;
  }
  return glib::Retrieve(value, result);
}

// \brief RetrieveProperties returns a HashTable of all properties for the
// specified interface.

BRILLO_EXPORT bool RetrieveProperties(const Proxy& proxy,
                                      const char* interface,
                                      glib::ScopedHashTable* result);

// \brief Returns a connection to the system bus.

BRILLO_EXPORT BusConnection GetSystemBusConnection();

// \brief Returns a private connection to a bus at |address|.

BRILLO_EXPORT BusConnection GetPrivateBusConnection(const char* address);

// \brief Calls a method |method_name| with no arguments per the given |path|
// and |interface_name|.  Ignores return value.

BRILLO_EXPORT void CallMethodWithNoArguments(const char* service_name,
                                             const char* path,
                                             const char* interface_name,
                                             const char* method_name);

// \brief Low-level signal monitor base class.
//
// Used when there is no definite named signal sender (that Proxy
// could be used for).

class BRILLO_EXPORT SignalWatcher {
 public:
  SignalWatcher() {}
  ~SignalWatcher();
  void StartMonitoring(const std::string& interface, const std::string& signal);

 private:
  // Callback invoked on the given signal arrival.
  virtual void OnSignal(DBusMessage* message) = 0;

  // Returns a string matching the D-Bus messages that we want to listen for.
  BRILLO_PRIVATE std::string GetDBusMatchString() const;

  // A D-Bus message filter to receive signals.
  BRILLO_PRIVATE static DBusHandlerResult FilterDBusMessage(
      DBusConnection* dbus_conn, DBusMessage* message, void* data);
  std::string interface_;
  std::string signal_;
};

}  // namespace dbus
}  // namespace brillo

#endif  // LIBBRILLO_BRILLO_GLIB_DBUS_H_
