/*******************************************************************************
 * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA
 * 
 * Contact Info:
 * 	Bruce Donald
 * 	Duke University
 * 	Department of Computer Science
 * 	Levine Science Research Center (LSRC)
 * 	Durham
 * 	NC 27708-0129 
 * 	USA
 * 	brd@cs.duke.edu
 * 
 * Copyright (C) 2011 Jeffrey W. Martin and Bruce R. Donald
 * 
 * <signature of Bruce Donald>, April 2011
 * Bruce Donald, Professor of Computer Science
 ******************************************************************************/


#include <jni.h>

#include "cgal.h"
#include "shotCgal.h"
#include "global.h"
#include "types.h"
#include "Storage.h"


#define CLASS					Java_edu_duke_donaldLab_jdshot_disco_cgal_HoleIterator
#define HoleIterator_init		CLASSFN( CLASS, init )
#define HoleIterator_cleanup	CLASSFN( CLASS, cleanup )
#define HoleIterator_hasNext	CLASSFN( CLASS, hasNext )
#define HoleIterator_next		CLASSFN( CLASS, next )


static Storage<Arrangement::Hole_iterator> g_holeIterators( CGALCLASS( "HoleIterator" ), true );
static jclass g_holeIteratorClass;
static jfieldID g_holeIteratorFaceId;


void holeIteratorsCleanup( JNIEnv *jvm )
{
	g_holeIterators.cleanupAll( jvm );

	if( g_holeIteratorClass != NULL )
	{
		jvm->DeleteGlobalRef( g_holeIteratorClass );
		g_holeIteratorClass = NULL;
	}
}

Arrangement::Face *getFaceFromHoleIterator( JNIEnv *jvm, jobject self )
{
	// lookup meta info if needed
	if( g_holeIteratorClass == NULL )
	{
		g_holeIteratorClass = (jclass)jvm->NewGlobalRef( jvm->FindClass( CGALCLASS( "HoleIterator" ) ) );
	}
	if( g_holeIteratorFaceId == NULL )
	{
		g_holeIteratorFaceId = jvm->GetFieldID( g_holeIteratorClass, "m_face", "L" CGALCLASS( "Face" ) ";" );
		checkException( jvm );
	}

	jobject face = jvm->GetObjectField( self, g_holeIteratorFaceId );
	checkException( jvm );
	return getFace( jvm, face );
}

Arrangement::Hole_iterator *getHoleIterator( JNIEnv *jvm, jobject self )
{
	return g_holeIterators.get( jvm, self );
}


JNIEXPORT void JNICALL HoleIterator_init( JNIEnv *jvm, jobject self )
{
	START_SIGNAL_HANDLING
	{
		Arrangement::Face *pFace = getFaceFromHoleIterator( jvm, self );
		g_holeIterators.add( jvm, self, new Arrangement::Hole_iterator( pFace->holes_begin() ) );
	}
	STOP_SIGNAL_HANDLING
}

JNIEXPORT void JNICALL HoleIterator_cleanup( JNIEnv *jvm, jclass c, jint id )
{
	START_SIGNAL_HANDLING
	{
		if( !g_holeIterators.cleanup( id ) )
		{
			throwException( jvm, "HoleIterator cleanup failure!" );
		}
	}
	STOP_SIGNAL_HANDLING
}

JNIEXPORT jboolean JNICALL HoleIterator_hasNext( JNIEnv *jvm, jobject self )
{
	START_SIGNAL_HANDLING
	{
		Arrangement::Face *pFace = getFaceFromHoleIterator( jvm, self );
		Arrangement::Hole_iterator iter = *getHoleIterator( jvm, self );
		return iter != pFace->holes_end();
	}
	STOP_SIGNAL_HANDLING
	return false;
}

JNIEXPORT jobject JNICALL HoleIterator_next( JNIEnv *jvm, jobject self )
{
	START_SIGNAL_HANDLING
	{
		Arrangement::Hole_iterator *pIter = getHoleIterator( jvm, self );
		jobject hole = newHole( jvm, **pIter );
		(*pIter)++;

		return hole;
	}
	STOP_SIGNAL_HANDLING
	return NULL;
}
