/* doomload.m */
#include "idbsp.h"


int                 linenum = 0;
STORAGE            *linestore_i,
                   *thingstore_i;

/*
   =================
   =
   = ReadLine
   =
   =================
 */

/* worldline_t *ReadLine (FILE *file) */
worldline_t        *ReadLine(FILE * file, worldline_t * line)
{
/*      worldline_t     *line; */
	NXPoint            *p1,
	                   *p2;
	worldside_t        *s;
	sectordef_t        *e;
	int                 i;

/*      line = malloc(sizeof(worldline_t)); */
	memset(line, 0, sizeof(worldline_t));

	p1 = &line -> p1;
	p2 = &line -> p2;

	if (fscanf(file, "(%f,%f) to (%f,%f) : %d : %d : %d\n"
			,&p1 -> x, &p1 -> y, &p2 -> x, &p2 -> y, &line -> flags
			,&line -> special, &line -> tag) != 7)
		Error("Failed ReadLine");

	for (i = 0; i <= ((line -> flags & ML_TWOSIDED) != 0); i++)
		{
		s = &line -> side[i];
		if (fscanf(file, "    %d (%d : %s / %s / %s )\n"
				,&s -> firstrow, &s -> firstcollumn, s -> toptexture, s -> bottomtexture, s -> midtexture) != 5)
			Error("Failed ReadLine (side)");
		e = &s -> sectordef;
		if (fscanf(file, "    %d : %s %d : %s %d %d %d\n"
				,&e -> floorheight, e -> floorflat, &e -> ceilingheight
				,e -> ceilingflat, &e -> lightlevel, &e -> special, &e -> tag) != 7)
			Error("Failed ReadLine (sector)");
		if (!strcmp(e -> floorflat, "-"))
			printf("WARNING: line %i has no sectordef\n", linenum);
		}

	linenum++;

	return line;
}

/*
   =================
   =
   = ReadThing
   =
   =================
 */

/* worldthing_t *ReadThing (FILE *file) */
worldthing_t       *ReadThing(FILE * file, worldthing_t * thing)
{
	int                 x,
	                    y;

/*      worldthing_t    *thing; */

/*      thing = malloc(sizeof(*thing)); */
	memset(thing, 0, sizeof(*thing));

	if (fscanf(file, "(%i,%i, %d) :%d, %d\n"
			,&x, &y, &thing -> angle, &thing -> type, &thing -> options) != 5)
		Error("Failed ReadThing");

	thing -> origin.x = x & -16;
	thing -> origin.y = y & -16;

	return thing;
}

/*
   ==================
   =
   = LineOverlaid
   =
   = Check to see if the line is colinear and overlapping any previous lines
   ==================
 */

typedef struct
{
	float               left,
	                    right,
	                    top,
	                    bottom;
}

bbox_t;

void                BBoxFromPoints(bbox_t * box, NXPoint * p1, NXPoint * p2)
{
	if (p1 -> x < p2 -> x)
		{
		box -> left = p1 -> x;
		box -> right = p2 -> x;
		}
	else
		{
		box -> left = p2 -> x;
		box -> right = p1 -> x;
		}
	if (p1 -> y < p2 -> y)
		{
		box -> bottom = p1 -> y;
		box -> top = p2 -> y;
		}
	else
		{
		box -> bottom = p2 -> y;
		box -> top = p1 -> y;
		}
}

