/*
 * libsyncml - A syncml protocol implementation
 * Copyright (C) 2008-2009  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
 *
 */

#ifndef _SML_DATA_SYNC_INTERNALS_H_
#define _SML_DATA_SYNC_INTERNALS_H_

#include <libsyncml/data_sync_api/standard.h>
#include <libsyncml/data_sync_api/callbacks.h>

#include <libsyncml/syncml_internals.h>
#include <libsyncml/sml_support.h>

#include <libsyncml/sml_session.h>
#include <libsyncml/sml_transport.h>
#include <libsyncml/objects/sml_auth.h>
#include <libsyncml/objects/sml_ds_server.h>
#include <libsyncml/objects/sml_devinf_obj.h>

#include <glib.h>

/* typedef for internal function pointers */

typedef SmlBool (* SmlFunctionDataSyncInit) (
			SmlDataSyncObject *dsObject,
			SmlError **error);
typedef SmlBool (* SmlFunctionDataSyncConnect) (
			SmlDataSyncObject *dsObject,
			SmlError **error);
typedef SmlBool (* SmlFunctionTransportInit) (
			SmlDataSyncObject *dsObject,
			SmlError **error);
typedef SmlBool (* SmlFunctionTransportConnect) (
			SmlDataSyncObject *dsObject,
			SmlError **error);

/*! @brief This is the internal representation of the OMA DS packages.
 * OMA DS specifications define packages which can consist
 * of several messages. Each package represents a state.
 * The packages 1 to 6 are defined in the standards.
 * The package 0 is the usual SAN package like known from
 * OMA DS 1.2. The other states are used if someone
 * sends a message which has not directly to do with
 * the synchronization and the message is not part of
 * package 1 to 6.
 *
 * */
typedef enum  {
	SML_PACKAGE_RECEIVED_UNKNOWN = -3,
	SML_PACKAGE_RECEIVED_DEVINF_REQUEST = -2, /* only DevInf was requested */
	SML_PACKAGE_RECEIVED_DEVINF = -1,         /* only DevInf was received */
	SML_PACKAGE_0 = 0, /* SAN */
	SML_PACKAGE_1 = 1, /* alerts from client */
	SML_PACKAGE_2 = 2, /* alerts from server */
	SML_PACKAGE_3 = 3, /* sync from client */
	SML_PACKAGE_4 = 4, /* sync from server */
	SML_PACKAGE_5 = 5, /* map from client */
	SML_PACKAGE_6 = 6, /* end from server */
	SML_PACKAGE_END = 7, /* client after end received from server */
} SmlDataSyncPackageType;

typedef enum {
	SML_DATA_SYNC_STATE_UNKNOWN = 0,
	SML_DATA_SYNC_STATE_NEW = 1,
	SML_DATA_SYNC_STATE_INITIALIZED = 2,
	SML_DATA_SYNC_STATE_CONNECTED = 3,
	SML_DATA_SYNC_STATE_SESSION_READY = 4,
	SML_DATA_SYNC_STATE_SENT_CHANGES = 5,
	SML_DATA_SYNC_STATE_DISCONNECT_IN_PROGRESS = 6,
	SML_DATA_SYNC_STATE_DISCONNECTED = 7,
} SmlDataSyncInternalStateType;

/* typedefs for internal objects */

/*! @brief This object represents an OMA DS datastore.
 */
typedef struct SmlDataSyncDatastore {
	SmlDataSyncObject *dsObject;
	void *syncChanges;
	void *syncContexts;
	char *sourceUri;
	char *targetUri;
	char *contentType;
	SmlDsServer *server;
	SmlDsSession *session;
	char *localNext;
	char *remoteNext;
	SmlAlertType alertType;
	GList *changes;
} SmlDataSyncDatastore;

/*! @brief This is the central synchronization object.
 */
struct SmlDataSyncObject {
	SmlSessionType dsType;
	SmlTransportType tspType;
	SmlTransportConnectionType conType;

	SmlManager *manager;
	SmlTransport *tsp;
	SmlAuthenticator *auth;
	SmlDevInf *localDevInf;
	SmlDevInf *remoteDevInf;
	SmlDevInfAgent *agent;
	SmlSession *session;

	GMutex *managerMutex;

	/* loop management */

	GSourceFuncs *functions;
	SmlThread *thread;
	GMainContext *context;
	GSource *source;

	/* config data */

	GList *datastores;

	SmlBool useNumberOfChanges;
	SmlBool useTimestampAnchor;
	SmlBool onlyLocaltime;
	SmlBool onlyReplace;
	SmlBool useStringTable;
	SmlBool useWbxml;
	unsigned int maxObjSize;
	unsigned int maxMsgSize;
	char *identifier;
	SmlAuthType authType;
	char *username;
	char *password;

	char *url;
	char *target;

	SmlProtocolVersion version;

	char *fakeDevice;
	char *fakeManufacturer;
	char *fakeModel;
	char *fakeSoftwareVersion;

	/* states */

	SmlDataSyncInternalStateType internalState;
	int refCount;
	SmlDataSyncPackageType actualPackage;
	
	/* callbacks */

	SmlDataSyncEventCallback eventCallback;
	void *eventUserdata;

	SmlDataSyncGetAlertTypeCallback getAlertTypeCallback;
	void *getAlertTypeUserdata;

	SmlDataSyncChangeCallback changeCallback;
	void *changeUserdata;

	SmlDataSyncChangeStatusCallback changeStatusCallback;

	SmlDataSyncMappingCallback mappingCallback;
	void *mappingUserdata;

	SmlDataSyncGetAnchorCallback getAnchorCallback;
	void *getAnchorUserdata;

	SmlDataSyncSetAnchorCallback setAnchorCallback;
	void *setAnchorUserdata;

	SmlDataSyncWriteDevInfCallback writeDevInfCallback;
	void *writeDevInfUserdata;

	SmlDataSyncReadDevInfCallback readDevInfCallback;
	void *readDevInfUserdata;

	SmlDataSyncHandleRemoteDevInfCallback handleRemoteDevInfCallback;
	void *handleRemoteDevInfUserdata;

	/* internal function pointers */

	SmlFunctionDataSyncInit funcDsInit;
	SmlFunctionDataSyncInit funcDsConnect;
	SmlFunctionTransportInit funcTspInit;
	SmlFunctionTransportConnect funcTspConnect;
	SmlDsSessionAlertCb funcDatastoreAlert;
};

/*! @brief This internal structure represents exactly one change.
 */
typedef struct SmlDataSyncChange {
	SmlDataSyncDatastore *datastore;
	SmlChangeType type;
	char *name;
	char *data;
	unsigned int size;
	void *userdata;
} SmlDataSyncChange;

void smlDataSyncSendEvent(
	SmlDataSyncObject *dsObject,
	SmlDataSyncEventType type,
	void *userdata,
	SmlError *error);

SmlBool smlDataSyncSendMap(
	SmlDataSyncObject *dsObject,
	SmlError **error);

#endif /* _SML_DATA_SYNC_INTERNALS_H_ */
