/* Header for class jonah_base_JonahInterface */

#ifndef _Included_jonah_base_JonahInterface
#define _Included_jonah_base_JonahInterface

#include <jni.h>
#include "jonah_base_JonahInterface.h"
#include "jonah.h"

#define ObjStEECertReqActive              0x00010000lu
#define ObjStEECertReqPopPendingS         0x00020000lu
#define ObjStEECertReqPopPending          0x00030000lu
#define ObjStEECertReqSubmittedS          0x00040000lu
#define ObjStEECertReqRejected            0x00050000lu
#define ObjStEECertIssued                 0x00060000lu

#define ObjStRAPrereqS                    0x01010000lu
#define ObjStRACertReqPending             0x01020000lu
#define ObjStRACertReqPopPendingS         0x01030000lu
#define ObjStRACertReqActive              0x01040000lu
#define ObjStRACertReqRAApproved          0x01050000lu
#define ObjStRACertReqWaitingForCAS       0x01060000lu
#define ObjStRACertReqRejecting           0x01070000lu
#define ObjStRACertCAApproved             0x01080000lu
#define ObjStRACertCARejected             0x01090000lu

#define ObjStCACertReqActive              0x02010000lu
#define ObjStCACertSigned                 0x02020000lu
#define ObjStCACertReqRejected            0x02030000lu


