/*
 *  Copyright (c) 1994, Riley Rainey,  riley@netcon.com
 *
 *  Permission to use, copy, modify and distribute (without charge) this
 *  software, documentation, images, etc. is granted, provided that this 
 *  comment and the author's name is retained.
 *
 *  This software is provided by the author as is, and without any expressed
 *  or implied warranties, including, but not limited to, the implied
 *  warranties of merchantability and fitness for a particular purpose.  In no
 *  event shall the author be liable for any direct, indirect, incidental, or
 *  consequential damages arising in any way out of the use of this software.
 */

#include <X11/Xos.h>
#include <Xm/Xm.h>
#include <stdio.h>
#include <string.h>

#include "../util/memory.h"
#include "shared.h"
#include "gutil.h"
#include "gutil1.h"
#include "dialog.h"
#include "edit.h"

#define io_IMPORT
#include "io.h"

static char     magic_header[] = { 'R', 'R', '1', '1', 0, 0, 0, 1 };

#define REVISION        1


void
ClearWorkspace (Boolean redisplay)
{

	register int    i;

	for (i=sel_polygon; i >= 0; i = polygon_list[i].next)
		FreePolygon (&polygon_list[i]);

	sel_polygon = -1;

	for (i=unsel_polygon; i >= 0; i = polygon_list[i].next)
		FreePolygon (&polygon_list[i]);

	unsel_polygon = -1;

	if (cur_polygon != NULL)
		FreePolygon (cur_polygon);

	if (redisplay) {
		DrawWidget (twindow, False);
		DrawWidget (bwindow, False);
	}

	for (i=0; i<marker_count; ++i) {
		marker_list[i].defined = False;
	}

	clipboard_polygon = -1;
}

int
ReadGeditFile (char *name)
{
	FILE    *f;
	int     n;
	long    object_count, revision;
	char    magic[8];
	double  scale;

/*
 *  Is this a V library object?
 */
	
	n = strlen(name);
	if (n > 4 && strcmp(&name[n-4], ".obj") == 0) {
		return -1; // FIXME: handle error
	}

	if ((f = fopen (name, "r")) == (FILE *) NULL) {
		fprintf (stderr, "Unable to open %s\n", name);
		return -1;
	}

	ClearWorkspace (False);

	if (fread ((char *) magic, sizeof (magic), 1, f) != 1) {
		return -1; // FIXME: handle error
	}

	if (strncmp (magic, magic_header, 8) != 0) {
		gedit_error ("That file does not appear to be\n\
a gedit data file.  It cannot be\n\
edited by this program.");
		return -1;
	}

	if (fread ((char *) &revision, sizeof (revision), 1, f) != 1) {
		return -1; // FIXME: handle error
	}

	if (fread ((char *) &object_count, sizeof (object_count), 1, f) != 1) {
		return -1; // FIXME: handle error
	}

	if (fread ((char *) &scale, sizeof (scale), 1, f) != 1) {
		return -1; // FIXME: handle error
	}

	pixel_scale = scale;

	while (object_count-- > 0) {
		ReadObject (f);
	}

/*
 *  Now try to read markers
 */

	if (fread ((char *) &object_count, sizeof (object_count), 1, f) == 1) {
		while (object_count-- > 0) {
			ReadMarker (f);
		}
	}

/*
 *  Attempt to read the craft structure.
 */

	if (fread ((char *) &craft_name, sizeof (craft_name), 1, f) != 1) {
		return -1; // FIXME: handle error
	}
 
	if (fread ((char *) &c, sizeof (c), 1, f) == 1) {
		craft_valid = 1;
		c.name = craft_name;
		InitializeDialogs (&c);
	}

	fclose (f);

	DrawWidget (twindow, False);
	DrawWidget (bwindow, False);

	return 0;
}

int
ReadObject (FILE *f)
{

	polygon_t       poly, *p;
	view_info_t     *q;
	register int    i;

	fread ((char *) &poly, sizeof (poly), 1, f);

	XtVaGetValues (twindow,
		XmNuserData,    &q,
		NULL);

	p = AllocPolygon ();

	p->normal = poly.normal;
	p->origin = poly.origin;
	p->d = poly.d;
	p->num_points = poly.num_points;
	p->point = (point_t *) memory_allocate(poly.num_points * sizeof (point_t), NULL);

	fread ((char *) p->point, sizeof (point_t), poly.num_points, f);

	for (i=0; i < p->num_points; ++i)
		PointToXYZ (q, &p->point[i]);   

	p->next = unsel_polygon;
	unsel_polygon = p->id;

	return 0;
}

