/*
 * libsyncml - A syncml protocol implementation
 * Copyright (C) 2005  Armin Bauer <armin.bauer@opensync.org>
 * Copyright (C) 2008  Michael Bell <michael.bell@opensync.org>
 *
 * This library 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 2.1 of the License, or (at your option) any later version.
 *
 * This library 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 library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 *
 */

#include "../support.h"

/* ************************************
 * *********** OMA DS SERVER **********
 * ************************************
 *          (libsyncml customer)
 */

extern SmlTransportType tspType;
extern const char *obex_port;
extern const char *maxObjSize;
extern const char *maxMsgSize;
extern const char *enableWbxml;
extern const char *useTimestamp;
extern const char *identifier;
extern const char *locList[];

#include <libsyncml/data_sync_api/sml_data_sync_defines.h>
#include <libsyncml/data_sync_api/sml_data_sync.h>

static void
_libsyncml_event_callback (SmlDataSyncSession *session,
                           SmlDataSync *dsObject,
                           SmlDataSyncEventType type,
                           void *userdata,
                           const GError *error)
{
	smlTrace(TRACE_ENTRY, "%s(%p, %p, %i, %p, %p)", __func__, session, dsObject, type, userdata, error);
	if (error)
		smlTrace(TRACE_INTERNAL, "%s: error ::= %s", __func__, GET_ERROR_MESSAGE(error));

	GError *locerror = NULL;
	
	switch (type) {
		case SML_DATA_SYNC_SESSION_EVENT_ERROR:
			sml_fail_unless(FALSE, "%s", GET_ERROR_MESSAGE(error));
			smlAssert(FALSE);
			break;
		case SML_DATA_SYNC_SESSION_EVENT_CONNECT:
		case SML_DATA_SYNC_SESSION_EVENT_DISCONNECT:
		case SML_DATA_SYNC_SESSION_EVENT_GOT_ALL_ALERTS:
		case SML_DATA_SYNC_SESSION_EVENT_GOT_ALL_MAPPINGS:
			break;
		case SML_DATA_SYNC_SESSION_EVENT_FINISHED:
			/* cleanup */
			break;
		case SML_DATA_SYNC_SESSION_EVENT_GOT_ALL_CHANGES:
			sml_fail_unless(session != NULL, "The session must be present on GOT_ALL_CHANGES event.");
			sml_fail_unless(
				sml_data_sync_session_send_changes(session, &locerror),
				"%s", GET_ERROR_MESSAGE(locerror));
			break;
		default:
			sml_fail_unless(FALSE, "The unexpected data sync event %d was received.", type);
			break;
	}
	smlTrace(TRACE_EXIT, "%s", __func__);
}

static gboolean
_recv_change (SmlDataSyncDataStoreSession *session,
              SmlDataSyncChangeItem *item,
              void *userdata,
              GError **error)
{
	smlTrace(TRACE_INTERNAL, "%s (%p, %p, %p, %p)", __func__, session, item, userdata, error);
	return TRUE;
}
	
SmlDataSync *dsObject = NULL;

void libsyncml_connect()
{
	smlTrace(TRACE_ENTRY, "%s", __func__);
	GError *error = NULL;

	dsObject = sml_data_sync_new();
	sml_fail_unless(dsObject != NULL, "Cannot create SmlDataSync object.", NULL);
	sml_fail_unless(sml_data_sync_set_transport_type(dsObject, tspType, &error), "%s", GET_ERROR_MESSAGE(error));
	sml_fail_unless(sml_data_sync_set_session_type(dsObject, SML_SESSION_TYPE_SERVER, &error), "%s", GET_ERROR_MESSAGE(error));

	switch(tspType)
	{
		case SML_TRANSPORT_OBEX_CLIENT:
			sml_fail_unless(
				sml_data_sync_set_option(
					dsObject,
					SML_DATA_SYNC_CONFIG_CONNECTION_TYPE,
					SML_DATA_SYNC_CONFIG_CONNECTION_NET,
					&error),
				"%s", GET_ERROR_MESSAGE(error));
			sml_fail_unless(
				sml_data_sync_set_option(
					dsObject,
					SML_TRANSPORT_CONFIG_PORT,
					obex_port, &error),
				"%s", GET_ERROR_MESSAGE(error));
			break;
		default:
			sml_fail_unless(FALSE, "The unsupported transport type %d was used for testing.", tspType);
	}

	sml_fail_unless(
		sml_data_sync_set_option(
			dsObject,
			SML_TRANSPORT_CONFIG_URL,
			"127.0.0.1", &error),
		"%s", GET_ERROR_MESSAGE(error));
	sml_fail_unless(
		sml_data_sync_set_option(
			dsObject,
			SML_DATA_SYNC_CONFIG_MAX_MSG_SIZE,
			maxMsgSize, &error),
		"%s", GET_ERROR_MESSAGE(error));
	sml_fail_unless(
		sml_data_sync_set_option(
			dsObject,
			SML_DATA_SYNC_CONFIG_MAX_OBJ_SIZE,
			maxObjSize, &error),
		"%s", GET_ERROR_MESSAGE(error));
	sml_fail_unless(
		sml_data_sync_set_option(
			dsObject,
			SML_DATA_SYNC_CONFIG_USE_WBXML,
			enableWbxml, &error),
		"%s", GET_ERROR_MESSAGE(error));
	sml_fail_unless(
		sml_data_sync_set_option(
			dsObject,
			SML_DATA_SYNC_CONFIG_IDENTIFIER,
			identifier, &error),
		"%s", GET_ERROR_MESSAGE(error));
	sml_fail_unless(
		sml_data_sync_set_option(
			dsObject,
			SML_DATA_SYNC_CONFIG_USE_TIMESTAMP_ANCHOR,
			useTimestamp, &error),
		"%s", GET_ERROR_MESSAGE(error));
	sml_fail_unless(
		sml_data_sync_set_option(
			dsObject,
			SML_DATA_SYNC_CONFIG_VERSION,
			"1.1", &error),
		"%s", GET_ERROR_MESSAGE(error));

	sml_data_sync_register_event_callback(dsObject, _libsyncml_event_callback, NULL);
	
	int i = 0;
	for (i = 0; locList[2*i] != NULL; i++)
	{
		SmlDataSyncDataStore *ds = sml_data_sync_data_store_new();
		sml_data_sync_data_store_set_content_type(ds, locList[2*i+1]);
		sml_data_sync_data_store_register_change_callback(ds, _recv_change, NULL);

		sml_data_sync_data_store_set_local_uri(ds, locList[2*i]);

		sml_fail_unless(sml_data_sync_add_data_store(dsObject, ds, &error), "%s", GET_ERROR_MESSAGE(error));
	}

	sml_fail_unless(sml_data_sync_initialize(dsObject, &error), "%s", GET_ERROR_MESSAGE(error));
	sml_fail_unless(error == NULL, "%s", GET_ERROR_MESSAGE(error));
	sml_fail_unless(sml_data_sync_run(dsObject, &error), "%s", GET_ERROR_MESSAGE(error));
	sml_fail_unless(error == NULL, "%s", GET_ERROR_MESSAGE(error));

	smlTrace(TRACE_EXIT, "%s", __func__);
}

void libsyncml_disconnect()
{
	g_object_unref(dsObject);
}
