/* savebsp.m */

#include "idbsp.h"

/* id           secdefstore_i; */
STORAGE *secdefstore_i;

/*
#define         MAXVERTEX               8192
#define         MAXTOUCHSECS    16
#define         MAXSECTORS              2048
#define         MAXSUBSECTORS   2048
*/

int                     vertexsubcount[MAXVERTEX];
short           vertexsublist[MAXVERTEX][MAXTOUCHSECS];
/* short **vertexsublist; */

int                     subsectordef[MAXSUBSECTORS];
int                     subsectornum[MAXSUBSECTORS];

int                     buildsector;


/*
==========================
=
= RecursiveGroupSubsector
=
==========================
*/

void RecursiveGroupSubsector (int ssnum)
{
				int                             i, l, count;
				int                             vertex;
				int                             checkss;
				short                   *vertsub;
/*      short vertsub[MAXTOUCHSECS]; */

				int                             vt;
				mapseg_t                *seg;
				mapsubsector_t  *ss;
				maplinedef_t    *ld;
				mapsidedef_t    *sd;

/*      ss = [subsecstore_i elementAt:ssnum]; */
				ss = (mapsubsector_t *)subsecstore_i->data + ssnum;
				subsectornum[ssnum] = buildsector;

				for (l=0 ; l<ss->numsegs ; l++)
				{
/*
								seg = [maplinestore_i elementAt: ss->firstseg+l];
								ld = [ldefstore_i elementAt: seg->linedef];
*/
				 seg = (mapseg_t *)maplinestore_i->data + ss->firstseg + l;
				 ld = (maplinedef_t *)ldefstore_i->data + seg->linedef;
				 DrawLineDef (ld);
/*              sd = [sdefstore_i elementAt: ld->sidenum[seg->side]]; */
				 sd = (mapsidedef_t *)sdefstore_i->data + ld->sidenum[seg->side];
								sd->sector = buildsector;

								for (vt=0 ; vt<2 ; vt++)
								{
												if (vt)
																vertex = seg->v1;
												else
																vertex = seg->v2;

												vertsub = vertexsublist[vertex];
/*
												fseek(vertexsublist, vertex * MAXTOUCHSECS, SEEK_SET);
												fread(vertsub,sizeof(short),MAXTOUCHSECS,vertexsublist);
*/
												count = vertexsubcount[vertex];
												for (i=0 ; i<count ; i++)
												{
																checkss = vertsub[i];
																if (subsectordef[checkss] == subsectordef[ssnum])
																{
																				if (subsectornum[checkss] == -1)
																				{
																								RecursiveGroupSubsector (checkss);
																								continue;
																				}
																				if ( subsectornum[checkss] != buildsector)
																					/*      Error ("RecusiveGroup: regrouped a sector"); */
																								Error("RecursiveGroupSubsector: regrouped (%d (subsectornum[%d]) != %d",
																											subsectornum[checkss],checkss,buildsector);

																}
												}
								}
				}
}

/*
=================
=
= UniqueSector
=
= Returns the sector number, adding a new sector if needed
=================
*/

int UniqueSector (sectordef_t *def)
{
				int             i, count;
				mapsector_t             ms, *msp;

				ms.floorheight = def->floorheight;
				ms.ceilingheight = def->ceilingheight;
				memcpy (ms.floorpic,def->floorflat,8);
				memcpy (ms.ceilingpic,def->ceilingflat,8);
				ms.lightlevel = def->lightlevel;
				ms.special = def->special;
				ms.tag = def->tag;

/*
 see if an identical sector already exists
				count = [secdefstore_i count];
				msp = [secdefstore_i elementAt:0];
*/
				count = secdefstore_i->count;
				msp = (mapsector_t *)secdefstore_i->data;
				for (i=0 ; i<count ; i++, msp++)
/*
				 if (!bcmp(msp, &ms, sizeof(ms)))
								return i;
*/
								if (!memcmp(msp, &ms, sizeof(ms)))
												return i;

/*      [secdefstore_i addElement: &ms]; */
				memcpy((mapsector_t *)secdefstore_i->data + secdefstore_i->count, &ms, sizeof(mapsector_t));
				secdefstore_i->count += 1;
				secdefstore_i->data = (mapsector_t *)realloc(secdefstore_i->data,
																																sizeof(mapsector_t) * (secdefstore_i->count + 1));

				return count;
}




void AddSubsectorToVertex (int subnum, int vertex)
{
				int             j;
/*      short vsl[MAXTOUCHSECS]; */

				for (j=0 ; j< vertexsubcount[vertex] ; j++)
								if (vertexsublist[vertex][j] == subnum)
												return;
				vertexsublist[vertex][j] = subnum;
				vertexsubcount[vertex]++;
/*
				fseek(vertexsublist, vertex * MAXTOUCHSECS, SEEK_SET);
				fread(vsl,sizeof(short),MAXTOUCHSECS, vertexsublist);

				for (j=0;j<vertexsubcount[vertex];j++)
								if (vsl[j] == subnum)
												return

				vsl[j] = subnum;
				vertexsubcount[vertex]++;

				fseek(vertexsublist, -MAXTOUCHSECS, SEEK_CUR);
				fwrite(vsl,sizeof(short),MAXTOUCHSECS, vertexsublist);
*/
}


