#define	LIBQTOOLS_CORE
#define	LIBQBUILD_CORE
#include <libqtools.h>
#include <libqbuild.h>

struct memory bspStatic;
struct memory *bspMem = &bspStatic;

extern int bitbytes;						/* (num_visleafs+63)>>3 */
extern int bitlongs;
extern int c_chains;
extern int c_leafsee, c_portalsee;
extern int c_portalskip, c_leafskip;
extern int c_portaltest, c_portalpass, c_portalcheck;
extern int c_vistest, c_mighttest;
extern int count_sep;
extern int leafon;						/* the next leaf to be given to a thread to process */
extern int originalvismapsize;
extern int testvislevel;
extern int totalvis;
extern unsigned char *uncompressed;				/* [bitbytes*num_visleafs] */
extern unsigned char portalsee[MAX_MAP_PORTALS];

extern void CalcVis(__memBase);
extern void CalcAmbientSounds(__memBase);

/*
 * ===========
 * main
 * ===========
 */
int main(int argc, char **argv)
{
  char portalfile[NAMELEN_PATH];
  char source[NAMELEN_PATH];
  int i;
  HANDLE bspFile;
  int visOptions = 0;

  memset(bspMem, 0, sizeof(struct memory));

  if (!setjmp(eabort)) {
    mprintf("----- Vis ---------------\n");

    for (i = 1; i < argc; i++) {
      if (!strcmp(argv[i], "-fast")) {
	mprintf("fastvis = true\n");
	visOptions |= VIS_FAST;
      }
      else if (!strcmp(argv[i], "-level")) {
	testvislevel = atoi(argv[i + 1]);
	mprintf("testvislevel = %i\n", testvislevel);
	i++;
      }
      else if (!strcmp(argv[i], "-v")) {
	mprintf("verbose = true\n");
	visOptions |= VIS_VERBOSE;
      }
      else if (argv[i][0] == '-')
	Error("Unknown option \"%s\"", argv[i]);
      else
	break;
    }

    if (i != argc - 1)
      Error("usage: vis [-level 0-4] [-fast] [-v] bspfile");

    strcpy(source, argv[i]);
    ReplaceExt(source, "bsp");
    if ((bspFile = __open(source, H_READWRITE_BINARY_OLD)) > 0) {
      char *prtBuf;

      bspMem = LoadBSP(bspFile, ALL_QUAKE1_LUMPS & (~LUMP_VISIBILITY), BSP_VERSION_Q1);
      bspMem->visOptions = visOptions;
      AllocClusters(bspMem, LUMP_VISIBILITY);

      strcpy(portalfile, argv[i]);
      ReplaceExt(portalfile, "prt");

      prtBuf = (char *)GetVoid(portalfile);
      LoadPortals(prtBuf);
      tfree(prtBuf);

      originalvismapsize = num_visportals * ((num_visportals + 7) / 8);
      bitbytes = ((num_visportals + 63) & ~63) >> 3;
      bitlongs = bitbytes / sizeof(long);

      if (!(uncompressed = (char *)kmalloc(bitbytes * num_visleafs)))
	Error("Vis: failed to allocate bitbytes!\n");

/*    CalcPassages (); */
      CalcVis(bspMem);

      mprintf("%5i c_chains\n", c_chains);
      mprintf("%5i visdatasize (compressed from %i)\n", bspMem->shared.quake1.visdatasize, originalvismapsize);

      CalcAmbientSounds(bspMem);

      WriteBSP(bspFile, bspMem, BSP_VERSION_Q1);

      for (i = 0; i < num_visleafs; i++)
	if (leafs[i])
	  FreeLeaf(leafs[i]);
      for (i = 0; i < (num_visportals * 2); i++)
	if (portals[i].winding);
      FreeWinding(portals[i].winding);
      tfree(leafs);
      tfree(portals);
      kfree();

      FreeClusters(bspMem, 0);
      __close(bspFile);
    }
  }

  return 0;
}
