/*
 * unity-webapps-launcher-context.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 <glib/gi18n.h>

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

#include "unity-webapps-dbus-defs.h"

#include "unity-webapps-debug.h"

#include "unity-webapps-interest-manager.h"
#include "unity-webapps-action-manager.h"
#include "unity-webapps-interest-tracker.h"
#include "unity-webapps-app-db.h"

#define UNITY_WEBAPPS_LAUNCHER_MAX_ACTIONS 6


static void
emit_action_invoked_signal (UnityWebappsLauncherContext *launcher_context,
			    const gchar *label, gint interest_id)
{
  GError *error;

  UNITY_WEBAPPS_NOTE (LAUNCHER, "Emitting ActionInvoked signal (%s)", label);

  error = NULL;
  
  g_dbus_connection_emit_signal (launcher_context->connection,
				 NULL,
				 UNITY_WEBAPPS_LAUNCHER_PATH,
				 UNITY_WEBAPPS_LAUNCHER_IFACE,
				 "ActionInvoked",
				 g_variant_new("(si)", label, interest_id, NULL),
				 &error);
  
  if (error != NULL)
    {
      g_warning ("Error emitting ActionInvoked signal (from menuitem) in launcher context: %s", error->message);
      g_error_free (error);
    }

}

static void
unity_webapps_launcher_context_on_action_invoked (UnityWebappsActionManager *action_manager,
						    const gchar *action_path,
						    gpointer user_data)
{
  UnityWebappsLauncherContext *launcher_context;
  
  UNITY_WEBAPPS_NOTE (LAUNCHER, "Got item-activated signal for menuitem");

  launcher_context = (UnityWebappsLauncherContext *)user_data;
  
  if (g_strcmp0 (action_path, _("Open a New Window")) == 0)
    {
      UNITY_WEBAPPS_NOTE (LAUNCHER, "Opening a new application window from quicklist");
      
      unity_webapps_application_info_open_new_instance (launcher_context->application_info);
      
      return;
    }
  
  gint interest_id = unity_webapps_action_manager_get_most_recent_interest_with_action (action_manager,
                                                                                        action_path);
  UNITY_WEBAPPS_NOTE (LAUNCHER, "emmiting action and raising %d", interest_id);
  if (interest_id != -1) {
    unity_webapps_context_daemon_raise_interest (interest_id);
    emit_action_invoked_signal (launcher_context, action_path, interest_id);
  } else {
    unity_webapps_context_daemon_raise_most_recent ();
  }
}

static void
real_set_count (UnityWebappsLauncherContext *context,
		gint count)
{
  unity_launcher_entry_set_count (context->launcher_entry, count);
  unity_launcher_entry_set_count_visible (context->launcher_entry, TRUE);
}

static void
real_clear_count (UnityWebappsLauncherContext *context)
{
  unity_launcher_entry_set_count_visible (context->launcher_entry, FALSE);
}
static void
real_set_progress (UnityWebappsLauncherContext *context,
		   gdouble progress)
{
  unity_launcher_entry_set_progress (context->launcher_entry, progress);
  unity_launcher_entry_set_progress_visible (context->launcher_entry, TRUE);
}

static void
real_clear_progress (UnityWebappsLauncherContext *context)
{
  unity_launcher_entry_set_progress_visible (context->launcher_entry, FALSE);
}

static void
real_set_urgent (UnityWebappsLauncherContext *context)
{
  unity_launcher_entry_set_urgent (context->launcher_entry, TRUE);
}

static gboolean
on_handle_set_count (UnityWebappsGenLauncher *launcher,
		     GDBusMethodInvocation *invocation,
		     gint count,
		     gpointer user_data)
{
  UnityWebappsLauncherContext *context;
  
  UNITY_WEBAPPS_NOTE (LAUNCHER, "Handling SetCount call, count: %d", count);
  
  context = (UnityWebappsLauncherContext *)user_data;

  real_set_count (context, count);
  
  g_dbus_method_invocation_return_value (invocation, NULL);
  
  return TRUE;
}

static gboolean
on_handle_clear_count (UnityWebappsGenLauncher *launcher,
		       GDBusMethodInvocation *invocation,
		       gpointer user_data)
{
  UnityWebappsLauncherContext *context;
  
  UNITY_WEBAPPS_NOTE (LAUNCHER, "Handling ClearCount call");
  
  context = (UnityWebappsLauncherContext *)user_data;

  real_clear_count (context);
  
  g_dbus_method_invocation_return_value (invocation, NULL);
  
  return TRUE;
}

static gboolean
on_handle_set_progress (UnityWebappsGenLauncher *launcher,
			GDBusMethodInvocation *invocation,
			gdouble progress,
			gpointer user_data)
{
  UnityWebappsLauncherContext *context;
  
  UNITY_WEBAPPS_NOTE (LAUNCHER, "Handling SetProgress call, progress: %f", progress);
  
  context = (UnityWebappsLauncherContext *)user_data;

  real_set_progress (context, progress);
  
  g_dbus_method_invocation_return_value (invocation, NULL);
  
  return TRUE;
}

static gboolean
on_handle_clear_progress (UnityWebappsGenLauncher *launcher,
			  GDBusMethodInvocation *invocation,
			  gpointer user_data)
{
  UnityWebappsLauncherContext *context;
  
  UNITY_WEBAPPS_NOTE (LAUNCHER, "Handling ClearProgress call");
  
  context = (UnityWebappsLauncherContext *)user_data;

  real_clear_progress (context);
  
  g_dbus_method_invocation_return_value (invocation, NULL);
  
  return TRUE;
}

static gboolean
on_handle_add_action (UnityWebappsGenLauncher *launcher,
		      GDBusMethodInvocation *invocation,
		      const gchar *label,
		      gint interest_id,
		      gpointer user_data)
{
  UnityWebappsLauncherContext *context;
  
  UNITY_WEBAPPS_NOTE (LAUNCHER, "Handling AddAction call, action: %s", label);
  
  context = (UnityWebappsLauncherContext *)user_data;
  
  unity_webapps_action_manager_add_action (context->action_manager,
					   label,
					   interest_id);
  
  g_dbus_method_invocation_return_value (invocation, NULL);
  
  return TRUE;
}

static gboolean
on_handle_add_static_action (UnityWebappsGenLauncher *launcher,
			     GDBusMethodInvocation *invocation,
			     const gchar *label,
			     const gchar *page,
			     gpointer user_data)
{
  UnityWebappsLauncherContext *context;
  UNITY_WEBAPPS_NOTE (LAUNCHER, "Handling AddStaticAction call, action: %s", label);

  context = (UnityWebappsLauncherContext *)user_data;

  unity_webapps_app_db_add_action (unity_webapps_application_info_get_name (context->application_info),
				   unity_webapps_application_info_get_domain (context->application_info),
				   label, page);

  // TODO: UGH
  unity_webapps_application_info_ensure_desktop_file (context->application_info, NULL);

  g_dbus_method_invocation_return_value (invocation, NULL);

  return TRUE;
}

static gboolean
on_handle_remove_static_actions (UnityWebappsGenLauncher *launcher,
				 GDBusMethodInvocation *invocation,
				 gpointer user_data)
{
  UnityWebappsLauncherContext *context;

  UNITY_WEBAPPS_NOTE (LAUNCHER, "Handling RemoveStaticActions call");

  context = (UnityWebappsLauncherContext *)user_data;

  unity_webapps_app_db_clear_actions (unity_webapps_application_info_get_name (context->application_info),
				      unity_webapps_application_info_get_domain (context->application_info));

  unity_webapps_application_info_ensure_desktop_file (context->application_info, NULL);

  g_dbus_method_invocation_return_value (invocation, NULL);

  return TRUE;
}

static gboolean
on_handle_remove_action (UnityWebappsGenLauncher *launcher,
			 GDBusMethodInvocation *invocation,
			 const gchar *label,
			 gint interest_id,
			 gpointer user_data)
{
  UnityWebappsLauncherContext *context;
  
  UNITY_WEBAPPS_NOTE (LAUNCHER, "Handling RemoveAction call, action: %s", label);
  
  context = (UnityWebappsLauncherContext *)user_data;
  
  unity_webapps_action_manager_remove_action (context->action_manager,
					      label,
					      interest_id);
  
  g_dbus_method_invocation_return_value (invocation, NULL);
  
  return TRUE;
}

static gboolean
on_handle_remove_actions (UnityWebappsGenLauncher *launcher,
			  GDBusMethodInvocation *invocation,
			  gint interest_id,
			  gpointer user_data)
{
  UnityWebappsLauncherContext *context;
  
  UNITY_WEBAPPS_NOTE (LAUNCHER, "Handling RemoveActions call");
  
  context = (UnityWebappsLauncherContext *)user_data;
  
  unity_webapps_action_manager_remove_all_actions (context->action_manager,
						   interest_id);
  
  g_dbus_method_invocation_return_value (invocation, NULL);
  
  return TRUE;
}




static gboolean
on_handle_set_urgent (UnityWebappsGenLauncher *launcher,
		      GDBusMethodInvocation *invocation,
		      gpointer user_data)
{
  UnityWebappsLauncherContext *context;
  
  UNITY_WEBAPPS_NOTE (LAUNCHER, "Handling SetUrgent call");
  
  context = (UnityWebappsLauncherContext *)user_data;
  
  real_set_urgent (context);
  
  g_dbus_method_invocation_return_value (invocation, NULL);
  
  return TRUE;
}
  




static void
export_object (GDBusConnection *connection,
	       UnityWebappsLauncherContext *launcher_context)
{
  GError *error;
  
  launcher_context->launcher_service_interface = unity_webapps_gen_launcher_skeleton_new ();
  
  g_signal_connect (launcher_context->launcher_service_interface,
		    "handle-set-count",
		    G_CALLBACK (on_handle_set_count),
		    launcher_context);

  g_signal_connect (launcher_context->launcher_service_interface,
		    "handle-clear-count",
		    G_CALLBACK (on_handle_clear_count),
		    launcher_context);

  g_signal_connect (launcher_context->launcher_service_interface,
		    "handle-set-progress",
		    G_CALLBACK (on_handle_set_progress),
		    launcher_context);

  g_signal_connect (launcher_context->launcher_service_interface,
		    "handle-clear-progress",
		    G_CALLBACK (on_handle_clear_progress),
		    launcher_context);

  g_signal_connect (launcher_context->launcher_service_interface,
		    "handle-add-static-action",
		    G_CALLBACK (on_handle_add_static_action),
		    launcher_context);
  g_signal_connect (launcher_context->launcher_service_interface,
		    "handle-remove-static-actions",
		    G_CALLBACK (on_handle_remove_static_actions),
		    launcher_context);

  g_signal_connect (launcher_context->launcher_service_interface,
		    "handle-add-action",
		    G_CALLBACK (on_handle_add_action),
		    launcher_context);
  g_signal_connect (launcher_context->launcher_service_interface,
		    "handle-remove-action",
		    G_CALLBACK (on_handle_remove_action),
		    launcher_context);
  g_signal_connect (launcher_context->launcher_service_interface,
		    "handle-remove-actions",
		    G_CALLBACK (on_handle_remove_actions),
		    launcher_context);
  g_signal_connect (launcher_context->launcher_service_interface,
		    "handle-set-urgent",
		    G_CALLBACK (on_handle_set_urgent),
		    launcher_context);
  
  error = NULL;
  
  g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (launcher_context->launcher_service_interface),
				    connection,
				    UNITY_WEBAPPS_LAUNCHER_PATH,
				    &error);
  
  if (error != NULL)
    {
      g_error ("Error exporting Unity Webapps Launcher object: %s", error->message);
      
      g_error_free (error);
      
      return;
    }
  
  UNITY_WEBAPPS_NOTE (LAUNCHER, "Exported Launcher object");
}

UnityWebappsLauncherContext *
unity_webapps_launcher_context_new (GDBusConnection *connection, const gchar *desktop_id, UnityWebappsInterestTracker *interest_tracker,
				    UnityWebappsApplicationInfo *application_info)
{
  UnityWebappsLauncherContext *launcher_context;

  UNITY_WEBAPPS_NOTE (LAUNCHER, "Creating new UnityWebappsLauncherContext object");
  
  launcher_context = g_malloc0 (sizeof (UnityWebappsLauncherContext));
  
  launcher_context->application_info = application_info;
  
  launcher_context->connection = g_object_ref (G_OBJECT (connection));
  
  export_object (connection, launcher_context);
  
  launcher_context->launcher_entry = unity_launcher_entry_get_for_desktop_id (desktop_id);
  launcher_context->action_manager = unity_webapps_action_manager_new_flat (interest_tracker, NULL);
  
  unity_webapps_action_manager_set_track_activity (launcher_context->action_manager, FALSE);

  unity_webapps_action_manager_add_action (launcher_context->action_manager, _("Open a New Window"), -1);
  
  unity_launcher_entry_set_quicklist (launcher_context->launcher_entry,
				      unity_webapps_action_manager_get_root (launcher_context->action_manager));
  
  g_signal_connect (launcher_context->action_manager,
		    "action-invoked",
		    G_CALLBACK (unity_webapps_launcher_context_on_action_invoked),
		    launcher_context);
  
  launcher_context->num_actions = 0;
  
  
  return launcher_context;
}

void
unity_webapps_launcher_context_free (UnityWebappsLauncherContext *launcher_context)
{
  UNITY_WEBAPPS_NOTE (LAUNCHER, "Finalizing UnityWebappsLauncherContext object");
  g_object_unref (G_OBJECT (launcher_context->launcher_service_interface));
  g_object_unref (G_OBJECT (launcher_context->connection));
  
  g_object_unref (G_OBJECT (launcher_context->launcher_entry));
  
  g_object_unref (G_OBJECT (launcher_context->action_manager));

  g_free (launcher_context);
}