/*
================
=
= BuildSectordefs
=
= Call before ProcessNodes
================
*/

void BuildSectordefs (void)
{
				int                             i;
				worldline_t             *wl;
				int                             count;
				mapseg_t                *seg;

/*
 build sectordef list
*/
/*
				secdefstore_i = [[Storage alloc]
								initCount:              0
								elementSize:    sizeof(mapsector_t)
								description:    NULL];
*/

				secdefstore_i = (STORAGE *)SafeMalloc(sizeof(STORAGE));
				secdefstore_i->data = (mapsector_t *)SafeMalloc(sizeof(mapsector_t));
				secdefstore_i->count = 0;
				secdefstore_i->size = sizeof(mapsector_t);

/*
				count = [linestore_i count];
				wl= [linestore_i elementAt:0];
*/

				count = linestore_i->count;
				wl = linestore_i->data;
				for (i=0 ; i<count ; i++, wl++)
				{
/*
								seg = [maplinestore_i elementAt: i];
*/
/*                seg = (mapseg_t *)maplinestore_i->data + i; */
								wl->side[0].sector = UniqueSector(&wl->side[0].sectordef);
								if (wl->flags & ML_TWOSIDED)
								{
												wl->side[1].sector = UniqueSector(&wl->side[1].sectordef);
								}
				}
}


/*
================
=
= ProcessSectors
=
= Must be called after ProcessNodes, because it references the subsector list
================
*/

void ProcessSectors (void)
{
				int                             i,l;
				int                             numss;
				mapsubsector_t  *ss;
				mapsector_t             sec;
				mapseg_t                *seg;
				maplinedef_t    *ml;
				mapsidedef_t    *ms;

/*
 build a connection matrix that lists all the subsectors that touch
 each vertex
*/
				memset (vertexsubcount, 0, sizeof(vertexsubcount));
				memset (vertexsublist, 0, sizeof(vertexsublist));
/*      memset(vertexsublist, 0, MAXVERTEX * MAXTOUCHSECS); */
/*      numss = [subsecstore_i count]; */
				numss = subsecstore_i->count;

				printf("\n");
				for (i=0 ; i<numss ; i++)
				{
/*              ss = [subsecstore_i elementAt: i]; */
				 printf("Processing subsector #%d of %d\r",i,numss);
				 ss = (mapsubsector_t*)subsecstore_i->data + i;
								for (l=0 ; l<ss->numsegs ; l++)
								{
/*                      seg = [maplinestore_i elementAt: ss->firstseg+l]; */
								seg = (mapseg_t *)maplinestore_i->data + ss->firstseg + l;
												AddSubsectorToVertex (i, seg->v1);
												AddSubsectorToVertex (i, seg->v2);
								}
								subsectornum[i] = -1;           /* ungrouped */
/*
								ml = [ldefstore_i elementAt: seg->linedef];
								ms = [sdefstore_i elementAt: ml->sidenum[seg->side]];
*/
				 ml = (maplinedef_t *)ldefstore_i->data + seg->linedef;
				 ms = (mapsidedef_t *)sdefstore_i->data + ml->sidenum[seg->side];
								subsectordef[i] = ms->sector;
				}

/*
 recursively build final sectors
*/
/*
				secstore_i = [[Storage alloc]
								initCount:              0
								elementSize:    sizeof(mapsector_t)
								description:    NULL];
*/
				secstore_i = (STORAGE *)SafeMalloc(sizeof(STORAGE));
				secstore_i->data = (mapsector_t *)SafeMalloc(sizeof(mapsector_t));
				secstore_i->count = 0;
				secstore_i->size = sizeof(mapsector_t);

				buildsector = 0;
/*
				if (draw)
								PSsetgray (0);
*/
				for (i=0 ; i<numss ; i++)
				{
								if (subsectornum[i] == -1)
								{
								 EraseWindow ();
												RecursiveGroupSubsector (i);
								sec = *((mapsector_t *)secdefstore_i->data + subsectordef[i]);
/*                      sec = *(mapsector_t *)[secdefstore_i elementAt: subsectordef[i]]; */
/*                      [secstore_i addElement: &sec]; */
								memcpy((mapsector_t *)secstore_i->data + secstore_i->count, &sec, sizeof(mapsector_t));
								secstore_i->count += 1;
								secstore_i->data = (mapsector_t *)realloc(secstore_i->data,
																																sizeof(mapsector_t) * (secstore_i->count + 1));

												buildsector++;
								}
				}

}


