/*
 * 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 <stdio.h>

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

#include "unity-webapps-sanitizer.h"
#include "unity-webapps-debug.h"

#include "unity-webapps-rate.h"
#include "unity-webapps-dbus-util.h"

typedef struct _unity_webapps_launcher_action_data {
  UnityWebappsLauncherCallback callback;
  gpointer user_data;
} unity_webapps_launcher_action_data;

static void
_launcher_context_action_invoked (UnityWebappsGenLauncher *launcher,
				  const gchar *label,
          gint interest_id,
				  gpointer user_data)
{
  UnityWebappsContext *context;
  unity_webapps_launcher_action_data *data;
  
  context = (UnityWebappsContext *)user_data;
  g_return_if_fail(context != NULL);

  if (!G_IS_OBJECT(context))
    return;

  if (context->priv->interest_id != interest_id)
    return;
  
  data = g_hash_table_lookup (context->priv->launcher_context->quicklist_callbacks_by_name, label);
  
  if ((data != NULL) && (data->callback != NULL))
    {
      UNITY_WEBAPPS_NOTE (LAUNCHER, "Quicklist action invoked: %s", label);

      data->callback(context, data->user_data);
      return;
    }
  
  UNITY_WEBAPPS_NOTE (LAUNCHER, "Quicklist action invoked, but we do not have a handler: %s", label);
}

UnityWebappsLauncherContext *
unity_webapps_launcher_context_new (UnityWebappsContext *main_context, GError **error)
{
  UnityWebappsLauncherContext *context;
  
  context = g_malloc0 (sizeof (UnityWebappsLauncherContext));
  context->launcher_rate = 0;
  
  context->launcher_proxy = 
    unity_webapps_gen_launcher_proxy_new_sync (unity_webapps_service_get_connection (main_context->priv->service) ,
					       G_DBUS_PROXY_FLAGS_NONE,
					       main_context->priv->context_name,
					       UNITY_WEBAPPS_LAUNCHER_PATH, 
					       NULL /* Cancellable */,
					       error);
  
  if (error && (*error != NULL))
    {
      g_critical ("Error creating launcher context proxy object for %s: %s", main_context->priv->context_name, (*error)->message);
      
      return NULL;
    }
  
  context->quicklist_callbacks_by_name = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
  
  g_signal_connect (context->launcher_proxy, "action-invoked", G_CALLBACK (_launcher_context_action_invoked), main_context);
  
  return context;
}

void 
unity_webapps_launcher_context_free (UnityWebappsLauncherContext *context)
{
  g_return_if_fail (context != NULL);
  g_object_unref (G_OBJECT (context->launcher_proxy));
  
  g_hash_table_destroy (context->quicklist_callbacks_by_name);
  
  g_free (context);
}

UNITY_WEBAPPS_DEFINE_VOID_DBUS_HANDLER(set_count,launcher,Launcher,LAUNCHER,"Count succesfully set");

void
unity_webapps_launcher_set_count (UnityWebappsContext *context,
				  gint count)
{
  g_return_if_fail (context != NULL);
  g_return_if_fail (UNITY_WEBAPPS_IS_CONTEXT (context));
  
  if (unity_webapps_rate_check_launcher_rate_limit (context) == FALSE)
    {
      return;
    }
  
  unity_webapps_gen_launcher_call_set_count (context->priv->launcher_context->launcher_proxy,
					     count,
					     NULL /* Cancellable */,
					     set_count_complete_callback,
					     context);
  UNITY_WEBAPPS_NOTE (LAUNCHER, "Setting count: %d", count);
}

UNITY_WEBAPPS_DEFINE_VOID_DBUS_HANDLER(set_progress,launcher,Launcher,LAUNCHER,"Progress succesfully set");

