#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <string>
#include <list>
#include <map>
#include <deque>

#include <stdlib.h>
#include <gio/gio.h>

#include "dbus/DBusBindingGio.hh"
#include "dbus/DBusException.hh"
#include "DBusGUI.hh"

using namespace std;
using namespace workrave::dbus;

class DBusGUI_Marshall : public DBusMarshallGio
{
public:
  void get_operation_mode(GVariant *variant, OperationMode *result);
  GVariant *put_operation_mode(const OperationMode *result);

  void get_TimerData(GVariant *variant, GenericDBusApplet::TimerData *result);
  GVariant *put_TimerData(const GenericDBusApplet::TimerData *result);
  void get_MenuItem(GVariant *variant, GenericDBusApplet::MenuItem *result);
  GVariant *put_MenuItem(const GenericDBusApplet::MenuItem *result);

  void get_MenuItems(GVariant *variant, GenericDBusApplet::MenuItems *result);
  GVariant *put_MenuItems(const GenericDBusApplet::MenuItems *result);

};


void
DBusGUI_Marshall::get_operation_mode(GVariant *variant, OperationMode *result)
{
  std::string value;
  get_string(variant, &value);

if("normal" == value)
    {
      *result = OPERATION_MODE_NORMAL;
    }
else if("suspended" == value)
    {
      *result = OPERATION_MODE_SUSPENDED;
    }
else if("quiet" == value)
    {
      *result = OPERATION_MODE_QUIET;
    }
  else
    {
      throw DBusRemoteException()
        << message_info("Type error in enum")
        << error_code_info(DBUS_ERROR_INVALID_ARGS)
        << actual_type_info("operation_mode");
    }
}

GVariant *
DBusGUI_Marshall::put_operation_mode(const OperationMode *result)
{
  string value;
  switch (*result)
    {
    case OPERATION_MODE_NORMAL:
      value = "normal";
      break;
    case OPERATION_MODE_SUSPENDED:
      value = "suspended";
      break;
    case OPERATION_MODE_QUIET:
      value = "quiet";
      break;
    default:
      throw DBusRemoteException()
        << message_info("Type error in enum")
        << error_code_info(DBUS_ERROR_INVALID_ARGS)
        << actual_type_info("operation_mode");
    }

  return put_string(&value);
}



void
DBusGUI_Marshall::get_TimerData(GVariant *variant, GenericDBusApplet::TimerData *result)
{

  gsize num_fields = g_variant_n_children(variant);
  if (num_fields != 8)
    {
      throw DBusRemoteException()
        << message_info("Incorrect number of member in struct")
        << error_code_info(DBUS_ERROR_INVALID_ARGS)
        << actual_type_info("TimerData");
    }

  GVariant *v_bar_text = g_variant_get_child_value(variant, 0);
  get_string(v_bar_text, &result->bar_text);
  GVariant *v_slot = g_variant_get_child_value(variant, 1);
  get_int(v_slot, &result->slot);
  GVariant *v_bar_secondary_color = g_variant_get_child_value(variant, 2);
  get_uint32(v_bar_secondary_color, &result->bar_secondary_color);
  GVariant *v_bar_secondary_val = g_variant_get_child_value(variant, 3);
  get_uint32(v_bar_secondary_val, &result->bar_secondary_val);
  GVariant *v_bar_secondary_max = g_variant_get_child_value(variant, 4);
  get_uint32(v_bar_secondary_max, &result->bar_secondary_max);
  GVariant *v_bar_primary_color = g_variant_get_child_value(variant, 5);
  get_uint32(v_bar_primary_color, &result->bar_primary_color);
  GVariant *v_bar_primary_val = g_variant_get_child_value(variant, 6);
  get_uint32(v_bar_primary_val, &result->bar_primary_val);
  GVariant *v_bar_primary_max = g_variant_get_child_value(variant, 7);
  get_uint32(v_bar_primary_max, &result->bar_primary_max);

  g_variant_unref(v_bar_text);
  g_variant_unref(v_slot);
  g_variant_unref(v_bar_secondary_color);
  g_variant_unref(v_bar_secondary_val);
  g_variant_unref(v_bar_secondary_max);
  g_variant_unref(v_bar_primary_color);
  g_variant_unref(v_bar_primary_val);
  g_variant_unref(v_bar_primary_max);
}

