/*
 * Pidgin Knotify plugin for KDE 4
 *
 * Copyright (C) 2009 Ian J.Yue <ian.j.yue@gmail.com>
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the term of the GNU General Public License as published by 
 * the Free Software Foundation, either version 3, or (at your option)
 * any later version.
 *
 * This program 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
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#ifndef PURPLE_PLUGINS
#define PURPLE_PLUGINS
#endif

#include <glib.h>
#include <stdlib.h>

#include "connection.h"
#include "conversation.h"
#include "core.h"
#include "debug.h"
#include "signals.h"
#include "version.h"
#include "status.h"

#define PIDGIN_KNOTIFY_PLUGIN_ID 		"pidgin-knotify"
#define PIDGIN_KNOTIFY_PLUGIN_NAME		"Pidgin Knotify"
#define PIDGIN_KNOTIFY_PLUGIN_VERSION	"0.2.1"
#define PIDGIN_KNOTIFY_PLUGIN_SUMMARY   "Pidgin Knotify"
#define PIDGIN_KNOTIFY_PLUGIN_DESR	    "Knotify for Pidgin events in KDE environment desktop."
#define PIDGIN_KNOTIFY_PLUGIN_AUTHOR	"Ian J.Yue <ian.j.yue@gmail.com>"
#define PIDGIN_KNOTIFY_PLUGIN_HOMEPAGE	"http://pidgin-knotify.googlecode.com"

/* Preferences */

/* The number of seconds of notification */
#define NOTIFY_TIMEOUT "/plugins/knotify/notify_timeout"
#define TIMEOUT_DEFAULT 3

#define NEW_MESSAGE "/plugins/knotify/newmsg"

#define SIGN_ON "/plugins/knotify/signon"

#define SIGN_OFF "/plugins/knotify/signoff"

#define ONLY_AVAILABLE "/plugins/knotify/only_available"

/*int timeout = 3;*/				/* in second */

static void
notify(const gchar *title,
	   const gchar *body)
{
	gchar *command = NULL;
	int result, timeout;

	timeout = purple_prefs_get_int("/plugins/knotify/notify_timeout");
	command = g_strdup_printf("kdialog --title '%s' --passivepopup '%s' %d", title, body, timeout);

	if (command != NULL) {
			result = system(command);
			g_free(command);
	}
}

/* Signon flood be gone! - thanks to pidgin-libnotify */
static GList *just_signed_on_accounts = NULL;

static gboolean
event_connection_throttle_cb(gpointer data)
{
	PurpleAccount *account;

	account = (PurpleAccount *) data;

	if(! account)
		return FALSE;
	
	if(! purple_account_get_connection(account)) {
		just_signed_on_accounts = g_list_remove(just_signed_on_accounts, account);
		return FALSE;
	}

	if(! purple_account_is_connected(account))
		return TRUE;

	just_signed_on_accounts = g_list_remove(just_signed_on_accounts, account);
	return FALSE;
}

static void
event_connection_throttle(PurpleConnection *conn, gpointer data)
{
	PurpleAccount *account;

	/* TODO: this function gets called after buddy signs on for GTalk
	   users who have themselves as a buddy */
	purple_debug_info(PIDGIN_KNOTIFY_PLUGIN_ID, "event_connection_throttle() called\n");

	if(! conn)
		return;
	
	account = purple_connection_get_account(conn);
	if(! account)
		return;

	just_signed_on_accounts = g_list_prepend(just_signed_on_accounts, account);
	g_timeout_add(5000, event_connection_throttle_cb, (gpointer) account);
}


static gchar *
display_name(PurpleBuddy *buddy)
{
	if (buddy->alias) {
                return buddy->alias;
        } else if (buddy->server_alias) {
                return buddy->server_alias;
        } else {
                return buddy->name;
        }
}


static void
notify_buddy_signon_cb(PurpleBuddy *buddy, gpointer data)
{	
	gchar *name = display_name(buddy);
	gchar *body = NULL;

	if(!purple_prefs_get_bool(SIGN_ON)) return;

	/* fix signon flood */
	if(g_list_find(just_signed_on_accounts, buddy->account))
		return;

	body = g_strdup_printf("%s signed on.", name);
	notify("Pidgin", body);
	if(body != NULL)
		g_free(body);
}

static void
notify_buddy_signoff_cb(PurpleBuddy *buddy, gpointer data)
{
	gchar * name = display_name(buddy);
	gchar * body = NULL;

	if(!purple_prefs_get_bool(SIGN_OFF)) return;

	body = g_strdup_printf("%s signed off.", name);
	notify("Pidgin", body);
	if(body != NULL)
		g_free(body);
}

static void
notify_new_message_cb(PurpleAccount *account,
					  const gchar *sender,
					  const gchar *message,
					  int flags,
					  gpointer data)
{
	PurpleConversation *conv;
	PurpleBuddy *buddy;
	gchar *title = NULL, *body = NULL;
	gchar * name;

	if(!purple_prefs_get_bool(NEW_MESSAGE)) return;

	conv = purple_find_conversation_with_account (PURPLE_CONV_TYPE_IM, sender, account);

	if(conv && purple_conversation_has_focus(conv))
		return;
	
	buddy = purple_find_buddy(account, sender);
	if(!buddy) return;

	name = display_name(buddy);
	title = g_strdup_printf("%s says:", name);
	body = purple_markup_strip_html(message);

	notify(title, body);

	if(title != NULL) 
		g_free(title);
	if(body != NULL)
		g_free(body);
}

static void
notify_chat_cb(PurpleAccount *account,
			   const gchar *sender,
			   const gchar *message,
			   PurpleConversation *conv,
			   gpointer data)
{

}