void
unity_webapps_launcher_set_progress (UnityWebappsContext *context,
				     gdouble progress)
{
  g_return_if_fail (context != NULL);
  g_return_if_fail (UNITY_WEBAPPS_IS_CONTEXT (context));
  
  if (unity_webapps_rate_check_launcher_rate_limit (context) == FALSE)
    {
      return;
    }
  
  unity_webapps_gen_launcher_call_set_progress (context->priv->launcher_context->launcher_proxy,
						progress,
						NULL /* Cancellable */,
						set_progress_complete_callback,
						context);

  UNITY_WEBAPPS_NOTE (LAUNCHER, "Setting progress: %f", progress);
}

UNITY_WEBAPPS_DEFINE_VOID_DBUS_HANDLER(clear_count,launcher,Launcher,LAUNCHER,"Count succesfully cleared");

void
unity_webapps_launcher_clear_count (UnityWebappsContext *context)
				  
{
  g_return_if_fail (context != NULL);
  g_return_if_fail (UNITY_WEBAPPS_IS_CONTEXT (context));
  
  if (unity_webapps_rate_check_launcher_rate_limit (context) == FALSE)
    {
      return;
    }
  
  unity_webapps_gen_launcher_call_clear_count (context->priv->launcher_context->launcher_proxy,
					       NULL /* Cancellable */,
					       clear_count_complete_callback,
					       context);
  
  UNITY_WEBAPPS_NOTE (LAUNCHER, "Clearing count");
}

UNITY_WEBAPPS_DEFINE_VOID_DBUS_HANDLER(clear_progress,launcher,Launcher,LAUNCHER,"Progress succesfully cleared");

void
unity_webapps_launcher_clear_progress (UnityWebappsContext *context)
				  
{
  g_return_if_fail (context != NULL);
  g_return_if_fail (UNITY_WEBAPPS_IS_CONTEXT (context));
  
  if (unity_webapps_rate_check_launcher_rate_limit (context) == FALSE)
    {
      return;
    }
  
  unity_webapps_gen_launcher_call_clear_progress (context->priv->launcher_context->launcher_proxy,
						  NULL /* Cancellable */,
						  clear_progress_complete_callback,
						  context);
						
  UNITY_WEBAPPS_NOTE (LAUNCHER, "Clearing progress");
}

UNITY_WEBAPPS_DEFINE_VOID_DBUS_HANDLER(set_urgent,launcher,Launcher,LAUNCHER,"Urgent state succesfully set");

void
unity_webapps_launcher_set_urgent (UnityWebappsContext *context)
				  
{
  g_return_if_fail (context != NULL);
  g_return_if_fail (UNITY_WEBAPPS_IS_CONTEXT (context));
  
  if (unity_webapps_rate_check_launcher_rate_limit (context) == FALSE)
    {
      return;
    }
  
  unity_webapps_gen_launcher_call_set_urgent (context->priv->launcher_context->launcher_proxy,
					      NULL /* Cancellable */,
					      set_urgent_complete_callback,
					      context);
  
  UNITY_WEBAPPS_NOTE (LAUNCHER, "Setting urgent state");
}

UNITY_WEBAPPS_DEFINE_VOID_DBUS_HANDLER(add_static_action,launcher,Launcher,LAUNCHER,"Static action succesfully added");

#define MAXIMUM_LABEL_LENGTH 60

void
unity_webapps_launcher_add_static_action (UnityWebappsContext *context, const gchar *label, const gchar *page)
{
  g_return_if_fail (context != NULL);
  g_return_if_fail (UNITY_WEBAPPS_IS_CONTEXT (context));

  if (unity_webapps_rate_check_launcher_rate_limit (context) == FALSE)
    {
      return;
    }

  unity_webapps_gen_launcher_call_add_static_action (context->priv->launcher_context->launcher_proxy,
						     label,
						     page,
						     NULL,
						     add_static_action_complete_callback,
						     context);

  UNITY_WEBAPPS_NOTE (LAUNCHER, "Adding static action: %s", label);
}

UNITY_WEBAPPS_DEFINE_VOID_DBUS_HANDLER(remove_static_actions,launcher,Launcher,LAUNCHER,"Static actions succesfully removed");