GVariant *
DBusGUI_Marshall::put_TimerData(const GenericDBusApplet::TimerData *result)
{
  GVariantBuilder builder;
  g_variant_builder_init(&builder, (GVariantType *)"(siuuuuuu)");

  GVariant *v;
  v = put_string(&(result->bar_text));
  g_variant_builder_add_value(&builder, v);
  v = put_int(&(result->slot));
  g_variant_builder_add_value(&builder, v);
  v = put_uint32(&(result->bar_secondary_color));
  g_variant_builder_add_value(&builder, v);
  v = put_uint32(&(result->bar_secondary_val));
  g_variant_builder_add_value(&builder, v);
  v = put_uint32(&(result->bar_secondary_max));
  g_variant_builder_add_value(&builder, v);
  v = put_uint32(&(result->bar_primary_color));
  g_variant_builder_add_value(&builder, v);
  v = put_uint32(&(result->bar_primary_val));
  g_variant_builder_add_value(&builder, v);
  v = put_uint32(&(result->bar_primary_max));
  g_variant_builder_add_value(&builder, v);

  return g_variant_builder_end(&builder);
}


void
DBusGUI_Marshall::get_MenuItem(GVariant *variant, GenericDBusApplet::MenuItem *result)
{

  gsize num_fields = g_variant_n_children(variant);
  if (num_fields != 3)
    {
      throw DBusRemoteException()
        << message_info("Incorrect number of member in struct")
        << error_code_info(DBUS_ERROR_INVALID_ARGS)
        << actual_type_info("MenuItem");
    }

  GVariant *v_text = g_variant_get_child_value(variant, 0);
  get_string(v_text, &result->text);
  GVariant *v_command = g_variant_get_child_value(variant, 1);
  get_int32(v_command, &result->command);
  GVariant *v_flags = g_variant_get_child_value(variant, 2);
  get_int32(v_flags, &result->flags);

  g_variant_unref(v_text);
  g_variant_unref(v_command);
  g_variant_unref(v_flags);
}

GVariant *
DBusGUI_Marshall::put_MenuItem(const GenericDBusApplet::MenuItem *result)
{
  GVariantBuilder builder;
  g_variant_builder_init(&builder, (GVariantType *)"(sii)");

  GVariant *v;
  v = put_string(&(result->text));
  g_variant_builder_add_value(&builder, v);
  v = put_int32(&(result->command));
  g_variant_builder_add_value(&builder, v);
  v = put_int32(&(result->flags));
  g_variant_builder_add_value(&builder, v);

  return g_variant_builder_end(&builder);
}



void
DBusGUI_Marshall::get_MenuItems(GVariant *variant, GenericDBusApplet::MenuItems *result)
{
  GVariantIter iter;
  g_variant_iter_init(&iter, variant);

  GVariant *child;
  while ((child = g_variant_iter_next_value(&iter)))
    {
      GenericDBusApplet::MenuItem tmp;
      get_MenuItem(child, &tmp);
      result->push_back(tmp);

      g_variant_unref (child);
    }
}

GVariant *
DBusGUI_Marshall::put_MenuItems(const GenericDBusApplet::MenuItems *result)
{
  GVariantBuilder builder;
  g_variant_builder_init(&builder, (GVariantType *)"a(sii)");

  GenericDBusApplet::MenuItems::const_iterator it;

  for (it = result->begin(); it != result->end(); it++)
  {
    GVariant *v = put_MenuItem(&(*it));
    g_variant_builder_add_value(&builder, v);
  }

  return g_variant_builder_end(&builder);
}





class org_workrave_ControlInterface_Stub : public DBusBindingGio, public org_workrave_ControlInterface, DBusGUI_Marshall
{
private:
  typedef void (org_workrave_ControlInterface_Stub::*DBusMethodPointer)(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs);

  struct DBusMethod
  {
    const string name;
    DBusMethodPointer fn;
  };

  virtual void call(const std::string &method_name, void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs);

  virtual const char *get_interface_introspect()
  {
    return interface_introspect;
  }

public:
  org_workrave_ControlInterface_Stub(IDBus::Ptr dbus);
  ~org_workrave_ControlInterface_Stub();


private:
  void OpenMain(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs);
  void Preferences(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs);
  void SetOperationMode(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs);
  void NetworkConnect(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs);
  void NetworkLog(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs);
  void NetworkReconnect(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs);
  void NetworkDisconnect(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs);
  void ReadingMode(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs);
  void Statistics(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs);
  void Exercises(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs);
  void RestBreak(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs);
  void Quit(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs);
  void About(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs);

  static const DBusMethod method_table[];
  static const char *interface_introspect;
};


org_workrave_ControlInterface *org_workrave_ControlInterface::instance(const ::workrave::dbus::IDBus::Ptr dbus)
{
  org_workrave_ControlInterface_Stub *iface = NULL;
  DBusBinding *binding = dbus->find_binding("org.workrave.ControlInterface");

  if (binding != NULL)
    {
      iface = dynamic_cast<org_workrave_ControlInterface_Stub *>(binding);
    }

  return iface;
}

org_workrave_ControlInterface_Stub::org_workrave_ControlInterface_Stub(IDBus::Ptr dbus)
  : DBusBindingGio(dbus)
{
}

org_workrave_ControlInterface_Stub::~org_workrave_ControlInterface_Stub()
{
}

