/* exif-content.c
 *
 * Copyright (c) 2001 Lutz Mueller <lutz@users.sourceforge.net>
 *
 * 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 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., 51 Franklin Street, Fifth Floor,
 * Boston, MA  02110-1301  USA.
 */

#include <config.h>

#include <libexif/exif-content.h>
#include <libexif/exif-system.h>

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

/* unused constant
 * static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
 */

struct _ExifContentPrivate
{
	unsigned int ref_count;

	ExifMem *mem;
	ExifLog *log;
};

ExifContent *
exif_content_new (void)
{
	ExifMem *mem = exif_mem_new_default ();
	ExifContent *content = exif_content_new_mem (mem);

	exif_mem_unref (mem);

	return content;
}

ExifContent *
exif_content_new_mem (ExifMem *mem)
{
	ExifContent *content;

	if (!mem) return NULL;

	content = exif_mem_alloc (mem, (ExifLong) sizeof (ExifContent));
	if (!content)
		return NULL;
	content->priv = exif_mem_alloc (mem,
				(ExifLong) sizeof (ExifContentPrivate));
	if (!content->priv) {
		exif_mem_free (mem, content);
		return NULL;
	}

	content->priv->ref_count = 1;

	content->priv->mem = mem;
	exif_mem_ref (mem);

	return content;
}

void
exif_content_ref (ExifContent *content)
{
	content->priv->ref_count++;
}

void
exif_content_unref (ExifContent *content)
{
	content->priv->ref_count--;
	if (!content->priv->ref_count)
		exif_content_free (content);
}

void
exif_content_free (ExifContent *content)
{
	ExifMem *mem = (content && content->priv) ? content->priv->mem : NULL;
	unsigned int i;

	if (!content) return;

	for (i = 0; i < content->count; i++)
		exif_entry_unref (content->entries[i]);
	exif_mem_free (mem, content->entries);

	if (content->priv) {
		exif_log_unref (content->priv->log);
	}

	exif_mem_free (mem, content->priv);
	exif_mem_free (mem, content);
	exif_mem_unref (mem);
}

void
exif_content_dump (ExifContent *content, unsigned int indent)
{
	char buf[1024];
	unsigned int i;

	for (i = 0; i < 2 * indent; i++)
		buf[i] = ' ';
	buf[i] = '\0';

	if (!content)
		return;

	printf ("%sDumping exif content (%u entries)...\n", buf,
		content->count);
	for (i = 0; i < content->count; i++)
		exif_entry_dump (content->entries[i], indent + 1);
}

void
exif_content_add_entry (ExifContent *c, ExifEntry *entry)
{
	ExifEntry **entries;
	if (!c || !c->priv || !entry || entry->parent) return;

	/* One tag can only be added once to an IFD. */
	if (exif_content_get_entry (c, entry->tag)) {
		exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "ExifContent",
			"An attempt has been made to add "
			"the tag '%s' twice to an IFD. This is against "
			"specification.", exif_tag_get_name (entry->tag));
		return;
	}

	entries = exif_mem_realloc (c->priv->mem,
		c->entries, sizeof (ExifEntry*) * (c->count + 1));
	if (!entries) return;
	entry->parent = c;
	entries[c->count++] = entry;
	c->entries = entries;
	exif_entry_ref (entry);
}

void
exif_content_remove_entry (ExifContent *c, ExifEntry *e)
{
	unsigned int i;
	ExifEntry **t, *temp;

	if (!c || !c->priv || !e || (e->parent != c)) return;

	/* Search the entry */
	for (i = 0; i < c->count; i++)
			if (c->entries[i] == e)
					break;

	if (i == c->count)
			return;

	/* Remove the entry */
	temp = c->entries[c->count-1];
	if (c->count > 1) {
		t = exif_mem_realloc (c->priv->mem, c->entries,
					sizeof(ExifEntry*) * (c->count - 1));
		if (!t) {
			return;
		}
		c->entries = t;
		c->count--;
		if (i != c->count) { /* we deallocated the last slot already */ 
			memmove (&t[i], &t[i + 1], sizeof (ExifEntry*) * (c->count - i - 1));
			t[c->count-1] = temp;
		} 
	} else {
		exif_mem_free (c->priv->mem, c->entries);
		c->entries = NULL;
		c->count = 0;
	}
	e->parent = NULL;
	exif_entry_unref (e);
}