void
unity_webapps_launcher_remove_static_actions (UnityWebappsContext *context)
{
  g_return_if_fail (context != NULL);
  g_return_if_fail (UNITY_WEBAPPS_IS_CONTEXT (context));

  if (unity_webapps_rate_check_launcher_rate_limit (context) == FALSE)
    {
      return;
    }

  unity_webapps_gen_launcher_call_remove_static_actions (context->priv->launcher_context->launcher_proxy,
							 NULL,
							 remove_static_actions_complete_callback,
							 context);

  UNITY_WEBAPPS_NOTE (LAUNCHER, "Removing all static actions");
}


UNITY_WEBAPPS_DEFINE_VOID_DBUS_HANDLER(add_action,launcher,Launcher,LAUNCHER,"Action succesfully added");

void
unity_webapps_launcher_add_action (UnityWebappsContext *context, const gchar *label, UnityWebappsLauncherCallback callback, gpointer user_data)
				  
{
  gchar *sanitized_label;
  unity_webapps_launcher_action_data *data;

  g_return_if_fail (context != NULL);
  g_return_if_fail (UNITY_WEBAPPS_IS_CONTEXT (context));
  g_return_if_fail (callback != NULL);


  if (unity_webapps_rate_check_launcher_rate_limit (context) == FALSE)
    {
      return;
    }
  
  // The Hash Table takes ownership of this.
  sanitized_label = unity_webapps_sanitizer_limit_string_argument (label, MAXIMUM_LABEL_LENGTH);
  
  unity_webapps_gen_launcher_call_add_action (context->priv->launcher_context->launcher_proxy,
					      sanitized_label,
					      context->priv->interest_id,
					      NULL /* Cancellable */,
					      add_action_complete_callback,
					      context);
  
  data = g_malloc0 (sizeof (unity_webapps_launcher_action_data));
  data->callback = callback;
  data->user_data = user_data;
  
  g_hash_table_insert (context->priv->launcher_context->quicklist_callbacks_by_name, sanitized_label, data);
  
  UNITY_WEBAPPS_NOTE (LAUNCHER, "Adding action: %s", label);
}

UNITY_WEBAPPS_DEFINE_VOID_DBUS_HANDLER(remove_action,launcher,Launcher,LAUNCHER,"Action succesfully removed");

void
unity_webapps_launcher_remove_action (UnityWebappsContext *context, const gchar *label)
{
  gchar *sanitized_label;

  g_return_if_fail (context != NULL);
  g_return_if_fail (UNITY_WEBAPPS_IS_CONTEXT (context));

  if (unity_webapps_rate_check_launcher_rate_limit (context) == FALSE)
    {
      return;
    }
  
  sanitized_label = unity_webapps_sanitizer_limit_string_argument (label, MAXIMUM_LABEL_LENGTH);
  
  unity_webapps_gen_launcher_call_remove_action (context->priv->launcher_context->launcher_proxy,
						 sanitized_label,
						 context->priv->interest_id,
						 NULL /* Cancellable */,
						 remove_action_complete_callback,
						 context);
  
  g_hash_table_remove (context->priv->launcher_context->quicklist_callbacks_by_name, sanitized_label);
  
  UNITY_WEBAPPS_NOTE (LAUNCHER, "Removing action: %s", label);

  g_free (sanitized_label);
}

UNITY_WEBAPPS_DEFINE_VOID_DBUS_HANDLER(remove_actions,launcher,Launcher,LAUNCHER,"Action succesfully removed");

void
unity_webapps_launcher_remove_actions (UnityWebappsContext *context)
				  
{
  g_return_if_fail (context != NULL);
  g_return_if_fail (UNITY_WEBAPPS_IS_CONTEXT (context));

  if (unity_webapps_rate_check_launcher_rate_limit (context) == FALSE)
    {
      return;
    }
  
  unity_webapps_gen_launcher_call_remove_actions (context->priv->launcher_context->launcher_proxy,
						  context->priv->interest_id,
						  NULL /* Cancellable */,
						  remove_actions_complete_callback,
						  context);
  
  g_hash_table_remove_all (context->priv->launcher_context->quicklist_callbacks_by_name);
  
  UNITY_WEBAPPS_NOTE (LAUNCHER, "Removing all actions");
}