void
org_workrave_ControlInterface_Stub::call(const std::string &method_name, void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs)
{
  const DBusMethod *table = method_table;
  while (table->fn != NULL)
    {
      if (method_name == table->name)
        {
          DBusMethodPointer ptr = table->fn;
          if (ptr != NULL)
            {
              (this->*ptr)(object, invocation, sender, inargs);
            }
          return;
        }
      table++;
    }

  throw DBusRemoteException()
    << message_info("Unknown method")
    << error_code_info(DBUS_ERROR_UNKNOWN_METHOD)
    << method_info(method_name)
    << interface_info("org.workrave.ControlInterface");
}


void
org_workrave_ControlInterface_Stub::OpenMain(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs)
{
  (void) sender;

  try
    {
      Menus *dbus_object = (Menus *) object;


      gsize num_in_args = g_variant_n_children(inargs);
      if (num_in_args != 0)
        {
          throw DBusRemoteException()
            << message_info("Incorrecy number of in-paraeters")
            << error_code_info(DBUS_ERROR_INVALID_ARGS)
            << method_info("OpenMain")
            << interface_info("org.workrave.ControlInterface");
        }


      dbus_object->on_menu_open_main_window(

      );

      GVariant *out = NULL;

      g_dbus_method_invocation_return_value(invocation, out);
    }
  catch (const DBusRemoteException &e)
    {
      e << method_info("OpenMain")
        << interface_info("org.workrave.ControlInterface");
      throw;
    }

}

void
org_workrave_ControlInterface_Stub::Preferences(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs)
{
  (void) sender;

  try
    {
      Menus *dbus_object = (Menus *) object;


      gsize num_in_args = g_variant_n_children(inargs);
      if (num_in_args != 0)
        {
          throw DBusRemoteException()
            << message_info("Incorrecy number of in-paraeters")
            << error_code_info(DBUS_ERROR_INVALID_ARGS)
            << method_info("Preferences")
            << interface_info("org.workrave.ControlInterface");
        }


      dbus_object->on_menu_preferences(

      );

      GVariant *out = NULL;

      g_dbus_method_invocation_return_value(invocation, out);
    }
  catch (const DBusRemoteException &e)
    {
      e << method_info("Preferences")
        << interface_info("org.workrave.ControlInterface");
      throw;
    }

}

void
org_workrave_ControlInterface_Stub::SetOperationMode(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs)
{
  (void) sender;

  try
    {
      Menus *dbus_object = (Menus *) object;

      OperationMode p_mode
      ;

      gsize num_in_args = g_variant_n_children(inargs);
      if (num_in_args != 1)
        {
          throw DBusRemoteException()
            << message_info("Incorrecy number of in-paraeters")
            << error_code_info(DBUS_ERROR_INVALID_ARGS)
            << method_info("SetOperationMode")
            << interface_info("org.workrave.ControlInterface");
        }

      GVariant *v_mode = g_variant_get_child_value(inargs, 0 );
      get_operation_mode(v_mode, &p_mode);

      dbus_object->on_set_operation_mode(

       p_mode
      );

      GVariant *out = NULL;

      g_dbus_method_invocation_return_value(invocation, out);
    }
  catch (const DBusRemoteException &e)
    {
      e << method_info("SetOperationMode")
        << interface_info("org.workrave.ControlInterface");
      throw;
    }

}

void
org_workrave_ControlInterface_Stub::NetworkConnect(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs)
{
  (void) sender;

  try
    {
      Menus *dbus_object = (Menus *) object;


      gsize num_in_args = g_variant_n_children(inargs);
      if (num_in_args != 0)
        {
          throw DBusRemoteException()
            << message_info("Incorrecy number of in-paraeters")
            << error_code_info(DBUS_ERROR_INVALID_ARGS)
            << method_info("NetworkConnect")
            << interface_info("org.workrave.ControlInterface");
        }


      dbus_object->on_menu_network_join(

      );

      GVariant *out = NULL;

      g_dbus_method_invocation_return_value(invocation, out);
    }
  catch (const DBusRemoteException &e)
    {
      e << method_info("NetworkConnect")
        << interface_info("org.workrave.ControlInterface");
      throw;
    }

}

void
org_workrave_ControlInterface_Stub::NetworkLog(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs)
{
  (void) sender;

  try
    {
      Menus *dbus_object = (Menus *) object;

      bool p_show
      ;

      gsize num_in_args = g_variant_n_children(inargs);
      if (num_in_args != 1)
        {
          throw DBusRemoteException()
            << message_info("Incorrecy number of in-paraeters")
            << error_code_info(DBUS_ERROR_INVALID_ARGS)
            << method_info("NetworkLog")
            << interface_info("org.workrave.ControlInterface");
        }

      GVariant *v_show = g_variant_get_child_value(inargs, 0 );
      get_bool(v_show, &p_show);

      dbus_object->on_menu_network_log(

       p_show
      );

      GVariant *out = NULL;

      g_dbus_method_invocation_return_value(invocation, out);
    }
  catch (const DBusRemoteException &e)
    {
      e << method_info("NetworkLog")
        << interface_info("org.workrave.ControlInterface");
      throw;
    }

}

