/* GdkPixbuf library - JPEG2000 Image Loader
 *
 * Copyright © 2020 Nichlas Severinsen
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#ifndef UTIL_H
#define UTIL_H

#include <grok.h>

#define JP2_RFC3745_MAGIC "\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a"
#define JP2_MAGIC "\x0d\x0a\x87\x0a"
/* position 45: "\xff\x52" */
#define J2K_CODESTREAM_MAGIC "\xff\x4f\xff\x51"

typedef enum {
    UNKNOWN_FORMAT = 0,
	J2K_CFMT = 1,
	JP2_CFMT = 2,
} FORMAT;

/**
 * Identify what coded to use for input file.
 */
int util_identify(FILE *fp)
{
	int length;
	unsigned char buffer[12];

	memset(buffer, 0, 12);
	length = fread(buffer, 1, 12, fp);
	if(length != 12)
	{
		return -1;
	}
	fseek(fp, 0, SEEK_SET);

	if(memcmp(buffer, JP2_RFC3745_MAGIC, 12) == 0 || memcmp(buffer, JP2_MAGIC, 4) == 0)
	{
		return GRK_CODEC_JP2;
	}
	else if(memcmp(buffer, J2K_CODESTREAM_MAGIC, 4) == 0)
	{
		return GRK_CODEC_J2K;
	}

	// TODO: JPT? JPP? JPX? JPH?

	return -1;
}

/**
 * Create stream from file pointer.
 */
grk_stream* util_create_stream(FILE *fp)
{
    fseek(fp, 0L, SEEK_END);
    size_t sz = ftell(fp);
    fseek(fp, 0, SEEK_SET);
    guint8 *memoryBuffer = g_malloc(sizeof(guint8) * sz);
    size_t ret = fread(memoryBuffer, 1, sz, fp);
    fseek(fp, 0, SEEK_SET);

    if(ret == sz)
    {
        return grk_stream_create_mem_stream(memoryBuffer, sz, true, true);
    }

    return NULL;
}

/**
 * Destroy stream, codec, and image. As long as they aren't null pointers.
 */
void util_destroy(grk_stream* stream, grk_codec *codec, grk_image *image)
{
	if(stream != NULL)
	{
		grk_stream_destroy(stream);
	}
	if(codec != NULL)
	{
		grk_destroy_codec(codec);
	}
	if(image != NULL)
	{
		grk_image_destroy(image);
	}

    grk_deinitialize();
}

static void error_callback(const char *msg, void *client_data)
{
    (void) client_data;
    g_print("[ERROR] %s", msg);
}

static void warning_callback(const char *msg, void *client_data)
{
    (void) client_data;
    g_print("[WARNING] %s", msg);
}

static void info_callback(const char *msg, void *client_data)
{
    (void) client_data;
    g_print("[INFO] %s", msg);
}

#endif
