/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/***************************************************************************
 *            camel-imapx-metadata.h
 *
 *  Mon Oct 11 12:43:03 2010
 *  Copyright  2010  Christian Hilberg
 *  <hilberg@kernelconcepts.de>
 ****************************************************************************/

/*
 * This program 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 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with main.c; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301,  USA
 */

/*----------------------------------------------------------------------------*/
/* ANNOTATEMORE / METADATA (RFC 5464) */

#ifndef _CAMEL_IMAPX_METADATA_H_
#define _CAMEL_IMAPX_METADATA_H_

/*----------------------------------------------------------------------------*/

#include <glib.h>
#include <gio/gio.h>

#include <libekolabutil/camel-system-headers.h>

#include "camel-imapx-stream.h"

/*----------------------------------------------------------------------------*/

/* ANNOTATEMORE vs. METADATA:
 *
 * ANNOTATEMORE [05]:
 * The value of a named entry can contain a multitude of attributes, each
 * with a .priv and .shared suffix, all stored in one entry string.
 *
 * METADATA:
 * Each named entry has a '/private' or '/shared' name prefix,
 * and a single value (string or binary) attached to them. This means there
 * are separate entries for shared and private annotations.
 *
 * Result:
 *
 *
 * Since METADATA allows for binary values, we need to take care that we
 * can handle NUL data bytes, hence the choice of GByteArray for values (which
 * needs to be stored as a blob in the metadata cache db).
 */

/*----------------------------------------------------------------------------*/

typedef enum {
	CAMEL_IMAPX_METADATA_ATTRIB_TYPE_UNSET = 0,
	CAMEL_IMAPX_METADATA_ATTRIB_TYPE_NIL,
	CAMEL_IMAPX_METADATA_ATTRIB_TYPE_UTF8,
	CAMEL_IMAPX_METADATA_ATTRIB_TYPE_BINARY,
	CAMEL_IMAPX_METADATA_ATTRIB_LAST_TYPE
} camel_imapx_metadata_attrib_type_t;

typedef enum {
	CAMEL_IMAPX_METADATA_ACCESS_PRIVATE = 0,
	CAMEL_IMAPX_METADATA_ACCESS_SHARED,
	CAMEL_IMAPX_METADATA_LAST_ACCESS
} camel_imapx_metadata_access_t;

typedef enum {
	CAMEL_IMAPX_METADATA_PROTO_INVAL = 0,
	CAMEL_IMAPX_METADATA_PROTO_ANNOTATEMORE,
	CAMEL_IMAPX_METADATA_PROTO_METADATA,
	CAMEL_IMAPX_METADATA_LAST_PROTO
} camel_imapx_metadata_proto_t;


typedef struct _CamelImapxMetadataSpec {
	camel_imapx_metadata_proto_t proto;
	gchar *mailbox_name;
	gchar *entry_name;
	gchar *attrib_name;
} CamelImapxMetadataSpec;

typedef struct _CamelImapxMetadataAttrib {
	/* attribute name kept as hash table key in CamelImapxMetaEntry */
	GByteArray *data[CAMEL_IMAPX_METADATA_LAST_ACCESS]; /* attribute data (UTF-8/Binary/NIL/unset) */
	camel_imapx_metadata_attrib_type_t type[CAMEL_IMAPX_METADATA_LAST_ACCESS]; /* type of data */
} CamelImapxMetadataAttrib;

typedef struct _CamelImapxMetadataEntry {
	/* entry name kept as hash table key in CamelImapxMetaAnnotation */
	GHashTable *attributes; /* for CamelImapxMetaAttribute */
} CamelImapxMetadataEntry;

typedef struct _CamelImapxMetadataAnnotation {
	/* annotation name kept as hash table key in CamelImapxMetaData */
	GHashTable *entries;
} CamelImapxMetadataAnnotation;

typedef struct _CamelImapxMetadata {
	camel_imapx_metadata_proto_t proto;
	GHashTable *mboxes;
	/* lock needed? */
	GMutex *md_lock;
} CamelImapxMetadata;

/*----------------------------------------------------------------------------*/
/* TODO check which of these can be made static */

CamelImapxMetadataAttrib*
camel_imapx_metadata_attrib_new (void);

void
camel_imapx_metadata_attrib_free (CamelImapxMetadataAttrib *ma);

CamelImapxMetadataEntry*
camel_imapx_metadata_entry_new (void);

void
camel_imapx_metadata_entry_free (CamelImapxMetadataEntry *me);

CamelImapxMetadataAnnotation*
camel_imapx_metadata_annotation_new (void);

void
camel_imapx_metadata_annotation_free (CamelImapxMetadataAnnotation *man);

CamelImapxMetadata*
camel_imapx_metadata_new (camel_imapx_metadata_proto_t proto,
                          gboolean locked);

CamelImapxMetadata*
camel_imapx_metadata_resect (CamelImapxMetadata **md);

void
camel_imapx_metadata_free (CamelImapxMetadata *md);

camel_imapx_metadata_proto_t
camel_imapx_metadata_get_proto (CamelImapxMetadata *md);

gboolean
camel_imapx_metadata_add_from_server_response (CamelImapxMetadata *md,
                                               CamelIMAPXStream *is,
                                               GCancellable *cancellable,
                                               GError**);

GSList*
camel_imapx_metadata_new_commandlist (const CamelImapxMetadata *md);

CamelImapxMetadataSpec*
camel_imapx_metadata_spec_new (camel_imapx_metadata_proto_t proto,
                               const gchar *mailbox_name,
                               const gchar *entry_name,
                               const gchar *attrib_name,
                               GError**);

void
camel_imapx_metadata_spec_free (CamelImapxMetadataSpec *spec);

CamelImapxMetadataAttrib*
camel_imapx_metadata_get_attrib_from_entry (CamelImapxMetadataEntry *me,
                                            CamelImapxMetadataSpec *spec);

CamelImapxMetadataAttrib*
camel_imapx_metadata_get_attrib_from_annotation (CamelImapxMetadataAnnotation *ma,
                                                 CamelImapxMetadataSpec *spec);

CamelImapxMetadataAttrib*
camel_imapx_metadata_get_attrib_from_metadata (CamelImapxMetadata *md,
                                               CamelImapxMetadataSpec *spec);

/*----------------------------------------------------------------------------*/

#endif /* _CAMEL_IMAPX_METADATA_H_ */

/*----------------------------------------------------------------------------*/