#ifdef __cplusplus
extern "C" {
#endif


#include "pkiTask.h"

class msg_t;

class msgChan {
private:
  pki_mutex_t mutex;
  uint32 count;
  uint32 maxLength;
  msg_t * first;
  msg_t * last;
public:
  msgChan(uint32 maxMsgs = 0);           // Maximum queue length.  0 - infinite queuing
  ~msgChan();

  uint32 snd(uint32 d1, uint32 d2);   // Returns 0 for OK, 1 for no space left, 2 for internal error
  uint32 snd(uint32 d1, const utf8String str);   // Returns 0 for OK, 1 for no space left, 2 for internal error
  uint32 rcv(uint32 &d1, uint32 &d2); // Returns 0 for OK, 1 for no messages waiting, 2 for internal error
  uint32 rcv(uint32 &d1, utf8String &str); // Returns 0 for OK, 1 for no messages waiting, 2 for internal error
  
  uint32 msgsWaiting(void);
};




class msg_t {
public:
  msg_t * prev;
  msg_t * next;
  uint32 d1;
  uint32 d2;
  utf8String text;
  msg_t(msg_t * p, msg_t * n, uint32 v1, uint32 v2);
  msg_t(msg_t * p, msg_t * n, uint32 v1, const utf8String str);
  ~msg_t();
};

msg_t::msg_t(msg_t * p, msg_t * n, uint32 v1, uint32 v2) {
  prev = p;
  next = n;
  if (prev != NULL) prev->next = this;
  if (next != NULL) next->prev = this;
  text = NULL;
  d1 = v1;
  d2 = v2;
}

msg_t::msg_t(msg_t * p, msg_t * n, uint32 v1, const utf8String str) {
  prev = p;
  next = n;
  if (prev != NULL) prev->next = this;
  if (next != NULL) next->prev = this;
  text = NULL;
  d1 = v1;
  text = str;
}

msg_t::~msg_t() {
  if (prev != NULL) prev->next = next;
  if (next != NULL) next->prev = prev;
  if (text) JNH_release_utf8String(text);
  text = NULL;
}

msgChan::msgChan(uint32 queueLength) {
  mutex = PKI_MUTEX_INIT;
  pkiCreateMutex(&mutex, 0);
  count = 0;
  maxLength = queueLength;
  first = NULL;
  last = NULL;
}

msgChan::~msgChan() {
  msg_t * p;
  msg_t * pp;
  pkiLockMutex(&mutex);
  p = first;
  while (p) {
    pp = p->next;
    delete pp;
    p = pp;
  };
  count = 0;
  pkiUnlockMutex(&mutex);
}


uint32 msgChan::snd(uint32 d1, uint32 d2) {
  uint32 res = 0;
  pkiLockMutex(&mutex);
  try {
    if ((maxLength > 0) && (count >= maxLength)) {
		// No room in the queue
		res = 1; 
    } else if (last == NULL) {
		// First message in the queue
		last = new msg_t(NULL, NULL, d1, d2);
      first = last;
      count = 1;
    } else {
		// Second or greater message in queue
		last = new msg_t(last, NULL, d1, d2);
      count++;
    };
    pkiUnlockMutex(&mutex);
  }
  catch (...) {
    res = 2;
    pkiUnlockMutex(&mutex);
  };
  return res;
}

uint32 msgChan::rcv(uint32 &d1, uint32 &d2) {
  uint32 res = 0;
  msg_t * p;
  pkiLockMutex(&mutex);
  try {
    if (count == 0) {
      res = 1; // No messages waiting
    } else if (first == NULL) {
      res = 2; // Internal error
    } else {
      d1 = first->d1;    
      d2 = first->d2;    
      p = first->next;  
      delete first;
      first = p;
	  // extra code to check if removing last msg
	  if (first == NULL)
		  last = NULL;
      count--;
    };
  } catch(...) {
    pkiUnlockMutex(&mutex);
    res = 2;
  };
  pkiUnlockMutex(&mutex);
  return res;
}


uint32 msgChan::snd(uint32 d1, const utf8String str) {   // Returns 0 for OK, 1 for no space left, 2 for internal error
  uint32 res = 0;
  pkiLockMutex(&mutex);
  try {
    if ((maxLength > 0) && (count >= maxLength)) {
		// No room in the queue
		res = 1; 
    } else if (last == NULL) {
		// First message in the queue
		last = new msg_t(NULL, NULL, d1, str);
      first = last;
      count = 1;
    } else {
		// Second or greater message in queue
		last = new msg_t(last, NULL, d1, str);
      count++;
    };
    pkiUnlockMutex(&mutex);
  }
  catch (...) {
    res = 2;
    pkiUnlockMutex(&mutex);
  };
  return res;
}

uint32 msgChan::rcv(uint32 &d1, utf8String &str) { // Returns 0 for OK, 1 for no messages waiting, 2 for internal error
  uint32 res = 0;
  msg_t * p;
  pkiLockMutex(&mutex);
  try {
    if (count == 0) {
      res = 1; // No messages waiting
    } else if (first == NULL) {
      res = 2; // Internal error
    } else {
      d1 = first->d1;    
      str = first->text;
	  first->text = NULL;
      p = first->next;  
      delete first;
      first = p;
	  // extra code to check if removing last msg
	  if (first == NULL)
		  last = NULL;
      count--;
    };
  } catch(...) {
    pkiUnlockMutex(&mutex);
    res = 2;
  };
  pkiUnlockMutex(&mutex);
  return res;
}

uint32 msgChan::msgsWaiting(void) {
  uint32 res;
  pkiLockMutex(&mutex);
  res = count;
  pkiUnlockMutex(&mutex);
  return res;
}


static msgChan msg;
static msgChan logmsg;

/*
 * Method:    java_callback
 * Signature: 

	Used by Jonah Server Thread
    This routine will send message to the queue 
  Note:  
  
	File java\include\jni_md.h  #define JNICALL __stdcall
	File java\include\jni_md.h: #define JNIEXPORT __declspec(dllexport)
*/
void java_callback(uint32 eventId, 
                   uint32 eventStatus)
{
	msg.snd(eventId, eventStatus);
}

/*
 * Method:    java_logcallback
 * Signature: 

	Used by Jonah Server Thread
    This routine will send message to the queue 
*/
void java_logcallback(uint32 logCode, 
                const utf8String logMsg)
{
	logmsg.snd(logCode, logMsg);
}


/*
 * Class:     jonah_base_JonahInterface
 * Method:    Java_get_logmsg
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_Java_1get_1logmsg
  (JNIEnv * env, jobject obj)
{
	utf8String str = NULL;
	uint32 retValInt = 0;
	jclass cls = env->GetObjectClass( obj);
	jmethodID mid = env->GetMethodID( cls, "Java_sleep", "(I)V");
	if (mid == 0)
		return 0;
	while (1) {
		// If message is found in que breakout of while and return
		if (logmsg.rcv(retValInt, str) == 0) break;
		// Sleep for 10 second then check for message
		env->CallVoidMethod( obj,mid, 10000);
	};
	mid = env->GetMethodID( cls, "CallbackLogData", "(ILjava/lang/String;)V");
	if (mid == 0)
		return 0;

	jstring retValStr = env->NewStringUTF((char *)str);
	JNH_release_utf8String(str);
	env->CallVoidMethod( obj,mid, retValInt, retValStr);
//	env->SetIntField( clsStore, fHandle, objId);
//	env->SetIntField( clsStore, fState, objSt);
	return 0;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    Java_get_cmsg
 * Signature: (II)I
 * Interface: Java_get_cmsg(int objectHandle, int state);
 *			  Java_get_cmsg(Ostore  objectStore);

	Used by Java Notifiaction Thread
    This routine will retrieve message from the queue and 
	provide them to the Java Notification thread. A call to Java_sleep
	will call up to the Java Notifiaction thread's Java routine
	to have it pause reading from the queue

*/
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_Java_1get_1cmsg
  (JNIEnv * env, jobject obj, jobject jobjectStore)
{
	jclass clsStore = (env)->GetObjectClass(jobjectStore);
	jfieldID	fHandle;
	jfieldID	fState;
	uint32 objId;
	uint32 queobjSt;
	jclass cls = env->GetObjectClass( obj);

	fHandle = env->GetFieldID( clsStore, "objectHandle", "I");
	if (fHandle == 0)
		return 0;
	fState = env->GetFieldID( clsStore, "objectState", "I");
	if (fState == 0)
		return 0;
	
	jmethodID mid = env->GetMethodID( cls, "Java_sleep", "(I)V");
	if (mid == 0)
		return 0;
	while (1) {
		// If message is found in que breakout of while and return
		if (msg.rcv(objId, queobjSt) == 0) break;
		// Sleep for 1 second then check for message
		env->CallVoidMethod( obj,mid, 1000);
	};
	mid = env->GetMethodID( cls, "CallbackMainData", "(IJ)V");
	if (mid == 0)
		return 0;


	env->CallVoidMethod( obj,mid, objId, queobjSt);
	return 0;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_register_callbacks
 * Signature: ()I
 * Interface: JNH_register_callbacks(void)
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1register_1callbacks
  (JNIEnv *, jobject)
{
  uint32 retVal = JNH_register_callbacks(&java_callback,&java_logcallback);
  return retVal;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_register_callback
 * Signature: ()I
 * Interface: JNH_register_callback(void)
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1register_1callback
  (JNIEnv *env, jobject obj)
{
  uint32 retVal = JNH_register_callback(&java_callback);
  return retVal;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_start_server
 * Signature: (I)I
 * Interface: JNH_start_server(int serverType)
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1start_1server
  (JNIEnv *env, jobject obj, jint jserverType)
{
  uint32 retVal = JNH_start_server(jserverType);
  return retVal;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_list_objects
 * Signature: ()I
 * Interface: JNH_list_objects(void)
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1list_1objects
  (JNIEnv *env, jobject obj)
{
  uint32 retVal = JNH_list_objects();
  return retVal;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_INI_readString
 * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I
 * Interface: JNH_INI_readString(const utf8String section,
                          const utf8String key,
                          utf8String * value)
 */

/*1
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1INI_1readString
  (JNIEnv *env, jobject obj, jstring jsection, jstring jkey, jobject jvalue)
{
	jclass clsRetVal = (env)->GetObjectClass(jvalue);
	jfieldID	fRetInt;
	jfieldID	fRetStr;
	fRetInt = env->GetFieldID( clsRetVal, "retInt", "I");
	if (fRetInt == 0)
		return 0;
	fRetStr = env->GetFieldID( clsRetVal, "retStr", "Ljava/lang/String;");
	if (fRetStr == 0)
		return 0;
 //utf8String str_jvalue;
  char * str;
  const char * str_jsection = env->GetStringUTFChars( jsection, 0);
  const char * str_jkey = env->GetStringUTFChars( jkey, 0);

  str = NULL;// = env->GetStringUTFChars( jvalue, 0);

  uint32 retVal = JNH_INI_readString((unsigned char *const)str_jsection,
                          (unsigned char *const)str_jkey,
                          (unsigned char **)&str,
						  (unsigned char *const)"");

  jvalue = env->NewStringUTF(str);
//  jvalue = env->NewString((char *)str_jvalue, strlen((const char *)str_jvalue));
  JNH_release_utf8String((unsigned char *)str);
  env->ReleaseStringUTFChars( jsection, str_jsection);
  env->ReleaseStringUTFChars( jkey, str_jkey);
  
  //  env->ReleaseStringUTFChars( jvalue, str_jvalue);
  env->SetIntField( clsRetVal, fRetInt, retVal);
  env->SetObjectField( clsRetVal, fRetStr, jvalue);
  return 0;
} */
/*
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1INI_1readString
  (JNIEnv *env, jobject obj, jstring jsection, jstring jkey)
{
  jclass clsRetVal = (env)->GetObjectClass(obj);
  jfieldID fRetInt = env->GetFieldID( clsRetVal, "retInt1", "I");
  if (fRetInt == 0)
	return 0;
  jint intVal = env->GetIntField( clsRetVal, fRetInt);
  jfieldID  fRetStr = env->GetFieldID( clsRetVal, "retStr1", "Ljava/lang/String;");
  if (fRetStr == 0)
	return 0;

  char * str;
  const char * str_jsection = env->GetStringUTFChars( jsection, 0);
  const char * str_jkey = env->GetStringUTFChars( jkey, 0);

  str = NULL;// = env->GetStringUTFChars( jvalue, 0);

  uint32 retValInt = JNH_INI_readString((unsigned char *const)str_jsection,
                          (unsigned char *const)str_jkey,
                          (unsigned char **)&str,
						  (unsigned char *const)"");

  jstring retValStr = env->NewStringUTF(str);
  JNH_release_utf8String((unsigned char *)str);
  env->ReleaseStringUTFChars( jsection, str_jsection);
  env->ReleaseStringUTFChars( jkey, str_jkey);
  
  //  env->ReleaseStringUTFChars( jvalue, str_jvalue);
  env->SetIntField( clsRetVal, fRetInt, retValInt);
  env->SetObjectField( clsRetVal, fRetStr, retValStr);
  return 0;
}
*/
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1INI_1readString
  (JNIEnv *env, jobject obj, jstring jsection, jstring jkey)
{
  char * str;
  const char * str_jsection = env->GetStringUTFChars( jsection, 0);
  const char * str_jkey = env->GetStringUTFChars( jkey, 0);

  str = NULL;// = env->GetStringUTFChars( jvalue, 0);

  uint32 retValInt = JNH_INI_readString((unsigned char *const)str_jsection,
                          (unsigned char *const)str_jkey,
                          (unsigned char **)&str,
						  (unsigned char *const)"");

  jstring retValStr = env->NewStringUTF(str);
  JNH_release_utf8String((unsigned char *)str);
  env->ReleaseStringUTFChars( jsection, str_jsection);
  env->ReleaseStringUTFChars( jkey, str_jkey);
  
//  env->ReleaseStringUTFChars( jvalue, str_jvalue);
//  jObject = env->NewObject(clsRetVal,,);

  // Callback the result values to JAVA ReturnValues routine
  jclass	clsRetVal = (env)->GetObjectClass(obj);
  jmethodID	mid = env->GetMethodID(clsRetVal,"ReturnValues","(ILjava/lang/String;)V");
  if (mid == 0)
	return 0;
  env->CallVoidMethod(obj,mid,retValInt,retValStr);
  return retValInt;
}


/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_preregister_user
 * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)I
 * Interface: JNH_preregister_user(const utf8String CAname,
                            const utf8String RAname,
                            const octetString preregistrationRecord,
                            const utf8String passwd,
                            uint32 * reqId)
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1preregister_1user
  (JNIEnv *env, jobject obj, jstring jpreregistrationRecord, jstring jpasswd)
{
  const char * str_jpreregistrationRecord = env->GetStringUTFChars( jpreregistrationRecord, 0);
  const char * str_jpasswd = env->GetStringUTFChars( jpasswd, 0);
  uint32 int_reqId;

  uint32 retVal = JNH_preregister_user((unsigned char *const)str_jpreregistrationRecord,
                            (unsigned char *const)str_jpasswd,
                            &int_reqId);

  jint jreqId = int_reqId;
  env->ReleaseStringUTFChars( jpreregistrationRecord, str_jpreregistrationRecord);
  env->ReleaseStringUTFChars( jpasswd, str_jpasswd);

  
   // Callback the result values to JAVA ReturnValues routine
  jclass	clsRetVal = (env)->GetObjectClass(obj);
  jmethodID	mid = env->GetMethodID(clsRetVal,"ReturnValues","(I)V");
  if (mid == 0)
	return 0;
  env->CallVoidMethod(obj,mid,jreqId);
 return retVal;
}
/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_register_user
 * Signature: (I)I
 * Interface: JNH_register_user(uint32 reqId)
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1register_1user
  (JNIEnv *, jobject obj, jint jreqId)
{
  uint32 retVal = JNH_register_user(jreqId);
//  java_callback(1,4);
  return retVal;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_RA_pregegister_user
 * Signature: (Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)I
 * Interface: JNH_RA_pregegister_user(const utf8String CAname,
                               const utf8String username,
                               uint32 expirationSeconds,
                               const utf8String passwd,
                               octetString * preregistrationRecord)
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1RA_1preregister_1user
  (JNIEnv *env, jobject obj, jstring jCAname, jstring jusername, jint jexpirationSeconds,
   jstring jpasswd)
{
  const char * str_jCAname = env->GetStringUTFChars( jCAname, 0);
  const char * str_jusername = env->GetStringUTFChars( jusername, 0);
  const char * str_jpasswd = env->GetStringUTFChars( jpasswd, 0);
  char * str_jpreregistrationRecord;
  uint32 retVal = -1;
  retVal = JNH_RA_preregister_user((unsigned char *const)str_jCAname,
                               (unsigned char *const)str_jusername,
                               jexpirationSeconds,
                               (unsigned char *)str_jpasswd,
                               (unsigned char **)&str_jpreregistrationRecord);
  if (retVal != 0)
	  return retVal;
  jstring preregistrationRecord = env->NewStringUTF(str_jpreregistrationRecord);
//Mike Needs to`implement
//  JNH_release_utf8String((unsigned char *)str_jpreregistrationRecord);
  env->ReleaseStringUTFChars( jCAname, str_jCAname);
  env->ReleaseStringUTFChars( jusername, str_jusername);
  env->ReleaseStringUTFChars( jpasswd, str_jpasswd);

  // Callback the result values to JAVA ReturnValues routine
  jclass	clsRetVal = (env)->GetObjectClass(obj);
  jmethodID	mid = env->GetMethodID(clsRetVal,"ReturnValues","(ILjava/lang/String;)V");
  if (mid == 0)
	return 0;
  env->CallVoidMethod(obj,mid,retVal,preregistrationRecord);

  return retVal;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_Authorize_Registration
 * Signature: (II)I
 * Interface:  JNH_Authorize_Registration(uint32 reqId,
							uint32 keyId)
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1Authorize_1Registration
  (JNIEnv *env, jobject obj, jint jreqId, jint jkeyId)
{
  uint32 retVal = JNH_authorize_registration(jreqId, jkeyId);
  return retVal;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_Create_Certificate
 * Signature: (II)I
 * Interface: JNH_Create_Certificate(uint32 reqId,
							uint32 CAkeyId)
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1Create_1Certificate
  (JNIEnv *env, jobject obj, jint jreqId, jint jcaKeyId)
{
  uint32 retVal = JNH_create_certificate(jreqId, jcaKeyId);
  return retVal;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_Publish_Certificate
 * Signature: (I)I
 * Interface: JNH_Publish_Certificate(uint32 reqId)
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1Publish_1Certificate
  (JNIEnv *env, jobject obj, jint jreqId)
{
  uint32 retVal;// = JNH_publish_certificate(jreqId);
  return retVal;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_login_password
 * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;IZ)I
 * Interface: JNH_login_pwd(const utf8String user,
							const utf8String pwd,
							const utf8String device,
							uint32 keyVersion,
							const octetString algorithm,
							uint32 keySelector,
							IBOOL objectController,
							utf8String * fullname,
							uint32 * keyId)

 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1login_1password
				(JNIEnv *env, jobject obj, jstring juser, jstring jpwd, 
				jstring jdevice, jint jkeyVersion, jstring jalgorithm, 
				jint jkeySelector, jboolean jobjectController)
{
	uint32 retVal = -1;
	return retVal;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_login_key
 * Signature: (Ljava/lang/String;ILjava/lang/String;ILjava/lang/String;IZ)I
 * Interface: JNH_login_key(const utf8String user,
							uint32 storageKeyId,
							const utf8String device,
							uint32 keyVersion,
							const octetString algorithm,
							uint32 keySelector,
							IBOOL objectController,
							utf8String * fullname,
							uint32 * keyId)

 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1login_1key
  (JNIEnv *env, jobject obj, jstring juser, jint jstorageKeyId, jstring jdevice,
  jint jkeyVersion, jstring jalgorithm, jint jkeySelector, jboolean jobjectController)
{
  uint32 retVal = -1;
  return retVal;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_synch_object
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1synch_1object
  (JNIEnv *env, jobject obj, jint jreqId)
{
  uint32 retVal = JNH_save_object(jreqId);
  return retVal;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_reserve_object
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1reserve_1object
  (JNIEnv *env, jobject obj, jint jreqId)
{
  uint32 retVal = JNH_reserve_object(jreqId);
  return retVal;
}
/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_release_object
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1release_1object
  (JNIEnv *env, jobject obj, jint jreqId)
{
  uint32 retVal = JNH_release_object(jreqId);
  return retVal;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_reject_registration
 * Signature: (ILjava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1reject_1registration
  (JNIEnv *env, jobject obj, jint jreqId, jstring jmsg)
{
  const char * str_jmsg = env->GetStringUTFChars( jmsg, 0);
  uint32 retVal = JNH_reject_registration(jreqId,(unsigned char *const)str_jmsg);
  return retVal;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_get_error
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1get_1error
  (JNIEnv *env, jobject obj, jint jmsgId)
{
	char * msgstr = NULL;
	uint32 retVal = JNH_get_error(jmsgId, (unsigned char **)&msgstr);
	jstring retValStr = env->NewStringUTF(msgstr);
	JNH_release_utf8String((unsigned char *)msgstr);
//	jfieldID fretStr = (env)->GetFieldID( classJonahInterface, "retStr", "Ljava/lang/String;");
//    env->SetIntField( obj, fretStr, retValStr);
  // Callback the result values to JAVA ReturnValues routine
  jclass	clsRetVal = (env)->GetObjectClass(obj);
  jmethodID	mid = env->GetMethodID(clsRetVal,"ReturnValues","(ILjava/lang/String;)V");
  if (mid == 0)
	return 0;
  env->CallVoidMethod(obj,mid,retVal,retValStr);

  return retVal;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_delete_object
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1delete_1object
  (JNIEnv *env, jobject obj, jint jreqId)
{
	uint32 retVal = JNH_delete_object(jreqId);
	return retVal;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_validate_registration
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1validate_1registration
  (JNIEnv *env, jobject obj, jint jreqId)
{
	uint32 retVal = JNH_validate_registration(jreqId);
	return retVal;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_server_login_password
 * Signature: (Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1server_1login_1password
  (JNIEnv *env, jobject obj, jstring jpwd)
{
	uint32 retVal = -1;
	const char * str_jpasswd = env->GetStringUTFChars( jpwd, 0);
	retVal = JNH_server_login_pwd((unsigned char *const)str_jpasswd);
	env->ReleaseStringUTFChars( jpwd, str_jpasswd);
	return retVal;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_export_credential
 * Signature: (ILjava/lang/String;Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1export_1credential
  (JNIEnv *env, jobject obj, jint jreqId, jstring jpwd, jstring jdevice)
{
	uint32 retVal = -1;
	const char * str_jpwd = env->GetStringUTFChars( jpwd, 0);
	const char * str_jdevice = env->GetStringUTFChars( jdevice, 0);
    retVal = JNH_export_credential(jreqId, (unsigned char *const)str_jpwd,(unsigned char *const)str_jdevice);
	env->ReleaseStringUTFChars( jpwd, str_jpwd);
	env->ReleaseStringUTFChars( jdevice, str_jdevice);
	return retVal;
}

/* Check for null value and return */
#define NULL_CHECK(e) if ((e) == 0) return 0
/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_get_algorithms
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1get_1algorithms
  (JNIEnv *env, jobject obj, jint jalgType)
{
  uint32	retNumAlgs;
//  utf8String*  names = new utf8String[50];
  unsigned char  names[100][100] = {""};	
//  utf8String * names[250];
//  utf8String * names;
  uint32 retValInt = 0;
  jclass jcls;
  jobjectArray retArrayStr;
//  jstring retValStr = env->NewStringUTF(str);

  // Get number of algorithm string from backend
//  retValInt = JNH_get_algorithms(jalgType,&retNumAlgs,&names[0]);
  strcpy((char *)names[0],"id-dsa\0");
  retNumAlgs = 1;
//  retValInt = JNH_get_algorithms(jalgType,&retNumAlgs, (unsigned char ***)&names[0][0]);
  if (retValInt == 0) {
	// Convert array of C string to an array of Java Strings
    NULL_CHECK(jcls = env->FindClass("java/lang/String"));
	NULL_CHECK(retArrayStr = env->NewObjectArray(retNumAlgs,jcls, 0));
    for (int i = 0; i < retNumAlgs; i++) {
//		jstring jstr = env->NewStringUTF((const char*)names++);
		jstring jstr = env->NewStringUTF((const char*)names[i]);
		NULL_CHECK(jstr);
		env->SetObjectArrayElement(retArrayStr, i, jstr);
		env->DeleteLocalRef(jstr);
    }
	// pass array of Java Strings back to Jonah
    jclass	classJonahInterface = (env)->GetObjectClass(obj);
    jmethodID	mid = env->GetMethodID(classJonahInterface,"ReturnValues","(ILjava/lang/reflect/Array;)V");
//    jmethodID	mid = env->GetMethodID(classJonahInterface,"ReturnValues","(ILjava/lang/String;)V");
    if (mid == 0)
	  return 0;
    env->CallVoidMethod(obj,mid,retNumAlgs,retArrayStr);
  }
  return retValInt;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_get_algorithm_keylengths
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1get_1algorithm_1keylengths
  (JNIEnv *env, jobject obj, jstring jalgName)
{
  uint32	retValInt = 0;
  uint32	retNumKeys;
  unsigned char  keyLengths[50][10] = {""};	
  jclass jcls;
  jobjectArray retArrayStr;
  strcpy((char *)keyLengths[0],"512\0");
  strcpy((char *)keyLengths[1],"1024\0");
  retNumKeys = 2;
  if (retValInt == 0) {
	// Convert array of C string to an array of Java Strings
    NULL_CHECK(jcls = env->FindClass("java/lang/String"));
	NULL_CHECK(retArrayStr = env->NewObjectArray(retNumKeys,jcls, 0));
    for (int i = 0; i < retNumKeys; i++) {
		jstring jstr = env->NewStringUTF((const char*)keyLengths[i]);
		NULL_CHECK(jstr);
		env->SetObjectArrayElement(retArrayStr, i, jstr);
		env->DeleteLocalRef(jstr);
    }
	// pass array of Java Strings back to Jonah
    jclass	classJonahInterface = (env)->GetObjectClass(obj);
    jmethodID	mid = env->GetMethodID(classJonahInterface,"ReturnValues","(ILjava/lang/reflect/Array;)V");
    if (mid == 0)
	  return 0;
    env->CallVoidMethod(obj,mid,retNumKeys,retArrayStr);
  }
  return retValInt;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_inquire_certreq_subject
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1inquire_1certreq_1subject
  (JNIEnv *env, jobject obj, jint jreqId)
{
  uint32 retValInt = -1;
  char * str;
  str = NULL;
  retValInt = JNH_inquire_certreq_subject(jreqId,(unsigned char **)&str);
  if (retValInt == 0) {
	jstring retValStr = env->NewStringUTF(str);
	JNH_release_utf8String((unsigned char *)str);
    jclass	clsRetVal = (env)->GetObjectClass(obj);
    jmethodID	mid = env->GetMethodID(clsRetVal,"ReturnValues","(ILjava/lang/String;)V");
    if (mid == 0)
	  return 0;
    env->CallVoidMethod(obj,mid,retValInt,retValStr);
  }
  return retValInt;
}


/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_inquire_certreq_issuer
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1inquire_1certreq_1issuer
  (JNIEnv *env, jobject obj, jint jreqId)
{
  uint32 retValInt = -1;
  char * str;
  retValInt = JNH_inquire_certreq_issuer(jreqId,(unsigned char **)&str);
  if (retValInt == 0) {
    jstring retValStr = env->NewStringUTF(str);
    JNH_release_utf8String((unsigned char *)str);
    jclass	clsRetVal = (env)->GetObjectClass(obj);
    jmethodID	mid = env->GetMethodID(clsRetVal,"ReturnValues","(ILjava/lang/String;)V");
    if (mid == 0)
	  return 0;
    env->CallVoidMethod(obj,mid,retValInt,retValStr);
  }
  return retValInt;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_inquire_certreq_startdate
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1inquire_1certreq_1startdate
  (JNIEnv *env, jobject obj, jint jreqId)
//  (JNIEnv *env, jobject obj, jint jreqId, jobject objclass)
{
  uint32 retValInt = -1;
  utcDateTime  date;
  retValInt = JNH_inquire_certreq_startdate(jreqId, &date);
  if (retValInt == 0) {
	retValInt = 0;
//	date.year = 1964;
//	date.month = 7;
//	date.day = 7;
//	date.year = date.year - 1900;
    jclass	classJonahInterface = (env)->GetObjectClass(obj);
	jfieldID fYear = (env)->GetFieldID( classJonahInterface, "year", "I");
    env->SetIntField( obj, fYear, date.year);
	jfieldID fMonth = (env)->GetFieldID( classJonahInterface, "month", "I");
    env->SetIntField( obj, fMonth, date.month);
	jfieldID fDay = (env)->GetFieldID( classJonahInterface, "day", "I");
    env->SetIntField( obj, fDay, date.day);
  }
  return retValInt;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_inquire_certreq_enddate
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1inquire_1certreq_1enddate
  (JNIEnv *env, jobject obj, jint jreqId)
{
  uint32 retValInt = -1;
  utcDateTime  date;
  retValInt = JNH_inquire_certreq_enddate(jreqId, &date);
  if (retValInt == 0) {
	retValInt = 0;
//	date.year = 1994;
//	date.month = 11;
//	date.day = 25;
//	date.year = date.year - 1900;
    jclass	classJonahInterface = (env)->GetObjectClass(obj);
	jfieldID fYear = (env)->GetFieldID( classJonahInterface, "year", "I");
    env->SetIntField( obj, fYear, date.year);
	jfieldID fMonth = (env)->GetFieldID( classJonahInterface, "month", "I");
    env->SetIntField( obj, fMonth, date.month);
	jfieldID fDay = (env)->GetFieldID( classJonahInterface, "day", "I");
    env->SetIntField( obj, fDay, date.day);
  } 
  return retValInt;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_inquire_certreq_keyUsage
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1inquire_1certreq_1keyUsage
  (JNIEnv *env, jobject obj, jint jreqId)
{
  uint32 retValInt = -1;
  keyUsage_t	keyUsage;	
  retValInt = JNH_inquire_certreq_keyUsage(jreqId, &keyUsage);
  if (retValInt == 0) {
	jint jkeyUsage = keyUsage;
//	retValInt = 0;
//	jint jkeyUsage = 0x017el;
    jclass	classJonahInterface = (env)->GetObjectClass(obj);
	jfieldID fretInt = (env)->GetFieldID( classJonahInterface, "retInt", "I");
    env->SetIntField( obj, fretInt, jkeyUsage);
  }
  return retValInt;
}
/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_inquire_certreq_basicConstraints
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1inquire_1certreq_1basicConstraints
  (JNIEnv *env, jobject obj, jint jreqId)
{
  uint32 retValInt = -1;
  uint32	maxPathLen;
  IBOOL		isCaCert;
  retValInt = JNH_inquire_certreq_basicConstraints(jreqId, &isCaCert, &maxPathLen);
  if (retValInt == 0) {
	jint	  jmaxPathLen = maxPathLen;
	jboolean  jisCaCert = isCaCert;
	jclass	classJonahInterface = (env)->GetObjectClass(obj);
	jfieldID fretInt = (env)->GetFieldID( classJonahInterface, "retInt", "I");
	jfieldID fretBool = (env)->GetFieldID( classJonahInterface, "retBool", "Z");
    env->SetIntField( obj, fretInt, jmaxPathLen);
    env->SetBooleanField( obj, fretBool, jisCaCert);
  }
  return retValInt;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_inquire_certreq_privkey
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1inquire_1certreq_1privkey
  (JNIEnv *env, jobject obj, jint jreqId)
{
  uint32 retValInt = -1;
  uint32	privKey;
//  retValInt = JNH_inquire_certreq_privkey(jreqId, &privKey);
  if (retValInt == 0) {
	jint	  jprivKey = privKey;
	jclass	classJonahInterface = (env)->GetObjectClass(obj);
	jfieldID fretInt = (env)->GetFieldID( classJonahInterface, "retInt", "I");
    env->SetIntField( obj, fretInt, jprivKey);
   }
//  return retValInt;
  return 0;
}

  /*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_set_certreq_subject
 * Signature: (ILjava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1set_1certreq_1subject
  (JNIEnv *env, jobject obj, jint jreqId, jstring jsubject)
{
  const char * str_jsubject = env->GetStringUTFChars( jsubject, 0);
  uint32 retVal = -1;
  retVal = JNH_set_certreq_subject(jreqId,(unsigned char *const)str_jsubject);
  env->ReleaseStringUTFChars( jsubject, str_jsubject);
  return retVal;
}


/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_set_certreq_issuer
 * Signature: (ILjava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1set_1certreq_1issuer
  (JNIEnv *env, jobject obj, jint jreqId, jstring jissuer)
{
  const char * str_jissuer = env->GetStringUTFChars( jissuer, 0);
  uint32 retVal = -1;
  retVal = JNH_set_certreq_issuer(jreqId,(unsigned char *const)str_jissuer);
  env->ReleaseStringUTFChars( jissuer, str_jissuer);
  return retVal;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_set_certreq_startdate
 * Signature: (IJ)I
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1set_1certreq_1startdate
  (JNIEnv *env, jobject obj, jint jreqId, jint jyear, jint jmonth, jint jday )
{
  uint32 retValInt = -1;
  utcDateTime  date;
  date.year = jyear;
  date.month = jmonth;
  date.day = jday;
  date.hour = 0;
  date.min = 0;
  date.sec = 0;
  date.msec = 0;
  retValInt = JNH_set_certreq_startDate(jreqId, date);
  return retValInt;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_set_certreq_enddate
 * Signature: (IJ)I
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1set_1certreq_1enddate
  (JNIEnv *env, jobject obj, jint jreqId, jint jyear, jint jmonth, jint jday)
{
  uint32 retValInt = -1;
  utcDateTime  date;
  date.year = jyear;
  date.month = jmonth;
  date.day = jday;
  date.hour = 0;
  date.min = 0;
  date.sec = 0;
  date.msec = 0;
  retValInt = JNH_set_certreq_endDate(jreqId, date);
  return retValInt;
}
/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_set_certreq_keyUsage
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1set_1certreq_1keyUsage
  (JNIEnv *env, jobject obj, jint jreqId, jint  jkeyUsage)
{
  uint32 retValInt = -1;
  retValInt = JNH_set_certreq_keyUsage(jreqId,jkeyUsage);
  return retValInt;
}
/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_set_certreq_basicConstraints
 * Signature: (IZI)I
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1set_1certreq_1basicConstraints
  (JNIEnv *env, jobject obj, jint jreqId, jboolean jisCaCert, jint jmaxPathLen)
{
  uint32 retValInt = -1;
  retValInt = JNH_set_certreq_basicConstraints(jreqId,jisCaCert,jmaxPathLen);
  return retValInt;
}
/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_set_certreq_privkey_import
 * Signature: (Ljava/lang/String;Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1set_1certreq_1privkey_1import
  (JNIEnv *env, jobject obj, jint jreqId, jstring jfilename, jstring jpassword)
{
  const char * str_filename = env->GetStringUTFChars( jfilename, 0);
  const char * str_password = env->GetStringUTFChars( jpassword, 0);
  uint32 retValInt = -1;
  retValInt = JNH_set_certreq_privkey_import(jreqId,(unsigned char *const)str_filename,(unsigned char *const)str_password);
  env->ReleaseStringUTFChars( jfilename, str_filename);
  env->ReleaseStringUTFChars( jpassword, str_password);
  return retValInt;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_set_certreq_privkey_EE
 * Signature: (Ljava/lang/String;I)I
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1set_1certreq_1privkey_1EE
  (JNIEnv *env, jobject obj, jint jreqId, jstring jalgorithm, jint jkeylength)
{
  const char * str_algorithm = env->GetStringUTFChars(jalgorithm, 0);
  uint32 retValInt = -1;
  retValInt = JNH_set_certreq_privkey_EE(jreqId,(unsigned char *const)str_algorithm,jkeylength);
  env->ReleaseStringUTFChars( jalgorithm, str_algorithm);
  return retValInt;
}

/*
 * Class:     jonah_base_JonahInterface
 * Method:    JAVA_set_certreq_privkey_CA
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_jonah_base_JonahInterface_JAVA_1set_1certreq_1privkey_1CA
  (JNIEnv *env, jobject obj, jint jreqId)
{
  uint32 retValInt = -1;
  retValInt = JNH_set_certreq_privkey_CA(jreqId);
  return retValInt;
}

#ifdef __cplusplus
}
#endif
#endif