void
org_workrave_ControlInterface_Stub::NetworkReconnect(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs)
{
  (void) sender;

  try
    {
      Menus *dbus_object = (Menus *) object;


      gsize num_in_args = g_variant_n_children(inargs);
      if (num_in_args != 0)
        {
          throw DBusRemoteException()
            << message_info("Incorrecy number of in-paraeters")
            << error_code_info(DBUS_ERROR_INVALID_ARGS)
            << method_info("NetworkReconnect")
            << interface_info("org.workrave.ControlInterface");
        }


      dbus_object->on_menu_network_reconnect(

      );

      GVariant *out = NULL;

      g_dbus_method_invocation_return_value(invocation, out);
    }
  catch (const DBusRemoteException &e)
    {
      e << method_info("NetworkReconnect")
        << interface_info("org.workrave.ControlInterface");
      throw;
    }

}

void
org_workrave_ControlInterface_Stub::NetworkDisconnect(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs)
{
  (void) sender;

  try
    {
      Menus *dbus_object = (Menus *) object;


      gsize num_in_args = g_variant_n_children(inargs);
      if (num_in_args != 0)
        {
          throw DBusRemoteException()
            << message_info("Incorrecy number of in-paraeters")
            << error_code_info(DBUS_ERROR_INVALID_ARGS)
            << method_info("NetworkDisconnect")
            << interface_info("org.workrave.ControlInterface");
        }


      dbus_object->on_menu_network_leave(

      );

      GVariant *out = NULL;

      g_dbus_method_invocation_return_value(invocation, out);
    }
  catch (const DBusRemoteException &e)
    {
      e << method_info("NetworkDisconnect")
        << interface_info("org.workrave.ControlInterface");
      throw;
    }

}

void
org_workrave_ControlInterface_Stub::ReadingMode(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs)
{
  (void) sender;

  try
    {
      Menus *dbus_object = (Menus *) object;

      bool p_show
      ;

      gsize num_in_args = g_variant_n_children(inargs);
      if (num_in_args != 1)
        {
          throw DBusRemoteException()
            << message_info("Incorrecy number of in-paraeters")
            << error_code_info(DBUS_ERROR_INVALID_ARGS)
            << method_info("ReadingMode")
            << interface_info("org.workrave.ControlInterface");
        }

      GVariant *v_show = g_variant_get_child_value(inargs, 0 );
      get_bool(v_show, &p_show);

      dbus_object->on_menu_reading(

       p_show
      );

      GVariant *out = NULL;

      g_dbus_method_invocation_return_value(invocation, out);
    }
  catch (const DBusRemoteException &e)
    {
      e << method_info("ReadingMode")
        << interface_info("org.workrave.ControlInterface");
      throw;
    }

}

void
org_workrave_ControlInterface_Stub::Statistics(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs)
{
  (void) sender;

  try
    {
      Menus *dbus_object = (Menus *) object;


      gsize num_in_args = g_variant_n_children(inargs);
      if (num_in_args != 0)
        {
          throw DBusRemoteException()
            << message_info("Incorrecy number of in-paraeters")
            << error_code_info(DBUS_ERROR_INVALID_ARGS)
            << method_info("Statistics")
            << interface_info("org.workrave.ControlInterface");
        }


      dbus_object->on_menu_statistics(

      );

      GVariant *out = NULL;

      g_dbus_method_invocation_return_value(invocation, out);
    }
  catch (const DBusRemoteException &e)
    {
      e << method_info("Statistics")
        << interface_info("org.workrave.ControlInterface");
      throw;
    }

}

void
org_workrave_ControlInterface_Stub::Exercises(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs)
{
#if defined(HAVE_EXERCISES)
  (void) sender;

  try
    {
      Menus *dbus_object = (Menus *) object;


      gsize num_in_args = g_variant_n_children(inargs);
      if (num_in_args != 0)
        {
          throw DBusRemoteException()
            << message_info("Incorrecy number of in-paraeters")
            << error_code_info(DBUS_ERROR_INVALID_ARGS)
            << method_info("Exercises")
            << interface_info("org.workrave.ControlInterface");
        }


      dbus_object->on_menu_exercises(

      );

      GVariant *out = NULL;

      g_dbus_method_invocation_return_value(invocation, out);
    }
  catch (const DBusRemoteException &e)
    {
      e << method_info("Exercises")
        << interface_info("org.workrave.ControlInterface");
      throw;
    }

#else
 (void) object;

  g_dbus_method_invocation_return_dbus_error (invocation,
                                              "org.workrave.NotImplemented",
                                              "This method is unavailable in current configuration");
#endif
}

