// vis.h

#define WIN32_LEAN_AND_MEAN
#define WIN32_EXTRA_LEAN
#include "windows.h"
#undef CopyFile // Conflicts with local function below
#include <stdio.h>

#define FEATURE_DETAIL
#ifdef FEATURE_DETAIL
  #define PORTALFILE2 "PRT1-AM"
#endif
#define FEATURE_BSP2
#define USE_CHECK_STACK
#define USE_PORTALOVERLAP

#include "cmdlib.h"
#include "mathlib.h"
#include "bspfile.h"

#define PORTALFILE      "PRT1"

#define ON_EPSILON      OnEpsilon

typedef struct {
	vec3_t normal;
	//float dist;
	vec_t dist;
} plane_t;

typedef struct {
	qboolean original; // don't free, it's part of the portal
	int numpoints;
	vec3_t points[ 8 ]; // variable sized
} winding_t;

#define MAX_POINTS_ON_WINDING	128	//64

winding_t *NewWinding( int points );
void FreeWinding( winding_t *w );
winding_t *ClipWinding( winding_t *in, plane_t *split, qboolean keepon );
winding_t *CopyWinding( winding_t *w );

typedef enum { stat_none, stat_working, stat_done } vstatus_t;
typedef struct {
	plane_t plane; // normal pointing into neighbor
	int leaf; // neighbor
	winding_t *winding;
	vstatus_t status;
	byte *visbits;
	byte *mightsee;
	int nummightsee;
	int numcansee;
} portal_t;

#define STATE_VERSION 1 // Update this when structs portals_t or state_t are changed in a way that is incompatible

#pragma pack(1)
typedef struct {
	byte numpoints;
	byte status;
	byte visbits;
	byte mightsee;
	int nummightsee;
	int numcansee;
} portals0_t; // Version 0

typedef struct {
	byte status;
	byte visbits;
	byte mightsee;
	unsigned short nummightsee;
	unsigned short numcansee;
} portals_t;

typedef struct {
	int Version;
	int portalleafs;
	int numportals;
	int BaseDone;
	int CalcDone;
	int CurrPortal;
	int PercRate;
	int visdist;
	int VDCutOff;
	int VDTotal;
	unsigned long c_chains;
	double BaseTime;
	double CalcTime;
	int testlevel;
	int HiResPercent;
	double StateTime;
	int numleafs;
	byte Extra[ 1024 - ( 13 * sizeof( int ) + sizeof( long ) + 3 * sizeof( double )) ];
} state_t;
#pragma pack()

typedef struct leaf_s {
	int numportals;
	portal_t **portals;
	#ifdef FEATURE_DETAIL
	int visofs;
	#endif
} leaf_t;

typedef struct pstack_s {
	#ifdef USE_CHECK_STACK
	struct pstack_s *next;
	#endif
	leaf_t *leaf;
	portal_t *portal; // portal exiting
	winding_t *source, *pass;
	plane_t portalplane;
	byte *mightsee; // bit string
} pstack_t;

typedef struct {
	byte *leafvis; // bit string
	portal_t *base;
	pstack_t pstack_head;
} threaddata_t;

#ifndef __alpha
extern HANDLE	read_mutex;
extern HANDLE	save_mutex;
  #define READ_LOCK       WaitForSingleObject( read_mutex, INFINITE )
  #define READ_UNLOCK     ReleaseMutex( read_mutex )
  #define SAVE_LOCK       WaitForSingleObject( save_mutex, INFINITE )
  #define SAVE_UNLOCK     ReleaseMutex( save_mutex )
#else
  #define LOCK
  #define UNLOCK
#endif

extern int	numportals;
extern int	portalleafs;

extern portal_t *portals;
extern leaf_t	*leafs;

extern int	c_portaltest, c_portalpass, c_portalcheck;
extern int	c_vistest, c_mighttest;
extern unsigned long c_chains;

extern byte *vismap, *vismap_p, *vismap_end; // past visfile

extern qboolean fastvis;
extern qboolean verbose;
extern qboolean NoAmbient;
extern qboolean NoAmbientLava;
extern qboolean NoAmbientSky;
extern qboolean NoAmbientSlime;
extern qboolean NoAmbientWater;
extern double OnEpsilon;

extern int	testlevel;
extern int	visdist;

extern byte	*uncompressed;
extern unsigned int	bitbytes;
extern unsigned int	bitlongs;
#ifdef FEATURE_DETAIL
extern unsigned int	bitbytes_l;
extern int	numrealleafs;
extern int	*leafcluster;
#endif

extern state_t State;

void LeafFlow( int leafnum );
void BasePortalVis( void );

void PortalFlow( portal_t *p );

void CalcAmbientSounds( void );
char *GetCoord( leaf_t *leaf );
void SaveState( char *source, int CurrPortal, qboolean Flush );

#ifdef FEATURE_BSP2
void CalcAmbientSoundsBSP2( void );
#endif