/*
 * BindingsUtil.c
 *
 * Copyright (c) 2007  Vreixo Formoso
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * See COPYING file for details.
 */

#include "BindingsUtil.h"

#define JAVA_LIBBURN_JNI_VERSION JNI_VERSION_1_4

static JavaVM*	cachedJavaVM;

JNIEXPORT jint JNICALL
JNI_OnLoad
(
	JavaVM *jvm,
	void *reserved
)
{
	if (jvm == NULL) {
		perror("null JavaVM pointer");
	}
 	cachedJavaVM = jvm;
 	return JAVA_LIBBURN_JNI_VERSION;
}

/**
 * Creates a new TocEntry java class from a burn_toc_entry C struct
 */
jobject java_libburn_toc_entry_c2java
(
	JNIEnv *env, struct burn_toc_entry *entry
)
{
	static jclass tocEntryCls = NULL;
	static jmethodID cid = NULL;
	jobject result;

	if ( tocEntryCls == NULL ) {
		tocEntryCls = (*env)->FindClass(env, "org/pykix/libburnia/libburn/TocEntry");
		if ( tocEntryCls == NULL ) {
			return NULL;
		}
	}

	if ( cid == NULL ) {
		cid = (*env)->GetMethodID(env, tocEntryCls, "<init>", "(BBBBBBBBBBBBBBBII)V");
		if (cid == NULL) {
		    return NULL; /* exception thrown */
		}
	}

	result = (*env)->NewObject(env, tocEntryCls, cid, entry->session, entry->adr, entry->control, 
		entry->tno, entry->point, entry->min, entry->sec, entry->frame, entry->zero, entry->pmin, 
		entry->psec, entry->pframe, entry->extensions_valid, entry->session_msb, 
		entry->point_msb, entry->start_lba, entry->track_blocks);

	return result;
}


void java_libburn_throw_burn_exception
(
	JNIEnv *env, const char *msg
)
{
	static jclass cls = NULL; 

	if ( cls == NULL) {
		 cls = (*env)->FindClass(env, "org/pykix/libburnia/libburn/BurnException");
	}
	(*env)->ThrowNew(env, cls, msg);
}

jclass java_libburn_find_class
(
	JNIEnv *env, const char *name
)
{
	jclass localRefCls = (*env)->FindClass(env, name);
	if (localRefCls == NULL) {
	    return NULL; /* exception thrown */
	}
	
	jclass globalRef = (*env)->NewWeakGlobalRef(env, localRefCls);

	(*env)->DeleteLocalRef(env, localRefCls);

	return globalRef; //can be NULL on error, need to be checked!!
}

JNIEnv* java_libburn_get_env()
{
	JNIEnv* env;
	jint result;

	result = (*cachedJavaVM)->GetEnv(cachedJavaVM, (void **) &env, JAVA_LIBBURN_JNI_VERSION);
	if ( result != JNI_OK) {
		switch (result) {
		case JNI_EDETACHED:
			perror("[DEBUG] Current thread is not attached. Attaching...");

			JavaVMAttachArgs args;
			args.version = JAVA_LIBBURN_JNI_VERSION;
			args.name = "Signal handler callback";
			args.group = NULL;
			(*cachedJavaVM)->AttachCurrentThread(cachedJavaVM, (void **)&env, &args);
			return env;
			break;
		case JNI_EVERSION:
			g_error("Specified version is not supported.");
			break;
		}
		return NULL;
	}
	return env;
}
