/*
			===== IDBSP - id Software's BSP builder for DOOM ====
	DOS port (c) 1994 Ron Rossbach (ej070@cleveland.freenet.edu)

	File: SAVESCTR.C
		Implements the functions which build the SECTORS resource.

	Revisions:

		1)	Add command line parameter ("-uniquesector") to control sector handling.
				If parameter is specified, id's original sector handling is enabled.
				Without the parameter (default), sectors are not touched.  (v1.1)
*/

#include "idbsp.h"

STORAGE 		*secdefstore_i;
STORAGE 		*sectorsavelist;

int         vertexsubcount[MAXVERTEX];
short       vertexsublist[MAXVERTEX][MAXTOUCHSECS];
int         subsectordef[MAXSUBSECTORS];
int         subsectornum[MAXSUBSECTORS];
int         buildsector;

/*
===============================================================================
=
= RecursiveGroupSector
=
===============================================================================
*/
void RecursiveGroupSubsector(int ssnum)
{
	int							i, l, count;
	int     				vertex;
	int      				checkss;
	short     			*vertsub;
	int       			vt;
	mapseg_t  			*seg;
	mapsubsector_t  *ss;
	maplinedef_t    *ld;
	mapsidedef_t    *sd;

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

	for (l=0 ; l<ss->numsegs ; l++)
		{
		seg = (mapseg_t *)maplinestore_i->data + ss->firstseg + l;
		ld = (maplinedef_t *)ldefstore_i->data + seg->linedef;
		DrawLineDef (ld);

		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];
			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("RecursiveGroupSubsector:"
									"regrouped (%d (subsectornum[%d]) != %d",
										subsectornum[checkss],checkss,buildsector);

					}
				}
			}
		}
}

/*
===============================================================================
=
= UniqueSector
=
===============================================================================
*/
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 (!memcmp(msp, &ms, sizeof(ms)))
			return i;

	memcpy((mapsector_t *)secdefstore_i->data + secdefstore_i->count, &ms,
						sizeof(mapsector_t));
	secdefstore_i->count += 1;
	secdefstore_i->data = (mapsector_t *)SafeRealloc(secdefstore_i->data,
							sizeof(mapsector_t) * (secdefstore_i->count + 1));

	return count;
}

/*
===============================================================================
=
= AddSubsectorToVertex
=
===============================================================================
*/
void AddSubsectorToVertex(int subnum, int vertex)
{
	int             j;

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

	vertexsublist[vertex][j] = subnum;
	vertexsubcount[vertex]++;
}

/*
===============================================================================
=
= BuildSectordefs
=
===============================================================================
*/
void BuildSectordefs(void)
{
	int               i;
	worldline_t				*wl;
	int               count;
	mapseg_t          *seg;
	mapsector_t 			ms;

/*
 build sectordef list
*/
	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);

	if (sectopt == 1)
		{
		count = linestore_i->count;
		wl = linestore_i->data;
		for (i=0 ; i<count ; i++, wl++)
			{
			wl->side[0].sector = UniqueSector(wl->side[0].sectordef);
			if (wl->flags & ML_TWOSIDED)
				{
				wl->side[1].sector = UniqueSector(wl->side[1].sectordef);
				}
			}
		}

	if (sectopt == 0)
		{
		for (i=0; i<sectorlistcount; i++)
			{
			ms.floorheight = sectorlist[i].floorheight;
			ms.ceilingheight = sectorlist[i].ceilingheight;
			memcpy (ms.floorpic,sectorlist[i].floorflat,8);
			memcpy (ms.ceilingpic,sectorlist[i].ceilingflat,8);
			ms.lightlevel = sectorlist[i].lightlevel;
			ms.special = sectorlist[i].special;
			ms.tag = sectorlist[i].tag;

			memcpy((mapsector_t *)secdefstore_i->data + secdefstore_i->count,
									&ms, sizeof(mapsector_t));
			secdefstore_i->count += 1;
			secdefstore_i->data = (mapsector_t *)SafeRealloc(secdefstore_i->data,
												sizeof(mapsector_t) * (secdefstore_i->count + 1));
			}
		}
}

/*
===============================================================================
=
= 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;
	int 						bs;

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

	printf("\n");
	for (i=0 ; i<numss ; 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 = (mapseg_t *)maplinestore_i->data + ss->firstseg + l;
			AddSubsectorToVertex (i, seg->v1);
			AddSubsectorToVertex (i, seg->v2);
			}
		subsectornum[i] = -1;   				/* ungrouped */
		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 *)SafeMalloc(sizeof(STORAGE));
	secstore_i->data = (mapsector_t *)SafeMalloc(sizeof(mapsector_t));
	secstore_i->count = 0;
	secstore_i->size = sizeof(mapsector_t);

	buildsector = 0;
	bs = 0;

/*
	IDEA!  The following loop builds the final sector list from the read-in
	sector list; the read-in list is checked for duplicates, but this loop
	does not check for duplicates!  In fact, it CREATES duplicates in the
	final list!

	Make secdefstore_i hold a list of sectordef_t (not mapsector_t).  Use
	sectoronlist field to track whether sector has been added to final list.  If
	so, find it and reference that number on the sidedef.
*/
  if (sectopt == 1)
  	for (i=0 ; i<numss ; i++)
	  	{
		  if (subsectornum[i] == -1)
			  {
			  EraseWindow ();
/*
			if (uniquesector)
				buildsector = bs;
			else
				buildsector = subsectordef[i];
*/

			  RecursiveGroupSubsector(i);
/*
			if (uniquesector)
				{
*/
				sec = *((mapsector_t *)secdefstore_i->data + subsectordef[i]);
				memcpy((mapsector_t *)secstore_i->data + secstore_i->count, &sec,
											sizeof(mapsector_t));
				secstore_i->count += 1;
				secstore_i->data = (mapsector_t *)SafeRealloc(secstore_i->data,
															sizeof(mapsector_t) * (secstore_i->count + 1));
				bs++;
        buildsector++;
/*
				}
*/
			}
		}

/*
	Use the following to simply copy the existing sectors to the final list
*/
/*
	secstore_i = (STORAGE *)SafeMalloc(sizeof(STORAGE));
	secstore_i->data = (mapsector_t *)SafeCalloc(secdefstore_i->count, sizeof(mapsector_t));
	secstore_i->count = secdefstore_i->count;
	secstore_i->size = sizeof(mapsector_t);
*/
	if (sectopt == 0)
		{
		secstore_i->count = secdefstore_i->count;
		memcpy((mapsector_t *)secstore_i->data, secdefstore_i->data,
								secdefstore_i->count * sizeof(mapsector_t));
		}

	sectorsavelist = (STORAGE *)SafeMalloc(sizeof(STORAGE));
	sectorsavelist->data = (mapsector_t *)SafeCalloc(secstore_i->count,
											sizeof(mapsector_t));
	sectorsavelist->count = secstore_i->count;
	sectorsavelist->size = sizeof(mapsector_t);

	memcpy((mapsector_t *)sectorsavelist->data, secstore_i->data,
					secstore_i->count * sizeof(mapsector_t));

}