boolean             LineOverlaid(worldline_t * line)
{
	int                 j,
	                    count;
	worldline_t        *scan;
	divline_t           wl;
	bbox_t              linebox,
	                    scanbox;

	wl.pt = line -> p1;
	wl.dx = line -> p2.x - line -> p1.x;
	wl.dy = line -> p2.y - line -> p1.y;

/*
   count = [linestore_i count];
   scan = [linestore_i elementAt:0];
 */
	count = linestore_i -> count;
	scan = linestore_i -> data;

	for (j = 0; j < count; j++, scan++)
		{
		if (PointOnSide(&scan -> p1, &wl) != -1)
			continue;
		if (PointOnSide(&scan -> p2, &wl) != -1)
			continue;
/* line is colinear, see if it overlapps */
		BBoxFromPoints(&linebox, &line -> p1, &line -> p2);
		BBoxFromPoints(&scanbox, &scan -> p1, &scan -> p2);

		if (linebox.right > scanbox.left && linebox.left < scanbox.right)
			return true;
		if (linebox.bottom < scanbox.top && linebox.top > scanbox.bottom)
			return true;
		}
	return false;
}

/*
   ===================
   =
   = LoadDoomMap
   =
   ===================
 */

/* id   linestore_i, thingstore_i; */

/* void LoadDoomMap (char *mapname) */
void                LoadDoomMap(FILE * file)
{
/*      FILE            *file; */
/*              int                     i, version; */
	int                 i;
	int                 linecount,
	                    thingcount;
	worldline_t        *line;
	worldthing_t       *thing;

/*
   file = fopen (mapname,"r");
   if (!file)
   Error ("LoadDoomMap: couldn't open %s", mapname);
 */
/*
   if (!fscanf (file, "WorldServer version %d\n", &version) || version != 4)
   Error ("LoadDoomMap: not a version 4 doom map");
   printf ( "Loading version 4 doom map\n");
 */
/*
   read lines
 */
	if (fscanf(file, "\nlines:%d\n", &linecount) != 1)
		Error("LoadDoomMap: can't read linecount");
	printf("%i lines\n", linecount);
/*
   linestore_i = [[Storage alloc]
   initCount:              0
   elementSize:    sizeof(worldline_t)
   description:    NULL];
 */
	linestore_i = (STORAGE *) SafeMalloc(sizeof(STORAGE));
	linestore_i -> data = (worldline_t *) SafeCalloc(linecount, sizeof(worldline_t));
	linestore_i -> size = sizeof(worldline_t);
	linestore_i -> count = 0;

	line = linestore_i -> data;
	printf("\n");
	for (i = 0; i < linecount; i++, linestore_i -> count++, line++)
		{
/*              line = ReadLine (file); */
		printf("Reading line #%d\r", i);
		ReadLine(file, line);
		if (line -> p1.x == line -> p2.x && line -> p1.y == line -> p2.y)
			{
			printf("WARNING: line %i is length 0 (removed)\n", i);
			continue;
			}

		if (LineOverlaid(line))
			{
			printf("WARNING: line %i is overlaid (removed)\n", i);
			continue;
			}

/*
   [linestore_i addElement: line];
 */
/*
   linestore_i->count += 1;
   linestore_i->data = (worldline_t *)realloc(linestore_i->data,
   sizeof(worldline_t) * (linestore_i->count + 1));
   line = (worldline_t *)linestore_i->data + linestore_i->count;
 */
		}

/*
   read things
 */
	if (fscanf(file, "\nthings:%d\n", &thingcount) != 1)
		Error("LoadDoomMap: can't read thingcount");
	printf("\n\n%i things\n", thingcount);
/*
   thingstore_i = [[Storage alloc]
   initCount:              0
   elementSize:    sizeof(worldthing_t)
   description:    NULL];
 */
	thingstore_i = (STORAGE *) SafeMalloc(sizeof(STORAGE));
	thingstore_i -> data = (worldthing_t *) SafeCalloc(thingcount, sizeof(worldthing_t));
	thingstore_i -> size = sizeof(worldthing_t);
	thingstore_i -> count = thingcount;
/*
   for (i=0 ; i<thingcount ; i++)
   [thingstore_i addElement: ReadThing (file)];
 */
	thing = thingstore_i -> data;
	for (i = 0; i < thingcount; i++)
		{
		printf("Reading thing #%d\r", i);
		ReadThing(file, thing);
		thing++;
		}
/*
   fclose (file);
 */
}