static gboolean
plugin_load(PurplePlugin *plugin)
{
	void *blist_handle, *conn_handle, *conv_handle;

	blist_handle = purple_blist_get_handle();
	conn_handle = purple_connections_get_handle();
	conv_handle = purple_conversations_get_handle();

	/* pidgin events */
	purple_signal_connect(blist_handle, "buddy-signed-on", plugin,
						  PURPLE_CALLBACK(notify_buddy_signon_cb),
						  NULL);

	purple_signal_connect(blist_handle, "buddy-signed-off", plugin,
						  PURPLE_CALLBACK(notify_buddy_signoff_cb),
						  NULL);

	purple_signal_connect(conv_handle, "received-im-msg", plugin,
						  PURPLE_CALLBACK(notify_new_message_cb),
						  NULL);

	purple_signal_connect(conv_handle, "received-chat-msg", plugin,
						  PURPLE_CALLBACK(notify_chat_cb),
						  NULL);

	/* used just to not display the flood */
	purple_signal_connect(conn_handle, "signed-on", plugin,
						  PURPLE_CALLBACK(event_connection_throttle),
						  NULL);
	return TRUE;
}

static gboolean
plugin_unload (PurplePlugin *plugin)
{
	void *blist_handle, *conn_handle, *conv_handle;
	
	blist_handle = purple_blist_get_handle();
	conn_handle = purple_connections_get_handle();
	conv_handle = purple_conversations_get_handle();

	purple_signal_disconnect(blist_handle, "buddy-signed-on", plugin,
							 PURPLE_CALLBACK(notify_buddy_signon_cb));

	purple_signal_disconnect(blist_handle, "buddy-signed-off", plugin,
							 PURPLE_CALLBACK(notify_buddy_signoff_cb));

	purple_signal_disconnect(conv_handle, "received-im-msg", plugin,
							 PURPLE_CALLBACK(notify_new_message_cb));

	purple_signal_disconnect(conv_handle, "received-chat-msg", plugin,
							 PURPLE_CALLBACK(notify_chat_cb));

	purple_signal_disconnect(conn_handle, "signed-on", plugin,
							 PURPLE_CALLBACK(event_connection_throttle));

	return TRUE;
}


/* preference items */
static PurplePluginPrefFrame *
get_plugin_pref_frame(PurplePlugin *plugin)
{
	PurplePluginPrefFrame *frame;
	PurplePluginPref *ppref;

	frame = purple_plugin_pref_frame_new();
	
	ppref = purple_plugin_pref_new_with_name_and_label(
							NEW_MESSAGE,
							"New messages");
	purple_plugin_pref_frame_add(frame, ppref);

	ppref = purple_plugin_pref_new_with_name_and_label(
							SIGN_ON,
							"Buddy signs on");
	purple_plugin_pref_frame_add(frame, ppref);

	ppref = purple_plugin_pref_new_with_name_and_label(
							SIGN_OFF,
							"Buddy signs off");
	purple_plugin_pref_frame_add(frame, ppref);
	
	/*
	ppref = purple_plugin_pref_new_with_name_and_label(
							ONLY_AVAILABLE,
							"Only when available");
	purple_plugin_pref_frame_add(frame, ppref);
	*/
	
	ppref = purple_plugin_pref_new_with_name_and_label(
							NOTIFY_TIMEOUT,
							"Notify timeout (s)");
	purple_plugin_pref_set_bounds(ppref, 1, 60);
	purple_plugin_pref_frame_add(frame, ppref);

	return frame;
}


static PurplePluginUiInfo prefs_info = {
	get_plugin_pref_frame,
	0,                              /* page num */
	NULL,                           /* frame */
	/* Padding */
	NULL,
	NULL,
	NULL,
	NULL
};

static PurplePluginInfo info = 
{
	PURPLE_PLUGIN_MAGIC,
	PURPLE_MAJOR_VERSION,
	PURPLE_MINOR_VERSION,
	PURPLE_PLUGIN_STANDARD,		     /* type */
	NULL,						     /* UI_requirement */
	0,							     /* flags */
	NULL,						     /* dependencies */
	PURPLE_PRIORITY_DEFAULT,	     /* priority */
	PIDGIN_KNOTIFY_PLUGIN_ID,        /* ID */
	PIDGIN_KNOTIFY_PLUGIN_NAME,	     /* NAME */
	PIDGIN_KNOTIFY_PLUGIN_VERSION,   /* VERSION */
	PIDGIN_KNOTIFY_PLUGIN_SUMMARY,	 /* summary */
	PIDGIN_KNOTIFY_PLUGIN_DESR,      /* description */
	PIDGIN_KNOTIFY_PLUGIN_AUTHOR,    /* author */
	PIDGIN_KNOTIFY_PLUGIN_HOMEPAGE,  /* homepage */
	plugin_load,					 /* load */
	plugin_unload,					 /* unload */
	NULL,							 /* destroy */
	NULL,						     /* ui_info */
	NULL,							 /* extra_info */
	&prefs_info,                     /* prefs_info */
	NULL,                            /* actions */
	/* Padding */
	NULL,
	NULL,
	NULL,
	NULL
};

static void
init_plugin(PurplePlugin *plugin)
{
	purple_prefs_add_none("/plugins/knotify");
	purple_prefs_add_bool(NEW_MESSAGE, TRUE);
	purple_prefs_add_bool(SIGN_ON, TRUE);
	purple_prefs_add_bool(SIGN_OFF, TRUE);
	/*purple_prefs_add_bool(ONLY_AVAILABLE, FALSE);*/
	purple_prefs_add_int(NOTIFY_TIMEOUT, TIMEOUT_DEFAULT);
}


PURPLE_INIT_PLUGIN(pidgin_knotify, init_plugin, info)
