//	Hacked-together code for testing a triangulation's internal consistency.

#include "kernel.h"

void	CheckTriangulation(Triangulation *manifold);

void CheckTriangulation(Triangulation *manifold)
{
	Tetrahedron		*tet,
					*nbr;
	FaceIndex		f,
					nbr_f;
	VertexIndex		v,
					nbr_v;
	unsigned int	c,
					h,
					nbr_h;
	Permutation		this_gluing;
	char			scratch[512];

	//	Assign integer indices to the tetrahedra for reporting purposes.
	number_the_tetrahedra(manifold);
	
	//	Test neighbors and gluings.
	for (tet = manifold->tet_list_begin.next;
		 tet != &manifold->tet_list_end;
		 tet = tet->next)
	{
		for (f = 0; f < 4; f++)
		{
			this_gluing	= tet->gluing[f];
			nbr			= tet->neighbor[f];
			nbr_f		= EVALUATE(this_gluing, f);

			if (nbr->neighbor[nbr_f] != tet)
			{
				sprintf(scratch, "inconsistent neighbor data, tet %d face %d to tet %d face %d",
						tet->index, f, nbr->index, nbr_f);
				uAcknowledge(scratch);
				uFatalError("check_neighbors_and_gluings", "triangulations");
			}

			if (nbr->gluing[nbr_f] != inverse_permutation[this_gluing])
			{
				sprintf(scratch, "inconsistent gluing data, tet %d face %d to tet %d face %d",
						tet->index, f, nbr->index, nbr_f);
				uAcknowledge(scratch);
				uFatalError("check_neighbors_and_gluings", "triangulations");
			}
		}

		//	Test cusps and peripheral curves as well.
		//	JRW 2006/12/30
		for (v = 0; v < 4; v++)
		{
			for (f = 0; f < 4; f++)
			{
				if (f == v)
					continue;

				this_gluing	= tet->gluing[f];
				nbr			= tet->neighbor[f];
				nbr_v		= EVALUATE(this_gluing, v);
				nbr_f		= EVALUATE(this_gluing, f);
				
				if (tet->cusp[v] != nbr->cusp[nbr_v])
				{
					sprintf(scratch, "inconsistent cusp data, tet %d vertex %d to tet %d vertex %d",
							tet->index, v, nbr->index, nbr_v);
					uAcknowledge(scratch);
					uFatalError("check_neighbors_and_gluings", "triangulations");
				}
				
				for (c = 0; c < 1; c++)			//	meridian or longitude
					for (h = 0; h < 1; h++)		//	which sheet
					{
						switch (parity[this_gluing])
						{
							case 0:		//	even permutation, orientation-reversing  gluing
								nbr_h = ! h;
								break;

							case 1:		//	odd  permutation, orientation-preserving gluing
								nbr_h = h;
								break;
							
							default:
								uAcknowledge("invalid gluing");
								uFatalError("check_neighbors_and_gluings", "triangulations");
						}
						
						if (tet->curve[c][h][v][f] != - nbr->curve[c][nbr_h][nbr_v][nbr_f])
						{
							sprintf(
								scratch,
								"inconsistent %s:  tet %d vertex %d face %d sheet %d doesn't match tet %d vertex %d face %d sheet %d",
								c == M ? "meridian" : "longitude",
								tet->index,
								v,
								f,
								h,
								nbr->index,
								nbr_v,
								nbr_f,
								nbr_h);
							uAcknowledge(scratch);
							uFatalError("check_neighbors_and_gluings", "triangulations");
						}
					}
			}
		}
	}
	
	uAcknowledge("no problems detected\n");
}