int
ReadMarker (FILE *f)
{

	marker_t        m;
	register int    i;

	fread ((char *) &m, sizeof (m), 1, f);

	for (i=0; i<marker_count; ++i) {
		if (m.id ==  marker_list[i].id){
			marker_list[i] = m;
			return 0;
		}
	}

	fprintf (stderr, "Can't seem to locate marker: \"%s\".\n", m.name);
	return -1;
}

int
WriteGeditFile (char *name)
{
	FILE    *f;
	long    revision = REVISION, object_count = 0;
	polygon_t *p;
	register int i;

	if ((f = fopen (name, "w")) == (FILE *) NULL) {
		return -1; // FIXME: handle error
	}

	if (fwrite ((char *) magic_header, 8, 1, f) != 1) {
		return -1; // FIXME: handle error
	}

	if (fwrite ((char *) &revision, sizeof (revision), 1, f) != 1) {
		return -1; // FIXME: handle error
	}

	for (i=sel_polygon; i >= 0; i = polygon_list[i].next) {
		p = &polygon_list[i];
		if (!(p->point[0].point.x == 0.0 &&
			p->point[0].point.y == 0.0 &&
			p->point[0].point.z == 0.0 &&
			p->point[1].point.x == 0.0 &&
			p->point[1].point.y == 0.0 &&
			p->point[1].point.z == 0.0))
				object_count ++;
	}

	for (i=unsel_polygon; i >= 0; i = polygon_list[i].next){
		p = &polygon_list[i];
		if (!(p->point[0].point.x == 0.0 &&
			p->point[0].point.y == 0.0 &&
			p->point[0].point.z == 0.0 &&
			p->point[1].point.x == 0.0 &&
			p->point[1].point.y == 0.0 &&
			p->point[1].point.z == 0.0))
				object_count ++;
	}

	if (fwrite ((char *) &object_count, sizeof (object_count), 1, f) != 1) {
		return -1; // FIXME: handle error
	}

	if (fwrite ((char *) &pixel_scale, sizeof (pixel_scale), 1, f) != 1) {
		return -1; // FIXME: handle error
	}

	for (i=sel_polygon; i >= 0; i = polygon_list[i].next)
		WriteObject (f, &polygon_list[i]);

	for (i=unsel_polygon; i >= 0; i = polygon_list[i].next)
		WriteObject (f, &polygon_list[i]);

	object_count = 0;
	for (i=0; i<marker_count; ++i) {
		if (marker_list[i].defined)
			object_count++;
	}

	if (fwrite ((char *) &object_count, sizeof (object_count), 1, f)
		!= 1) {
	}

	for (i=0; i<marker_count; ++i) {
		if (marker_list[i].defined)
			WriteMarker(f, &marker_list[i]);
	}
	
	if (fwrite ((char *) &craft_name, sizeof (craft_name), 1, f) != 1) {
		return -1; // FIXME: handle error
	}
	
	if (fwrite ((char *) &c, sizeof (c), 1, f) != 1) {
		return -1; // FIXME: handle error
	}

	fclose (f);

	return 0;
}

void
WriteObject (FILE *f, polygon_t *p)
{

/*
 *  A simple test to detect when we've got a poorly formed polygon
 */

	if (p->point[0].point.x == 0.0 &&
	    p->point[0].point.y == 0.0 &&
	    p->point[0].point.z == 0.0 &&
	    p->point[1].point.x == 0.0 &&
	    p->point[1].point.y == 0.0 &&
	    p->point[1].point.z == 0.0) {
		return;
	}

	fwrite ((char *) p, sizeof (polygon_t), 1, f);

	fwrite ((char *) p->point, sizeof (point_t), p->num_points, f); 

}

void
WriteMarker (FILE *f, marker_t *p)
{

	fwrite ((char *) p, sizeof (marker_t), 1, f);   

}

int
gedit_error (char *s)
{

	fprintf (stderr, s);
	return 0;
}

