/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
 * unity-webapps-action-invoker.c
 * Copyright (C) Canonical LTD 2011
 * 
 * Author: Robert Carr <racarr@canonical.com>
 * 
unity-webapps 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 3 of the License, or
 * (at your option) any later version.
 * 
 * unity-webapps 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 program.  If not, see <http://www.gnu.org/licenses/>.";
 */
#include <stdlib.h>

#include "unity-webapps-service.h"
#include "unity-webapps-context.h"

#include <glib/gstdio.h>

#include <time.h>

#include <libdbusmenu-glib/menuitem.h>
#include <libdbusmenu-glib/client.h>

static UnityWebappsService *service = NULL;

static gchar *name = NULL;
static gchar *domain = NULL;
const gchar *action = NULL;

static GOptionEntry option_entries[] =
	{
		{ "name", 'n',0,G_OPTION_ARG_STRING, &name, "Application name", NULL },
		{ "domain", 'd',0, G_OPTION_ARG_STRING, &domain, "Application domain", NULL},
		{ "action", 'a', 0, G_OPTION_ARG_STRING, &action, "Action path", NULL}
	};

static gchar **
split_action_path (const gchar *action_path)
{
  gchar **components;
  
  if (action_path[0] != '/')
    {
      return NULL;
    }
  
  components = g_strsplit (action_path+1, "/", -1);
  
  if (g_strv_length (components) > 3)
    {
      g_strfreev (components);
      return NULL;
    }
  
  return components;
}

static DbusmenuMenuitem *
menuitem_find_child_by_label (DbusmenuMenuitem *item,
			      const gchar *label)
{
  const GList *children;
  const GList *walk;
  
  children = dbusmenu_menuitem_get_children (item);
  
  for (walk = children;
       walk != NULL;
       walk = walk->next)
    {
      DbusmenuMenuitem *child;
      
      const gchar *child_label;
      
      child = (DbusmenuMenuitem *)walk->data;
      child_label = dbusmenu_menuitem_property_get (child, "label");
      
      if (g_strcmp0 (child_label, label) == 0)
	{
	  return child;
	}
    }
  
  return NULL;
}


static void
invoke_action_by_path (DbusmenuMenuitem *root, const gchar *action_path)
{
  gchar **components;
  DbusmenuMenuitem *item;
  gint i, length;
  
  components = split_action_path (action_path);
  
  length = g_strv_length (components);
  
  if (length < 0)
	{
	  return;
	}
  
  item = root;
  
  for (i = 0; i < length; i++)
	{
	  DbusmenuMenuitem *child;
	  gchar *component;
	  
	  component = components[i];
	  
	  child = menuitem_find_child_by_label (item, component);
	  
	  if (child == NULL)
		{
		  g_error ("Action not found");
		  
		  exit (1);
		}
	  
	  item = child;
	}
  
  g_message("Invoking item: %s", components[i-1]);
  dbusmenu_menuitem_handle_event (item, "clicked", NULL, time(NULL));
  
  g_strfreev (components);
}

static void
on_root_changed (DbusmenuClient *client,
				 DbusmenuMenuitem *newitem,
				 gpointer user_data)
{
  invoke_action_by_path (newitem, action);
}

static void
context_ready (UnityWebappsContext *context, gpointer user_data)
{
  DbusmenuClient *client;
  const gchar *context_name;
  
  context_name = unity_webapps_context_get_context_name (context);
  
  client = dbusmenu_client_new (context_name, "/com/canonical/Unity/Webapps/Context/ApplicationActions");
  
  g_signal_connect (client, "root-changed",
					G_CALLBACK (on_root_changed),
					NULL);
  
}


gint
main (gint argc, gchar **argv)
{
  GOptionContext *context;
  GError *error;

    g_type_init ();
  
  service = unity_webapps_service_new ();
  
  error = NULL;
  
  context = g_option_context_new ("- Activate Unity WebApps");
  
  // TODO: GETTEXT
  g_option_context_add_main_entries (context, option_entries, NULL);

  if (!g_option_context_parse (context, &argc, &argv, &error))
	{
	  g_printf("Failed to parse arguments: %s\n", error->message);
	  exit(1);
	}
  
  unity_webapps_context_new (service, name, domain, "", NULL, context_ready, NULL);
  
  g_main_loop_run (g_main_loop_new (NULL, FALSE));
  
  return 0;  
}
