#include "internal.h"

#include "version.h"
#include "pidginstock.h"
#include "gtkblist.h"
#include "gtkplugin.h"
#include "gtkutils.h"
#include "dbus-maybe.h"

#define MEEBO_PLUGIN_ID "gtk-meebo"

static void *request_authorize;
const char *meebo_guests_group = "Meebo Guests";

static void
add_meebo_guest(PurpleAccount *account, const char *username,
								 const char *group, const char *alias)
{
	PurpleGroup *g;
	PurpleBuddy *b;
	PurpleConversation *c;

	group = meebo_guests_group;
	if (username == NULL) username = "meebo guest";
	if ((g = purple_find_group(group)) == NULL)
	{
		g = purple_group_new(group);
		purple_blist_add_group(g, NULL);
	}

	b = purple_buddy_new(account, username, alias);
	purple_blist_add_buddy(b, NULL, g, NULL);
	purple_account_add_buddy(account, b);

	c = purple_find_conversation_with_account(
							PURPLE_CONV_TYPE_IM, username, account);
	if (c != NULL) {
		PurpleBuddyIcon *icon = purple_conv_im_get_icon(PURPLE_CONV_IM(c));
		if (icon != NULL)
			purple_buddy_icon_update(icon);
	}
}

struct auth_and_add {
	PurpleAccountRequestAuthorizationCb auth_cb;
	PurpleAccountRequestAuthorizationCb deny_cb;
	void *data;
	char *username;
	char *alias;
	PurpleAccount *account;
};

static void
authorize_and_add_cb(struct auth_and_add *aa)
{
	aa->auth_cb(aa->data);
	purple_blist_request_add_buddy(aa->account, aa->username,
	 	                    NULL, aa->alias);

	g_free(aa->username);
	g_free(aa->alias);
	g_free(aa);
}

static void
authorize_and_add_cb_meebo(struct auth_and_add *aa)
{
	aa->auth_cb(aa->data);
	add_meebo_guest(aa->account, aa->username,
	 	                    NULL, aa->alias);

	g_free(aa->username);
	g_free(aa->alias);
	g_free(aa);
}

static void
deny_no_add_cb(struct auth_and_add *aa)
{
	aa->deny_cb(aa->data);

	g_free(aa->username);
	g_free(aa->alias);
	g_free(aa);
}

static void *
my_pidgin_accounts_request_authorization(PurpleAccount *account, const char *remote_user,
					const char *id, const char *alias, const char *message, gboolean on_list,
					GCallback auth_cb, GCallback deny_cb, void *user_data)
{
	char *buffer;
	PurpleConnection *gc;
	GtkWidget *alert;
	PurplePluginProtocolInfo *prpl_info;
	const char* protoname;

	gc = purple_account_get_connection(account);
	if (message != NULL && *message == '\0')
		message = NULL;

	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
	protoname = prpl_info->list_icon(account, NULL);
	if(!strcmp(protoname, "jabber") && strstr(g_strdup(remote_user),"@guest") != NULL &&
				strstr(g_strdup(remote_user),".meebo.org") != NULL) {
		struct auth_and_add *aa = g_new0(struct auth_and_add, 1);
		aa->auth_cb = (PurpleAccountRequestAuthorizationCb)auth_cb;
		aa->deny_cb = (PurpleAccountRequestAuthorizationCb)deny_cb;
		aa->data = user_data;
		aa->username = g_strdup(remote_user);
		aa->alias = g_strdup(alias);
		aa->account = account;
		authorize_and_add_cb_meebo(aa);
	}
	else {

		buffer = g_strdup_printf(_("%s%s%s%s wants to add %s to his or her buddy list%s%s"),
					remote_user,
							(alias != NULL ? " ("  : ""),
							(alias != NULL ? alias : ""),
							(alias != NULL ? ")"   : ""),
							(id != NULL
							? id
							: (purple_connection_get_display_name(gc) != NULL
							? purple_connection_get_display_name(gc)
							: purple_account_get_username(account))),
							(message != NULL ? ": " : "."),
							(message != NULL ? message  : ""));


		if (!on_list) {
			struct auth_and_add *aa = g_new0(struct auth_and_add, 1);
			aa->auth_cb = (PurpleAccountRequestAuthorizationCb)auth_cb;
			aa->deny_cb = (PurpleAccountRequestAuthorizationCb)deny_cb;
			aa->data = user_data;
			aa->username = g_strdup(remote_user);
			aa->alias = g_strdup(alias);
			aa->account = account;
			alert = pidgin_make_mini_dialog(gc, PIDGIN_STOCK_DIALOG_QUESTION,
							  _("Authorize buddy?"), buffer, aa,
							  _("Authorize"), authorize_and_add_cb,
							  _("Deny"), deny_no_add_cb,
							  NULL);
		} else {
			alert = pidgin_make_mini_dialog(gc, PIDGIN_STOCK_DIALOG_QUESTION,
							  _("Authorize buddy?"), buffer, user_data,
							  _("Authorize"), auth_cb,
							  _("Deny"), deny_cb,
							  NULL);
		}
		pidgin_blist_add_alert(alert);

		g_free(buffer);
	}

	return NULL;
}

