/* GIO - GLib Input, Output and Streaming Library
 * 
 * Copyright (C) 2010 Codethink Limited
 * Copyright (C) 2010 Hans Breuer
 *
 * 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 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., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * Authors: 
 *	Ryan Lortie <desrt@desrt.ca>
 *	Hans Breuer <hans@breuer.org>
 */

#include "gapplicationimpl.h"

#include "gactiongroup.h"
#include "gapplication.h"
#include "gfile.h"
#include "gdbusconnection.h"
#include "gdbusintrospection.h"
#include "gdbuserror.h"

#include <string.h>
#include <stdio.h>

#include "gapplicationcommandline.h"

/* GApplication implementation {{{1 */
struct _GApplicationImpl
{
  gchar           *object_path;
  guint            object_id;
  guint            action_id;
  gpointer         app;

  GHashTable      *actions;
  guint            signal_id;
};

void
g_application_impl_destroy (GApplicationImpl *impl)
{
  g_warning ("GApplicationImpl::destry()");

  g_slice_free (GApplicationImpl, impl);
}

GApplicationImpl *
g_application_impl_register (GApplication       *application,
                             const gchar        *appid,
                             GApplicationFlags   flags,
                             GHashTable        **remote_actions,
                             GCancellable       *cancellable,
                             GError            **error)
{
  GApplicationImpl *impl;
  GVariant *reply;
  guint32 rval;

  g_warning ("GApplicationImpl::register()");

  impl = g_slice_new (GApplicationImpl);

  impl->app = application;

  /* Only try to be the primary instance if
   * G_APPLICATION_IS_LAUNCHER was not specified.
   */
  if (~flags & G_APPLICATION_IS_LAUNCHER)
    {
      return NULL;
    }

  /* We are non-primary.  Try to get the primary's list of actions.
   * This also serves as a mechanism to ensure that the primary exists
   * (ie: DBus service files installed correctly, etc).
   */

  /* Create and populate the hashtable */
  {
    GVariant *descriptions;
    GVariantIter iter;
    GVariant *param_type;
    gboolean enabled;
    GVariant *state;
    gchar *name;

    *remote_actions = g_hash_table_new (g_str_hash, g_str_equal);
    descriptions = g_variant_get_child_value (reply, 0);
    g_variant_iter_init (&iter, descriptions);

    while (g_variant_iter_next (&iter, "(s@avb@av)", &name,
                                &param_type, &enabled, &state))
      {
        RemoteActionInfo *action;

        action = g_slice_new (RemoteActionInfo);
        action->parameter_type = g_variant_type_copy (
                                   g_variant_type_element (
                                     g_variant_get_type (param_type)));
        action->enabled = enabled;
        action->state = state;

        g_hash_table_insert (*remote_actions, name, action);
        g_variant_unref (param_type);
      }

    g_variant_unref (descriptions);
  }


  return impl;
}

void
g_application_impl_activate (GApplicationImpl *impl,
                             GVariant         *platform_data)
{
  g_warning ("GApplicationImpl::activate()");
}

void
g_application_impl_open (GApplicationImpl  *impl,
                         GFile            **files,
                         gint               n_files,
                         const gchar       *hint,
                         GVariant          *platform_data)
{
  GVariantBuilder builder;
  gint i;

  g_warning ("GApplicationImpl::open()");

  g_variant_builder_init (&builder, G_VARIANT_TYPE ("(assa{sv})"));
  g_variant_builder_open (&builder, G_VARIANT_TYPE_STRING_ARRAY);
  for (i = 0; i < n_files; i++)
    {
      gchar *uri = g_file_get_uri (files[i]);
      g_variant_builder_add (&builder, "s", uri);
      g_free (uri);
    }
  g_variant_builder_close (&builder);
  g_variant_builder_add (&builder, "s", hint);
  g_variant_builder_add_value (&builder, platform_data);

}

int
g_application_impl_command_line (GApplicationImpl  *impl,
                                 gchar            **arguments,
                                 GVariant          *platform_data)
{
  GMainContext *context;
  guint object_id;

  context = g_main_context_new ();
  g_main_context_push_thread_default (context);

  g_warning ("GApplicationImpl::command_line()");

  g_main_context_pop_thread_default (context);
  g_main_context_unref (context);

  return -1;
}

void
g_application_impl_change_action_state (GApplicationImpl *impl,
                                        const gchar      *action_name,
                                        GVariant         *value,
                                        GVariant         *platform_data)
{
  g_warning ("GApplicationImpl::change_action_state()");
}

void
g_application_impl_activate_action (GApplicationImpl *impl,
                                    const gchar      *action_name,
                                    GVariant         *parameter,
                                    GVariant         *platform_data)
{
  GVariant *param;

  if (parameter)
    parameter = g_variant_new_variant (parameter);

  param = g_variant_new_array (G_VARIANT_TYPE_VARIANT,
                               &parameter, parameter != NULL);

  g_warning ("GApplicationImpl::activate_action()");
}

void
g_application_impl_flush (GApplicationImpl *impl)
{
  g_warning ("GApplicationImpl::flush()");
}
