// -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 2 -*-

/* Copyright (C) 2010 The giomm Development Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <giomm/dbusmethodinvocation.h>
#include <gio/gio.h>

_DEFS(giomm,gio)
_PINCLUDE(glibmm/private/object_p.h)

namespace Gio
{

namespace DBus
{

/**This represents a virtual table for
 * handling properties and method calls for a D-Bus interface.
 *
 * If you want to handle getting/setting D-Bus properties asynchronously,
 * simply register an object with the org.freedesktop.DBus.Properties D-Bus
 * interface using Gio::DBus::Connection::register_object().
 *
 * The only correct use of this class is to declare a global instance of it
 * (or an instance local to the main function) and pass pointers to the
 * instance to the methods that require such a parameter.  The instance can be
 * used for multiple registrations and the memory it uses will be freed at the
 * end of execution.  Any other use (like creating an instance local to a
 * function and using that) may cause memory leaks or errors (if the instance
 * is destroyed too early).
 *
 * @newin{2,28}
 * @ingroup DBus
 */
class InterfaceVTable
{
  _CLASS_GENERIC(InterfaceVTable, GDBusInterfaceVTable)

public:
  /** The type for a slot which handles a method call for a D-Bus interface.
   * for example,
   * @code
   * void on_interface_method_call(const Glib::RefPtr<Gio::DBus::Connection>&
   * connection, const Glib::ustring& sender, const Glib::ustring&
   * object_path, const Glib::ustring& interface_name, const Glib::ustring&
   * method_name, const Glib::VariantContainerBase& parameters, const
   * Glib::RefPtr<Gio::DBus::MethodInvocation>& invocation);
   * @endcode
   */
  typedef sigc::slot<
    void,
    const Glib::RefPtr<Connection>&,
    const Glib::ustring&,
    const Glib::ustring&,
    const Glib::ustring&,
    const Glib::ustring&,
    const Glib::VariantContainerBase&,
    const Glib::RefPtr<MethodInvocation>&
  > SlotInterfaceMethodCall;

  /** The type for a slot which handles getting a property for a D-Bus
   * interface.
   * for example,
   * @code
   * void on_interface_get_property(Glib::VariantBase& property, const
   * Glib::RefPtr<Gio::DBus::Connection>& connection, const Glib::ustring&
   * sender, const Glib::ustring& object_path, const Glib::ustring&
   * interface_name, const Glib::ustring& property_name);
   * @endcode
   * @throw Glib::Error.
   */
  typedef sigc::slot<
    void,
    Glib::VariantBase&,
    const Glib::RefPtr<Connection>&,
    const Glib::ustring&,
    const Glib::ustring&,
    const Glib::ustring&,
    const Glib::ustring&
  > SlotInterfaceGetProperty;

  /** The type for a slot which handles setting a property for a D-Bus
   * interface.
   * for example,
   * @code
   * bool on_interface_set_property(const Glib::RefPtr<Gio::DBus::Connection>&
   * connection, const Glib::ustring& sender, const Glib::ustring&
   * object_path, const Glib::ustring& interface_name, const Glib::ustring&
   * property_name, const Glib::VariantBase& value);
   * @endcode
   * @throw Glib::Error.
   */
  typedef sigc::slot<
    bool,
    const Glib::RefPtr<Connection>&,
    const Glib::ustring&,
    const Glib::ustring&,
    const Glib::ustring&,
    const Glib::ustring&,
    const Glib::VariantBase&
  > SlotInterfaceSetProperty;

  /** Constructs a new InterfaceVTable using the specified slots.
   * @param slot_method_call The slot for handling incoming method calls.
   * @param slot_get_property The slot for getting a property.
   * @param slot_set_property The slot for setting a property.
   */
  explicit InterfaceVTable(
   const SlotInterfaceMethodCall& slot_method_call,
   const SlotInterfaceGetProperty& slot_get_property = SlotInterfaceGetProperty(),
   const SlotInterfaceSetProperty& slot_set_property = SlotInterfaceSetProperty()
  );

  /// Destructor.
  virtual ~InterfaceVTable();

  /// Provides access to the underlying C object.
  GDBusInterfaceVTable* gobj()
    { return reinterpret_cast<GDBusInterfaceVTable*>(&gobject_); }

  /// Provides access to the underlying C object.
  const GDBusInterfaceVTable* gobj() const
    { return reinterpret_cast<const GDBusInterfaceVTable*>(&gobject_); }


private:
  // Non-copyable.
  InterfaceVTable(const InterfaceVTable& other);
  InterfaceVTable& operator=(const InterfaceVTable& other);

public:
#ifndef DOXYGEN_SHOULD_SKIP_THIS
  // These are so the C callbacks and the
  // Gio::DBus::Connection::register_object() method can have access to the
  // copies of the slots used for creation when registering.
  SlotInterfaceMethodCall*      get_slot_method_call() const;
  SlotInterfaceGetProperty*     get_slot_get_property() const;
  SlotInterfaceSetProperty*     get_slot_set_property() const;
#endif

protected:
  // The underlying C instance.
  GDBusInterfaceVTable          gobject_;

  // Pointers to copies of the slots used to create an instance.
  SlotInterfaceMethodCall*      slot_method_call_;
  SlotInterfaceGetProperty*     slot_get_property_;
  SlotInterfaceSetProperty*     slot_set_property_;
};


} //namespace DBus

} // namespace Gio
