/*******************************************************************************
 * 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_Face
#define Face_cleanup			CLASSFN( CLASS, cleanup )
#define Face_isUnbounded		CLASSFN( CLASS, isUnbounded )
#define Face_getBoundingBox		CLASSFN( CLASS, getBoundingBox )
#define Face_isPointInside		CLASSFN( CLASS, isPointInside )
#define Face_getNumHalfedges	CLASSFN( CLASS, getNumHalfedges )
#define Face_getData			CLASSFN( CLASS, getData )
#define Face_setData			CLASSFN( CLASS, setData )


static Storage<Arrangement::Face> g_faces( CGALCLASS( "Face" ), false );


void facesCleanup( JNIEnv *jvm )
{
	g_faces.cleanupAll( jvm );
}

Arrangement::Face *getFace( JNIEnv *jvm, jobject self )
{
	return g_faces.get( jvm, self );
}

jobject newFace( JNIEnv *jvm, Arrangement::Face *pFace )
{
	return g_faces.addNew( jvm, pFace );
}

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

JNIEXPORT jboolean JNICALL Face_isUnbounded( JNIEnv *jvm, jobject self )
{
	START_SIGNAL_HANDLING
	{
		return getFace( jvm, self )->is_unbounded();
	}
	STOP_SIGNAL_HANDLING
	return false;
}

JNIEXPORT jobject JNICALL Face_getBoundingBox( JNIEnv *jvm, jobject self )
{
	START_SIGNAL_HANDLING
	{
		// init the box as a degenerate box
		Bbox_2 bbox;
		bool isDegenerate = true;

		// for each halfedge on the face...
		Arrangement::Face *pFace = getFace( jvm, self );
		Arrangement::Ccb_halfedge_circulator circ = pFace->outer_ccb();
		Arrangement::Ccb_halfedge_circulator circStart = circ;
		do
		{
			Arrangement::Halfedge halfedge = *circ;

			// get a bounding box for the curve
			Bbox_2 newBox = halfedge.curve().bbox();

			// "add" it to our bound
			if( isDegenerate )
			{
				bbox = newBox;
				isDegenerate = false;
			}
			else
			{
				bbox = bbox + newBox;
			}
		}
		while( ++circ != circStart );

		return newBox( jvm, bbox );
	}
	STOP_SIGNAL_HANDLING
	return NULL;
}

JNIEXPORT jint JNICALL Face_getNumHalfedges( JNIEnv *jvm, jobject self )
{
	int numHalfedges = 0;
	START_SIGNAL_HANDLING
	{
		Arrangement::Face *pFace = getFace( jvm, self );
		Arrangement::Ccb_halfedge_circulator circ = pFace->outer_ccb();
		Arrangement::Ccb_halfedge_circulator circStart = circ;
		do
		{
			numHalfedges++;
		}
		while( ++circ != circStart );
	}
	STOP_SIGNAL_HANDLING
	return numHalfedges;
}

JNIEXPORT jint JNICALL Face_getData( JNIEnv *jvm, jobject self )
{
	return getFace( jvm, self )->data();
}

JNIEXPORT void JNICALL Face_setData( JNIEnv *jvm, jobject self, jint data )
{
	getFace( jvm, self )->set_data( data );
}
