/*
 * Doom PostScript map generator. V1.1
 * Copyright James Bonfield, 3/3/94 
 *
 * Options:
 * -d		debugging - displays the wad directory
 * -w wadfile	select another wad file (default "doom.wad")
 * -l level	choose another level (default "E1M1")
 * -o		do not display objects
 * -m		do not display monsters
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include "wad.h"

/*
 * A4 paper is 8 1/4" by 11 3/4"
 * We allow 1/2" border.
 */
#define PAPER_X (72 * 8.25)
#define PAPER_Y (72 * 11.75)
#define PAPER_BORDER (72 * 0.5)

void doit(int fd, struct directory *dir, int size, char *lev_name,
	  int objs, int mons);

void dump_dir(struct directory *d, int size) {
    int i;

    for (i = 0; i < size; i++) {
	printf("Item=%5d, Start=%8d, Len=%8d, Name=%.8s\n",
	       i, d[i].start, d[i].length, d[i].name);
    }
}


void usage() {
    puts("wad [-w wadfile] [-d] [-o] [-m] [-l level]");
}

int main(int argc, char **argv) {
    struct directory *d;
    int fd, size, c;
    int objs=1, mons=1, dump=0;
    char *level = "E1M1";
    char *wadfile = "doom.wad";
    extern char *optarg;
    extern int optind;

    while ((c = getopt(argc, argv, "domw:l:")) != EOF) {
	switch (c) {
	case 'w': /* wad file */
	    wadfile = optarg;
	    break;
	case 'd': /* debug */
	    dump=1;
	    break;
	case 'l': /* select the level */
	    level = optarg;
	    break;
	case 'o': /* don't display objects */
	    objs=0;
	    break;
	case 'm': /* don't display monsters */
	    mons=0;
	    break;
	}
    }

    if (optind != argc) {
	usage();
	return 1;
    }

    if (NULL == (d = open_wad(wadfile, &fd, &size))) {
	fprintf(stderr, "Failed to open wad file.\n");
	return 1;
    }

    if (dump) {
	dump_dir(d, size);
	return 0;
    }

    doit(fd, d, size, level, objs, mons);
    
    return 0;
}

void doit(int fd, struct directory *dir, int size, char *lev_name,
	  int objs, int mons) {
    linedef *linedefs;
    vertex *vertexes;
    blockmap *blocks;
    sidedef *sidedefs;
    sector *sectors;
    thing *things;
    int numline, numvert, numblock, numside, numsect, numthing;
    int lev_index;
    int xorigin, yorigin, xsize, ysize;
    int2 sector;
    double xscale, yscale;
    int i, j;

    /* find level index */
    lev_index = get_index(dir, size, lev_name, 0);
    if (lev_index == 0) {
	fprintf(stderr, "Unknown level: %s\n", lev_name);
	exit(1);
    }

    /* load relevent arrays for this level */
    linedefs = read_linedefs(fd, dir, size, lev_index, &numline);
    vertexes = read_vertexes(fd, dir, size, lev_index, &numvert);
    blocks   = read_blockmap(fd, dir, size, lev_index, &numblock);
    sidedefs = read_sidedefs(fd, dir, size, lev_index, &numside);
    sectors  = read_sectors (fd, dir, size, lev_index, &numsect);
    things   = read_things  (fd, dir, size, lev_index, &numthing);

    /* calculate scaling info */
    xorigin = blocks[0];
    yorigin = blocks[1];
    xsize   = blocks[2] * 0x80;
    ysize   = blocks[3] * 0x80;

    xscale = (double)(PAPER_Y - 2*PAPER_BORDER)/xsize;
    yscale = (double)(PAPER_X - 2*PAPER_BORDER)/ysize;

    if (xscale > yscale)
	xscale = yscale;
    else
	yscale = xscale;

    /* output postscript header */
    printf("%%!\n");
    printf("newpath\n");
    printf("\n");
    printf("1 setlinecap\n");
    printf("%f %f translate\n", PAPER_BORDER, PAPER_Y - PAPER_BORDER);
    printf("-90 rotate\n");
    printf("%f %f scale\n", xscale, yscale);
    printf("%d %d translate\n", -xorigin, -yorigin);
    printf("%f setlinewidth\n", (double).5/xscale);
    printf("\n");
    printf("/l {\n");
    printf("    setgray setlinewidth moveto lineto stroke\n");
    printf("} def\n");
    printf("\n");
    printf("/a {\n");
    printf("    5 0 360 arc stroke\n");
    printf("} def\n");
    printf("\n");
    printf("/m {\n");
    printf("    gsave\n");
    printf("    moveto rotate\n");
    printf("    0 -13 rmoveto\n");
    printf("    0 25 rlineto\n");
    printf("    -10 -10 rlineto\n");
    printf("    10 10 rmoveto\n");
    printf("    10 -10 rlineto\n");
    printf("    stroke\n");
    printf("    grestore\n");
    printf("} def\n");

    /*
     * Display the walls.
     * Secret passages are done in grey.
     */
    for (i = 0; i < numline; i++) {
	sector = sidedefs[linedefs[i].sidedef1].sector;

	printf("%d %d %d %d ",
	       vertexes[linedefs[i].to_vertex].x,
	       vertexes[linedefs[i].to_vertex].y,
	       vertexes[linedefs[i].from_vertex].x,
	       vertexes[linedefs[i].from_vertex].y);
	
	if (linedefs[i].attrib & LI_IMPASS) {
	    printf("%f ", 1.2/xscale);
	} else {
	    printf("%f ", 0.5/xscale);
	}

	if (linedefs[i].attrib & LI_SECRET || sectors[sector].special == 9) {
	    printf(".5 l\n");
	} else {
	    printf("0 l\n");
	}
    }

    /*
     * Do we need to display objects or monsters?
     */
    if (objs || mons) {

	printf("    %d setlinewidth\n", 1/xscale);

	for (i = 0; i < numthing; i++) {

	    switch(things[i].type) {
		/* is this a monster? */
	    case 7: /* spider */
	    case 9: /* sergeant */
	    case 16: /* cyber */
	    case 58: /* invis */
	    case 3001: /* imp */
	    case 3002: /* demon */
	    case 3003: /* minotaur */
	    case 3004: /* human */
	    case 3005: /* cacodemon */
	    case 3006: /* skull */
		if (mons) {
		    printf("%d %d %d m\n",
			   things[i].angle, things[i].x, things[i].y);
		}
		break;
	    default:
		/* not a monster - so direction isn't important */
		if (objs) {
		    printf("%d %d a\n", things[i].x, things[i].y);
		}
	    }
	}
    }

    puts("showpage");

    return;
}
