
#ifndef _JL_GLOBALS_H_
#define _JL_GLOBALS_H_


#include "universal_threads.h"
#include "vec4.h"
class GlobalState;

extern const int GLOBAL_X_SIZE;
extern const int GLOBAL_Y_SIZE;

extern const int	DEFAULT_MAX_SUBD_LEVEL;
extern const float	DEFAULT_FOVEAL_SAMPLING;
extern const int	DEFAULT_NUM_RENDER_WORKERS;

extern const int        DEFAULT_DESIRED_NUM_PIXELS;
extern const real        DEFAULT_DESIRED_FRAME_RATE;

extern const int DEFAULT_HW_INTERP_CUTOFF; 
extern UNIV_SEMAHANDLE		global_sema_handle;

extern const int        NUM_FRAMES_REMEMBERED;

#define NO_INTERSECTION			1
#define PARTIAL_INTERSECTION	2
#define FULL_INTERSECTION		3

#define PLANE_LESS				-1
#define PLANE_ON				0
#define PLANE_GREATER			1

extern GlobalState * truly_GS;

typedef float RCFloat;

extern const float cell_color[3]; 
extern const float portal_color[3];
extern const float qr_color[3]; 
extern const float obj_color[3];
extern const float exit_pt_color[3];

struct Color {
  Vec4 diffuse;
  Vec4 ambient;
  Vec4 specular;
  real shininess;
};

class Counter {
  struct Count{
    int _size;
    int _num;
    Count *_next;
  } * _first;
  int _total;
  int _frame_id;
  int _num_sizes;

public:
  Counter (void) : _total(0), _first (NULL), _num_sizes (0) {}

  void Clear (void) {
    _total = 0;
    _num_sizes = 0;

    Count *cur = _first;
    Count *next;
    while (cur)
      {
	next = cur->_next;
	delete cur;
	cur = next;
      }
    _first = NULL;
  }

  void Update (int frameid) {
    if (frameid != _frame_id)
      {
	Clear();
	_frame_id = frameid;
      }
  }

  void Add (int frameid, int size) {

    Update (frameid);

    _total++;

    Count *cur = _first;
    Count *prev = NULL;
    while (cur)
      {
	if (cur->_size == size)
	  {
	    cur->_num++;
	    return;
	  }
	if (size > cur->_size)
	  break;

	prev = cur;
	cur = cur->_next;
      }

    _num_sizes++;
    Count *addme = new Count;
    addme->_num = 1;
    addme->_size = size;

    if (!prev)
      {
	if (_first)
	  addme->_next = _first;
	else
	  addme->_next = NULL;

      _first = addme;
      }
    else 
      {
	assert (prev->_next == cur);
	prev->_next = addme;
	addme->_next = cur;
      }
  };

  void print (char *name, int numbins = 0, int frameid = -1) {
    if (frameid != -1)
      Update (frameid);

    cout << name << ":" << _total << endl;

    Count *cur;

    int binsize = 0;
    if (numbins > 0)
      binsize = _num_sizes / numbins;

    int accum_bins = 0;
    int count = 0;
    int highest = 0;
    if (_first)
      highest = _first->_size;
    cur = _first;
    while (cur)
      {
	accum_bins ++;
	count += cur->_num;
	if (accum_bins > binsize || !cur->_next)
	  {
	    if (cur->_size != highest)
	      cout << "\t" << cur->_size << " to " << highest << ": " << count << endl;
	    else
	      cout << "\t" << cur->_size << ": " << count << endl;
	    accum_bins = 0;
	    count = 0;
	    if (cur->_next) highest = cur->_next->_size;
	  }
	cur = cur->_next;
      }
  }

  int Total (void) {return _total;}
  int Num (int size) {
    Count *cur = _first;
    while (cur)
      {
	if (cur->_size == size)
	  {
	    return cur->_num;
	  }
	cur = cur->_next;
      }
    return 0;
  }
};

extern const int MIN_HITS_BEFORE_GLED;
extern const int BAD_HIT_RATIO;
#endif