void
org_workrave_ControlInterface_Stub::RestBreak(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs)
{
  (void) sender;

  try
    {
      Menus *dbus_object = (Menus *) object;


      gsize num_in_args = g_variant_n_children(inargs);
      if (num_in_args != 0)
        {
          throw DBusRemoteException()
            << message_info("Incorrecy number of in-paraeters")
            << error_code_info(DBUS_ERROR_INVALID_ARGS)
            << method_info("RestBreak")
            << interface_info("org.workrave.ControlInterface");
        }


      dbus_object->on_menu_restbreak_now(

      );

      GVariant *out = NULL;

      g_dbus_method_invocation_return_value(invocation, out);
    }
  catch (const DBusRemoteException &e)
    {
      e << method_info("RestBreak")
        << interface_info("org.workrave.ControlInterface");
      throw;
    }

}

void
org_workrave_ControlInterface_Stub::Quit(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs)
{
  (void) sender;

  try
    {
      Menus *dbus_object = (Menus *) object;


      gsize num_in_args = g_variant_n_children(inargs);
      if (num_in_args != 0)
        {
          throw DBusRemoteException()
            << message_info("Incorrecy number of in-paraeters")
            << error_code_info(DBUS_ERROR_INVALID_ARGS)
            << method_info("Quit")
            << interface_info("org.workrave.ControlInterface");
        }


      dbus_object->on_menu_quit(

      );

      GVariant *out = NULL;

      g_dbus_method_invocation_return_value(invocation, out);
    }
  catch (const DBusRemoteException &e)
    {
      e << method_info("Quit")
        << interface_info("org.workrave.ControlInterface");
      throw;
    }

}

void
org_workrave_ControlInterface_Stub::About(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs)
{
  (void) sender;

  try
    {
      Menus *dbus_object = (Menus *) object;


      gsize num_in_args = g_variant_n_children(inargs);
      if (num_in_args != 0)
        {
          throw DBusRemoteException()
            << message_info("Incorrecy number of in-paraeters")
            << error_code_info(DBUS_ERROR_INVALID_ARGS)
            << method_info("About")
            << interface_info("org.workrave.ControlInterface");
        }


      dbus_object->on_menu_about(

      );

      GVariant *out = NULL;

      g_dbus_method_invocation_return_value(invocation, out);
    }
  catch (const DBusRemoteException &e)
    {
      e << method_info("About")
        << interface_info("org.workrave.ControlInterface");
      throw;
    }

}


const org_workrave_ControlInterface_Stub::DBusMethod org_workrave_ControlInterface_Stub::method_table[] = {
  { "OpenMain", &org_workrave_ControlInterface_Stub::OpenMain },
  { "Preferences", &org_workrave_ControlInterface_Stub::Preferences },
  { "SetOperationMode", &org_workrave_ControlInterface_Stub::SetOperationMode },
  { "NetworkConnect", &org_workrave_ControlInterface_Stub::NetworkConnect },
  { "NetworkLog", &org_workrave_ControlInterface_Stub::NetworkLog },
  { "NetworkReconnect", &org_workrave_ControlInterface_Stub::NetworkReconnect },
  { "NetworkDisconnect", &org_workrave_ControlInterface_Stub::NetworkDisconnect },
  { "ReadingMode", &org_workrave_ControlInterface_Stub::ReadingMode },
  { "Statistics", &org_workrave_ControlInterface_Stub::Statistics },
  { "Exercises", &org_workrave_ControlInterface_Stub::Exercises },
  { "RestBreak", &org_workrave_ControlInterface_Stub::RestBreak },
  { "Quit", &org_workrave_ControlInterface_Stub::Quit },
  { "About", &org_workrave_ControlInterface_Stub::About },
  { "", NULL }
};

const char *
org_workrave_ControlInterface_Stub::interface_introspect =
  "  <interface name=\"org.workrave.ControlInterface\">\n"
  "    <method name=\"OpenMain\">\n"
  "    </method>\n"
  "    <method name=\"Preferences\">\n"
  "    </method>\n"
  "    <method name=\"SetOperationMode\">\n"
  "      <arg type=\"s\" name=\"mode\" direction=\"in\" />\n"
  "    </method>\n"
  "    <method name=\"NetworkConnect\">\n"
  "    </method>\n"
  "    <method name=\"NetworkLog\">\n"
  "      <arg type=\"b\" name=\"show\" direction=\"in\" />\n"
  "    </method>\n"
  "    <method name=\"NetworkReconnect\">\n"
  "    </method>\n"
  "    <method name=\"NetworkDisconnect\">\n"
  "    </method>\n"
  "    <method name=\"ReadingMode\">\n"
  "      <arg type=\"b\" name=\"show\" direction=\"in\" />\n"
  "    </method>\n"
  "    <method name=\"Statistics\">\n"
  "    </method>\n"
  "    <method name=\"Exercises\">\n"
  "    </method>\n"
  "    <method name=\"RestBreak\">\n"
  "    </method>\n"
  "    <method name=\"Quit\">\n"
  "    </method>\n"
  "    <method name=\"About\">\n"
  "    </method>\n"
  "  </interface>\n";