static void
remove_group(PurpleGroup *group)
{
	PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
	PurpleBuddyList *purplebuddylist = purple_get_blist();
	PurpleBlistNode *node;
	GList *l;

	g_return_if_fail(group != NULL);

	node = (PurpleBlistNode *)group;

	/* Remove the node from its parent */
	if (purplebuddylist->root == node)
		purplebuddylist->root = node->next;
	if (node->prev)
		node->prev->next = node->next;
	if (node->next)
		node->next->prev = node->prev;

	purple_blist_schedule_save();

	/* Update the UI */
	if (ops && ops->remove)
		ops->remove(purplebuddylist, node);

	/* Remove the group from all accounts that are online */
	for (l = purple_connections_get_all(); l != NULL; l = l->next)
	{
		PurpleConnection *gc = (PurpleConnection *)l->data;

		if (purple_connection_get_state(gc) == PURPLE_CONNECTED)
			purple_account_remove_group(purple_connection_get_account(gc), group);
	}

	/* Delete the node */
	g_hash_table_destroy(group->node.settings);
	g_free(group->name);
	PURPLE_DBUS_UNREGISTER_POINTER(group);
	g_free(group);
}

static void
remove_meebo_buddy(PurpleBuddy *buddy)
{
	PurpleGroup *group = purple_buddy_get_group(buddy);
	purple_account_remove_buddy(purple_buddy_get_account(buddy), buddy, group);
	purple_blist_remove_buddy(buddy);

	if(!((PurpleBlistNode*)group)->child) {
		remove_group(group);
	}
}

static void
buddy_signoff_cb(PurpleBuddy *buddy)
{
	PurplePlugin *plugin = purple_plugins_find_with_id(purple_account_get_protocol_id(buddy->account));
	PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
	const char* protoname = prpl_info->list_icon(purple_buddy_get_account(buddy), NULL);
	const char* name = purple_buddy_get_name(buddy);
	if(!strcmp(protoname, "jabber") && strstr(name,"@guest") != NULL &&
				strstr(name,".meebo.org") != NULL) {
		purple_timeout_add(10000,(GSourceFunc)remove_meebo_buddy, buddy);
	}
}

static void
sign_on_cb(PurpleConnection *gc, PurpleBuddyList *blist)
{
	PurpleGroup *group;
	group = purple_find_group(meebo_guests_group);
	remove_group(group);
}

static void
xmlnode_received_cb(PurpleConnection *gc, xmlnode **packet, gpointer null)
{
	char *nick;
	PurpleBuddy * buddy;
	const char *from = xmlnode_get_attrib(*packet, "from");
	if(from != NULL && strstr(g_strdup(from),"@guest") != NULL && strstr(g_strdup(from),".meebo.org") != NULL) {
		nick = xmlnode_get_data(xmlnode_get_child(*packet, "nick"));
		if(nick != NULL) {
			buddy = purple_find_buddy(gc->account, from);
			purple_blist_server_alias_buddy(buddy, nick);
		}
	}
}

static gboolean
plugin_load(PurplePlugin *plugin)
{
	void *gtk_blist_handle;
	PurpleAccountUiOps *ui_ops;
	PurplePlugin *jabber;

	jabber = purple_find_prpl("prpl-jabber");
	if (!jabber)
		return FALSE;

	purple_signal_connect(jabber, "jabber-receiving-xmlnode", plugin,
			PURPLE_CALLBACK(xmlnode_received_cb), NULL);

	ui_ops = purple_accounts_get_ui_ops();
	request_authorize = ui_ops->request_authorize;
	ui_ops->request_authorize = my_pidgin_accounts_request_authorization;

	gtk_blist_handle = pidgin_blist_get_handle();
	purple_signal_connect(purple_blist_get_handle(), "buddy-signed-off",
				gtk_blist_handle, PURPLE_CALLBACK(buddy_signoff_cb), NULL);
	purple_signal_connect(purple_connections_get_handle(), "signed-on",
				gtk_blist_handle, PURPLE_CALLBACK(sign_on_cb), NULL);
	return TRUE;
}

static gboolean
plugin_unload(PurplePlugin *plugin)
{
	void *gtk_blist_handle;
	PurpleAccountUiOps *ui_ops;

	ui_ops = purple_accounts_get_ui_ops();
	ui_ops->request_authorize = request_authorize;

	gtk_blist_handle = pidgin_blist_get_handle();
	purple_signal_disconnect(purple_blist_get_handle(), "buddy-signed-off",
				gtk_blist_handle, PURPLE_CALLBACK(buddy_signoff_cb));
	return TRUE;
}

static PurplePluginInfo info =
{
	PURPLE_PLUGIN_MAGIC,
	PURPLE_MAJOR_VERSION,
	PURPLE_MINOR_VERSION,
	PURPLE_PLUGIN_STANDARD,
	PIDGIN_PLUGIN_TYPE,
	0,
	NULL,
	PURPLE_PRIORITY_DEFAULT,
	MEEBO_PLUGIN_ID,
	N_("Meebo Guest Auto Add/Remove"),
	"2.0.2",
	N_("Allows automatic adding and removal of meebo widget guests."),
	N_("This plugin was created for use with the meebo me widget. When "
		"people visit the web page on which your widget is placed, a buddy "
		"will automatically be added to your list in a group titled Meebo "
		"Guests. When they leave the site, the buddy will automatically be "
		"removed from your list."),
	"Justin Pomeroy <jrpomeroy@gmail.com>",
	"http://jrpomeroy.com/pidgin",
	plugin_load,
	plugin_unload,
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,

	/* padding */
	NULL,
	NULL,
	NULL,
	NULL
};

static void
init_plugin(PurplePlugin *plugin)
{
}

PURPLE_INIT_PLUGIN(meebo, init_plugin, info)