ExifEntry *
exif_content_get_entry (ExifContent *content, ExifTag tag)
{
	unsigned int i;

	if (!content)
		return (NULL);

	for (i = 0; i < content->count; i++)
		if (content->entries[i]->tag == tag)
			return (content->entries[i]);
	return (NULL);
}

void
exif_content_foreach_entry (ExifContent *content,
			    ExifContentForeachEntryFunc func, void *data)
{
	unsigned int i;

	if (!content || !func)
		return;

	for (i = 0; i < content->count; i++)
		func (content->entries[i], data);
}

void
exif_content_log (ExifContent *content, ExifLog *log)
{
	if (!content || !content->priv || !log || content->priv->log == log)
		return;

	if (content->priv->log) exif_log_unref (content->priv->log);
	content->priv->log = log;
	exif_log_ref (log);
}

ExifIfd
exif_content_get_ifd (ExifContent *c)
{
	if (!c || !c->parent) return EXIF_IFD_COUNT;

	return 
		((c)->parent->ifd[EXIF_IFD_EXIF] == (c)) ? EXIF_IFD_EXIF :
		((c)->parent->ifd[EXIF_IFD_0] == (c)) ? EXIF_IFD_0 :
		((c)->parent->ifd[EXIF_IFD_1] == (c)) ? EXIF_IFD_1 :
		((c)->parent->ifd[EXIF_IFD_GPS] == (c)) ? EXIF_IFD_GPS :
		((c)->parent->ifd[EXIF_IFD_INTEROPERABILITY] == (c)) ? EXIF_IFD_INTEROPERABILITY :
		EXIF_IFD_COUNT;
}

static void
fix_func (ExifEntry *e, void *UNUSED(data))
{
	exif_entry_fix (e);
}

/*!
 * Check if this entry is unknown and if so, delete it.
 * \note Be careful calling this function in a loop. Deleting an entry from
 * an ExifContent changes the index of subsequent entries, as well as the
 * total size of the entries array.
 */
static void
remove_not_recorded (ExifEntry *e, void *UNUSED(data))
{
	ExifIfd ifd = exif_entry_get_ifd(e) ;
	ExifContent *c = e->parent;
	ExifDataType dt = exif_data_get_data_type (c->parent);
	ExifTag t = e->tag;

	if (exif_tag_get_support_level_in_ifd (t, ifd, dt) ==
			 EXIF_SUPPORT_LEVEL_NOT_RECORDED) {
		exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "exif-content",
				"Tag 0x%04x is not recorded in IFD '%s' and has therefore been "
				"removed.", t, exif_ifd_get_name (ifd));
		exif_content_remove_entry (c, e);
	}

}

void
exif_content_fix (ExifContent *c)
{
	ExifIfd ifd = exif_content_get_ifd (c);
	ExifDataType dt;
	ExifEntry *e;
	unsigned int i, num;

	if (!c)
		return;

	dt = exif_data_get_data_type (c->parent);

	/*
	 * First of all, fix all existing entries.
	 */
	exif_content_foreach_entry (c, fix_func, NULL);

	/*
	 * Go through each tag and if it's not recorded, remove it. If one
	 * is removed, exif_content_foreach_entry() will skip the next entry,
	 * so if this happens do the loop again from the beginning to ensure
	 * they're all checked. This could be avoided if we stop relying on
	 * exif_content_foreach_entry but loop intelligently here.
	 */
	do {
		num = c->count;
		exif_content_foreach_entry (c, remove_not_recorded, NULL);
	} while (num != c->count);

	/*
	 * Then check for non-existing mandatory tags and create them if needed
	 */
	num = exif_tag_table_count();
	for (i = 0; i < num; ++i) {
		const ExifTag t = exif_tag_table_get_tag (i);
		if (exif_tag_get_support_level_in_ifd (t, ifd, dt) ==
			EXIF_SUPPORT_LEVEL_MANDATORY) {
			if (exif_content_get_entry (c, t))
				/* This tag already exists */
				continue;
			exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "exif-content",
					"Tag '%s' is mandatory in IFD '%s' and has therefore been added.",
					exif_tag_get_name_in_ifd (t, ifd), exif_ifd_get_name (ifd));
			e = exif_entry_new ();
			exif_content_add_entry (c, e);
			exif_entry_initialize (e, t);
			exif_entry_unref (e);
		}
	}
}