class org_workrave_AppletInterface_Stub : public DBusBindingGio, public org_workrave_AppletInterface, DBusGUI_Marshall
{
private:
  typedef void (org_workrave_AppletInterface_Stub::*DBusMethodPointer)(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs);

  struct DBusMethod
  {
    const string name;
    DBusMethodPointer fn;
  };

  virtual void call(const std::string &method_name, void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs);

  virtual const char *get_interface_introspect()
  {
    return interface_introspect;
  }

public:
  org_workrave_AppletInterface_Stub(IDBus::Ptr dbus);
  ~org_workrave_AppletInterface_Stub();

  void TimersUpdated(const string &path
      , GenericDBusApplet::TimerData &micro
      , GenericDBusApplet::TimerData &rest
      , GenericDBusApplet::TimerData &daily
  );
  void MenuUpdated(const string &path
      , GenericDBusApplet::MenuItems &menuitems
  );
  void TrayIconUpdated(const string &path
      , bool enabled
  );

private:
  void Embed(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs);
  void Command(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs);
  void ButtonClicked(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs);
  void GetMenu(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs);
  void GetTrayIconEnabled(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs);

  static const DBusMethod method_table[];
  static const char *interface_introspect;
};


org_workrave_AppletInterface *org_workrave_AppletInterface::instance(const ::workrave::dbus::IDBus::Ptr dbus)
{
  org_workrave_AppletInterface_Stub *iface = NULL;
  DBusBinding *binding = dbus->find_binding("org.workrave.AppletInterface");

  if (binding != NULL)
    {
      iface = dynamic_cast<org_workrave_AppletInterface_Stub *>(binding);
    }

  return iface;
}

org_workrave_AppletInterface_Stub::org_workrave_AppletInterface_Stub(IDBus::Ptr dbus)
  : DBusBindingGio(dbus)
{
}

org_workrave_AppletInterface_Stub::~org_workrave_AppletInterface_Stub()
{
}

void
org_workrave_AppletInterface_Stub::call(const std::string &method_name, void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs)
{
  const DBusMethod *table = method_table;
  while (table->fn != NULL)
    {
      if (method_name == table->name)
        {
          DBusMethodPointer ptr = table->fn;
          if (ptr != NULL)
            {
              (this->*ptr)(object, invocation, sender, inargs);
            }
          return;
        }
      table++;
    }

  throw DBusRemoteException()
    << message_info("Unknown method")
    << error_code_info(DBUS_ERROR_UNKNOWN_METHOD)
    << method_info(method_name)
    << interface_info("org.workrave.AppletInterface");
}


void
org_workrave_AppletInterface_Stub::Embed(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs)
{
  (void) sender;

  try
    {
      GenericDBusApplet *dbus_object = (GenericDBusApplet *) object;

      bool p_enabled
      ;
      std::string p_sender
      ;

      gsize num_in_args = g_variant_n_children(inargs);
      if (num_in_args != 2)
        {
          throw DBusRemoteException()
            << message_info("Incorrecy number of in-paraeters")
            << error_code_info(DBUS_ERROR_INVALID_ARGS)
            << method_info("Embed")
            << interface_info("org.workrave.AppletInterface");
        }

      GVariant *v_enabled = g_variant_get_child_value(inargs, 0 );
      get_bool(v_enabled, &p_enabled);
      GVariant *v_sender = g_variant_get_child_value(inargs, 1 );
      get_string(v_sender, &p_sender);

      dbus_object->applet_embed(

       p_enabled
      , p_sender
      );

      GVariant *out = NULL;

      g_dbus_method_invocation_return_value(invocation, out);
    }
  catch (const DBusRemoteException &e)
    {
      e << method_info("Embed")
        << interface_info("org.workrave.AppletInterface");
      throw;
    }

}

void
org_workrave_AppletInterface_Stub::Command(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs)
{
  (void) sender;

  try
    {
      GenericDBusApplet *dbus_object = (GenericDBusApplet *) object;

      int32_t p_command
      ;

      gsize num_in_args = g_variant_n_children(inargs);
      if (num_in_args != 1)
        {
          throw DBusRemoteException()
            << message_info("Incorrecy number of in-paraeters")
            << error_code_info(DBUS_ERROR_INVALID_ARGS)
            << method_info("Command")
            << interface_info("org.workrave.AppletInterface");
        }

      GVariant *v_command = g_variant_get_child_value(inargs, 0 );
      get_int32(v_command, &p_command);

      dbus_object->applet_command(

       p_command
      );

      GVariant *out = NULL;

      g_dbus_method_invocation_return_value(invocation, out);
    }
  catch (const DBusRemoteException &e)
    {
      e << method_info("Command")
        << interface_info("org.workrave.AppletInterface");
      throw;
    }

}

