/*
 * 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/defines.h>
#include <libsyncml/data_sync_api/standard.h>
#include <libsyncml/data_sync_api/callbacks.h>

static void _libsyncml_event_callback(
			SmlDataSyncObject *dsObject,
			SmlDataSyncEventType type,
			void *userdata,
			SmlError *error)
{
	smlTrace(TRACE_ENTRY, "%s(%p, %i, %p, %p)", __func__, dsObject, type, userdata, error);
	
	switch (type) {
		case SML_DATA_SYNC_EVENT_ERROR:
			sml_fail_unless(FALSE, "%s", smlErrorPrint(&error));
			smlAssert(FALSE);
			break;
		case SML_DATA_SYNC_EVENT_CONNECT:
		case SML_DATA_SYNC_EVENT_DISCONNECT:
		case SML_DATA_SYNC_EVENT_GOT_ALL_ALERTS:
		case SML_DATA_SYNC_EVENT_GOT_ALL_MAPPINGS:
			break;
		case SML_DATA_SYNC_EVENT_FINISHED:
			/* cleanup */
			break;
		case SML_DATA_SYNC_EVENT_GOT_ALL_CHANGES:
			sml_fail_unless(
				smlDataSyncSendChanges(dsObject, &error),
				"%s", smlErrorPrint(&error));
			break;
		default:
			sml_fail_unless(FALSE, "The unexpected data sync event %d was received.", type);
			break;
	}
	smlTrace(TRACE_EXIT, "%s", __func__);
}

static SmlBool _recv_change(
			SmlDataSyncObject *dsObject,
			const char *source,
			SmlChangeType type,
			const char *uid,
			char *data,
			unsigned int size,
			void *userdata,
			SmlError **error)
{
	smlTrace(TRACE_INTERNAL, "%s: %s ==> %s (%p, %d, %p, %d, %p, %p)", __func__, VA_STRING(source), VA_STRING(uid), dsObject, type, data, size, userdata, error);
	smlSafeCFree(&data);
	return TRUE;
}
	
SmlDataSyncObject *dsObject = NULL;

void libsyncml_connect()
{
	SmlError *error = NULL;

	dsObject = smlDataSyncNew(
			SML_SESSION_TYPE_SERVER,
			tspType,
			&error);
	sml_fail_unless(dsObject != NULL, "%s", smlErrorPrint(&error));

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

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

	smlDataSyncRegisterEventCallback(dsObject, _libsyncml_event_callback, NULL);
	smlDataSyncRegisterChangeCallback(dsObject, _recv_change, NULL);
	
	int i = 0;
	for (i = 0; locList[2*i] != NULL; i++)
	{
		sml_fail_unless(
			smlDataSyncAddDatastore(
				dsObject,
				locList[2*i+1], /* content-type */
				NULL,
				locList[2*i], /* source */
				&error),
			"%s", smlErrorPrint(&error));
		sml_fail_unless(error == NULL, NULL);
	}

	sml_fail_unless(smlDataSyncInit(dsObject, &error), "%s", smlErrorPrint(&error));
	sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error));
	sml_fail_unless(smlDataSyncRun(dsObject, &error), "%s", smlErrorPrint(&error));
	sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error));
}

void libsyncml_disconnect()
{
	smlDataSyncObjectUnref(&dsObject);
}
