/*
 *
 *  OBEX Client
 *
 *  Copyright (C) 2011 Intel Corporation
 *
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, 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, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

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

#include <errno.h>
#include <gdbus/gdbus.h>

#include "log.h"

#include "transfer.h"
#include "session.h"
#include "driver.h"
#include "opp.h"

#define OPP_UUID "00001105-0000-1000-8000-00805f9b34fb"
#define OPP_INTERFACE "org.bluez.obex.ObjectPush1"
#define ERROR_INTERFACE "org.bluez.obex.Error"

struct opp_data {
	struct obc_session *session;
};

static DBusConnection *conn = NULL;

static DBusMessage *opp_send_file(DBusConnection *connection,
					DBusMessage *message, void *user_data)
{
	struct opp_data *opp = user_data;
	struct obc_transfer *transfer;
	DBusMessage *reply;
	char *filename;
	char *basename;
	GError *err = NULL;

	if (dbus_message_get_args(message, NULL,
					DBUS_TYPE_STRING, &filename,
					DBUS_TYPE_INVALID) == FALSE)
		return g_dbus_create_error(message,
				ERROR_INTERFACE ".InvalidArguments", NULL);

	basename = g_path_get_basename(filename);

	transfer = obc_transfer_put(NULL, basename, filename, NULL, 0, &err);

	g_free(basename);

	if (transfer == NULL)
		goto fail;

	if (!obc_session_queue(opp->session, transfer, NULL, NULL, &err))
		goto fail;

	return obc_transfer_create_dbus_reply(transfer, message);

fail:
	reply = g_dbus_create_error(message,
				ERROR_INTERFACE ".Failed", "%s", err->message);
	g_error_free(err);
	return reply;
}

static DBusMessage *opp_pull_business_card(DBusConnection *connection,
					DBusMessage *message, void *user_data)
{
	struct opp_data *opp = user_data;
	struct obc_transfer *pull;
	DBusMessage *reply;
	const char *filename = NULL;
	GError *err = NULL;

	if (dbus_message_get_args(message, NULL,
				DBUS_TYPE_STRING, &filename,
				DBUS_TYPE_INVALID) == FALSE)
		return g_dbus_create_error(message,
				ERROR_INTERFACE ".InvalidArguments", NULL);

	pull = obc_transfer_get("text/x-vcard", NULL, filename, &err);
	if (pull == NULL)
		goto fail;

	if (!obc_session_queue(opp->session, pull, NULL, NULL, &err))
		goto fail;

	return obc_transfer_create_dbus_reply(pull, message);

fail:
	reply = g_dbus_create_error(message,
				ERROR_INTERFACE ".Failed", "%s", err->message);
	g_error_free(err);
	return reply;
}

static DBusMessage *opp_exchange_business_cards(DBusConnection *connection,
					DBusMessage *message, void *user_data)
{
	return g_dbus_create_error(message, ERROR_INTERFACE ".Failed", NULL);
}

static const GDBusMethodTable opp_methods[] = {
	{ GDBUS_METHOD("SendFile",
		GDBUS_ARGS({ "sourcefile", "s" }),
		GDBUS_ARGS({ "transfer", "o" }, { "properties", "a{sv}" }),
		opp_send_file) },
	{ GDBUS_METHOD("PullBusinessCard",
		GDBUS_ARGS({ "targetfile", "s" }),
		GDBUS_ARGS({ "transfer", "o" }, { "properties", "a{sv}" }),
		opp_pull_business_card) },
	{ GDBUS_METHOD("ExchangeBusinessCards",
		GDBUS_ARGS({ "clientfile", "s" }, { "targetfile", "s" }),
		GDBUS_ARGS({ "transfer", "o" }, { "properties", "a{sv}" }),
		opp_exchange_business_cards) },
	{ }
};

static void opp_free(void *data)
{
	struct opp_data *opp = data;

	obc_session_unref(opp->session);
	g_free(opp);
}

static int opp_probe(struct obc_session *session)
{
	struct opp_data *opp;
	const char *path;

	path = obc_session_get_path(session);

	DBG("%s", path);

	opp = g_try_new0(struct opp_data, 1);
	if (!opp)
		return -ENOMEM;

	opp->session = obc_session_ref(session);

	if (!g_dbus_register_interface(conn, path, OPP_INTERFACE, opp_methods,
						NULL, NULL, opp, opp_free)) {
		opp_free(opp);
		return -ENOMEM;
	}

	return 0;
}

static void opp_remove(struct obc_session *session)
{
	const char *path = obc_session_get_path(session);

	DBG("%s", path);

	g_dbus_unregister_interface(conn, path, OPP_INTERFACE);
}

static struct obc_driver opp = {
	.service = "OPP",
	.uuid = OPP_UUID,
	.probe = opp_probe,
	.remove = opp_remove
};

int opp_init(void)
{
	int err;

	DBG("");

	conn = dbus_bus_get(DBUS_BUS_SESSION, NULL);
	if (!conn)
		return -EIO;

	err = obc_driver_register(&opp);
	if (err < 0) {
		dbus_connection_unref(conn);
		conn = NULL;
		return err;
	}

	return 0;
}

void opp_exit(void)
{
	DBG("");

	dbus_connection_unref(conn);
	conn = NULL;

	obc_driver_unregister(&opp);
}