void
org_workrave_AppletInterface_Stub::ButtonClicked(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs)
{
  (void) sender;

  try
    {
      GenericDBusApplet *dbus_object = (GenericDBusApplet *) object;

      uint32_t p_button
      ;

      gsize num_in_args = g_variant_n_children(inargs);
      if (num_in_args != 1)
        {
          throw DBusRemoteException()
            << message_info("Incorrecy number of in-paraeters")
            << error_code_info(DBUS_ERROR_INVALID_ARGS)
            << method_info("ButtonClicked")
            << interface_info("org.workrave.AppletInterface");
        }

      GVariant *v_button = g_variant_get_child_value(inargs, 0 );
      get_uint32(v_button, &p_button);

      dbus_object->button_clicked(

       p_button
      );

      GVariant *out = NULL;

      g_dbus_method_invocation_return_value(invocation, out);
    }
  catch (const DBusRemoteException &e)
    {
      e << method_info("ButtonClicked")
        << interface_info("org.workrave.AppletInterface");
      throw;
    }

}

void
org_workrave_AppletInterface_Stub::GetMenu(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs)
{
  (void) sender;

  try
    {
      GenericDBusApplet *dbus_object = (GenericDBusApplet *) object;

      GenericDBusApplet::MenuItems p_menuitems
      ;

      gsize num_in_args = g_variant_n_children(inargs);
      if (num_in_args != 0)
        {
          throw DBusRemoteException()
            << message_info("Incorrecy number of in-paraeters")
            << error_code_info(DBUS_ERROR_INVALID_ARGS)
            << method_info("GetMenu")
            << interface_info("org.workrave.AppletInterface");
        }


      dbus_object->get_menu(

       p_menuitems
      );

      GVariantBuilder builder;
      g_variant_builder_init(&builder, (GVariantType*)"(a(sii))");

      GVariant *v_menuitems = put_MenuItems(&p_menuitems);
      g_variant_builder_add_value(&builder, v_menuitems);

      GVariant *out = g_variant_builder_end(&builder);

      g_dbus_method_invocation_return_value(invocation, out);
    }
  catch (const DBusRemoteException &e)
    {
      e << method_info("GetMenu")
        << interface_info("org.workrave.AppletInterface");
      throw;
    }

}

void
org_workrave_AppletInterface_Stub::GetTrayIconEnabled(void *object, GDBusMethodInvocation *invocation, const std::string &sender, GVariant *inargs)
{
  (void) sender;

  try
    {
      GenericDBusApplet *dbus_object = (GenericDBusApplet *) object;

      bool p_enabled
      ;

      gsize num_in_args = g_variant_n_children(inargs);
      if (num_in_args != 0)
        {
          throw DBusRemoteException()
            << message_info("Incorrecy number of in-paraeters")
            << error_code_info(DBUS_ERROR_INVALID_ARGS)
            << method_info("GetTrayIconEnabled")
            << interface_info("org.workrave.AppletInterface");
        }


      dbus_object->get_tray_icon_enabled(

       p_enabled
      );

      GVariantBuilder builder;
      g_variant_builder_init(&builder, (GVariantType*)"(b)");

      GVariant *v_enabled = put_bool(&p_enabled);
      g_variant_builder_add_value(&builder, v_enabled);

      GVariant *out = g_variant_builder_end(&builder);

      g_dbus_method_invocation_return_value(invocation, out);
    }
  catch (const DBusRemoteException &e)
    {
      e << method_info("GetTrayIconEnabled")
        << interface_info("org.workrave.AppletInterface");
      throw;
    }

}

void org_workrave_AppletInterface_Stub::TimersUpdated(const string &path
      , GenericDBusApplet::TimerData &micro
      , GenericDBusApplet::TimerData &rest
      , GenericDBusApplet::TimerData &daily
)
{
  IDBusPrivateGio::Ptr p = std::dynamic_pointer_cast<IDBusPrivateGio>(dbus);

  GDBusConnection *connection = p->get_connection();
  if (connection == NULL)
    {
      return;
    }

  GVariantBuilder builder;
  g_variant_builder_init(&builder, (GVariantType*)"((siuuuuuu)(siuuuuuu)(siuuuuuu))");

  GVariant *v_micro = put_TimerData(&micro);
  g_variant_builder_add_value(&builder, v_micro);
  GVariant *v_rest = put_TimerData(&rest);
  g_variant_builder_add_value(&builder, v_rest);
  GVariant *v_daily = put_TimerData(&daily);
  g_variant_builder_add_value(&builder, v_daily);

  GVariant *out = g_variant_builder_end(&builder);

  GError *error = NULL;
  g_dbus_connection_emit_signal(connection,
                                NULL,
                                path.c_str(),
                                "org.workrave.AppletInterface",
                                "TimersUpdated",
                                out,
                                &error);

  if (error != NULL)
    {
      g_error_free(error);
    }
}
void org_workrave_AppletInterface_Stub::MenuUpdated(const string &path
      , GenericDBusApplet::MenuItems &menuitems
)
{
  IDBusPrivateGio::Ptr p = std::dynamic_pointer_cast<IDBusPrivateGio>(dbus);

  GDBusConnection *connection = p->get_connection();
  if (connection == NULL)
    {
      return;
    }

  GVariantBuilder builder;
  g_variant_builder_init(&builder, (GVariantType*)"(a(sii))");

  GVariant *v_menuitems = put_MenuItems(&menuitems);
  g_variant_builder_add_value(&builder, v_menuitems);

  GVariant *out = g_variant_builder_end(&builder);

  GError *error = NULL;
  g_dbus_connection_emit_signal(connection,
                                NULL,
                                path.c_str(),
                                "org.workrave.AppletInterface",
                                "MenuUpdated",
                                out,
                                &error);

  if (error != NULL)
    {
      g_error_free(error);
    }
}
void org_workrave_AppletInterface_Stub::TrayIconUpdated(const string &path
      , bool enabled
)
{
  IDBusPrivateGio::Ptr p = std::dynamic_pointer_cast<IDBusPrivateGio>(dbus);

  GDBusConnection *connection = p->get_connection();
  if (connection == NULL)
    {
      return;
    }

  GVariantBuilder builder;
  g_variant_builder_init(&builder, (GVariantType*)"(b)");

  GVariant *v_enabled = put_bool(&enabled);
  g_variant_builder_add_value(&builder, v_enabled);

  GVariant *out = g_variant_builder_end(&builder);

  GError *error = NULL;
  g_dbus_connection_emit_signal(connection,
                                NULL,
                                path.c_str(),
                                "org.workrave.AppletInterface",
                                "TrayIconUpdated",
                                out,
                                &error);

  if (error != NULL)
    {
      g_error_free(error);
    }
}

const org_workrave_AppletInterface_Stub::DBusMethod org_workrave_AppletInterface_Stub::method_table[] = {
  { "Embed", &org_workrave_AppletInterface_Stub::Embed },
  { "Command", &org_workrave_AppletInterface_Stub::Command },
  { "ButtonClicked", &org_workrave_AppletInterface_Stub::ButtonClicked },
  { "GetMenu", &org_workrave_AppletInterface_Stub::GetMenu },
  { "GetTrayIconEnabled", &org_workrave_AppletInterface_Stub::GetTrayIconEnabled },
  { "", NULL }
};

const char *
org_workrave_AppletInterface_Stub::interface_introspect =
  "  <interface name=\"org.workrave.AppletInterface\">\n"
  "    <method name=\"Embed\">\n"
  "      <arg type=\"b\" name=\"enabled\" direction=\"in\" />\n"
  "      <arg type=\"s\" name=\"sender\" direction=\"in\" />\n"
  "    </method>\n"
  "    <method name=\"Command\">\n"
  "      <arg type=\"i\" name=\"command\" direction=\"in\" />\n"
  "    </method>\n"
  "    <method name=\"ButtonClicked\">\n"
  "      <arg type=\"u\" name=\"button\" direction=\"in\" />\n"
  "    </method>\n"
  "    <method name=\"GetMenu\">\n"
  "      <arg type=\"a(sii)\" name=\"menuitems\" direction=\"out\" />\n"
  "    </method>\n"
  "    <method name=\"GetTrayIconEnabled\">\n"
  "      <arg type=\"b\" name=\"enabled\" direction=\"out\" />\n"
  "    </method>\n"
  "    <signal name=\"TimersUpdated\">\n"
  "      <arg type=\"(siuuuuuu)\" name=\"micro\" />\n"
  "      <arg type=\"(siuuuuuu)\" name=\"rest\" />\n"
  "      <arg type=\"(siuuuuuu)\" name=\"daily\" />\n"
  "    </signal>\n"
  "    <signal name=\"MenuUpdated\">\n"
  "      <arg type=\"a(sii)\" name=\"menuitems\" />\n"
  "    </signal>\n"
  "    <signal name=\"TrayIconUpdated\">\n"
  "      <arg type=\"b\" name=\"enabled\" />\n"
  "    </signal>\n"
  "  </interface>\n";




void init_DBusGUI(IDBus::Ptr dbus)
{
  dbus->register_binding("org.workrave.ControlInterface", new org_workrave_ControlInterface_Stub(dbus));
  dbus->register_binding("org.workrave.AppletInterface", new org_workrave_AppletInterface_Stub(dbus));
}