#include "../include/zf.h"

#define HUD_MESSAGE_LIFESPAN 200
#define SHIP_LIFE_ROTATE_INC 1.0f
#define BOSS_TIME_COUNTER_START 500
#define BOSS_BOMB_TO_FLUX_END_BUFFER 12.0f

static float hud_energy;
static float hud_speed;
static float hud_angle;
static unsigned int hud_score;
static unsigned int high_score;

static CLimage* image;
static CLcontext* context;
static CLmodel* ship_model;
static float ship_life_rotate;

static int boss_mode;  /* 0 - off, 1 - on and couting, 2 - on and stopped (ie, when boss is dying)*/
static float boss_time;  /* how much flux time you have to beat boss */
static int boss_counter; /* how much counter time you have to beat boss - need to stop counter when boss dead*/

/*static ZfAudioSample* hud_sound;*/

static ZfSmartPointer smart_pointer;
static ZfSmartPointer msg_smart_pointer;

struct ZfHudMessage
{
    unsigned int ref_count;
    char* message;
    CLvertex position;
    float flux_t;
    bool activated; /* for type 1 only */

    int type;  /* 0 - pause type,
		  1 - just displays while running game 
	          2 - overlayed on game, only disappear when key pressed*/
    int age;
};

void
animate(void* some_amusing_name)
{
    /* rotate a bit */
    hud_angle++;
}

void
render_axis(float size)
{
    glBegin(GL_LINES);
    glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
    glVertex3f(0.0f, 0.0f, 0.0f);
    glVertex3f(size, 0.0f, 0.0f);

    glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
    glVertex3f(0.0f, 0.0f, 0.0f);
    glVertex3f(0.0f, size, 0.0f);

    glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
    glVertex3f(0.0f, 0.0f, 0.0f);
    glVertex3f(0.0f, 0.0f, size);
    glEnd();
}



static void
render_weapon_meter(float ship_power,
		    float flux_power)
{
    unsigned int i;
    char stock_left[3];

    glPushMatrix();
    glLoadIdentity();

    glTranslatef(0.0f, 1.0f, -7.0f);

    //render_axis(10.0f);

    for (i = 0; i < 16; i++)
    {
	static float angle = 0.0f;
	static float taper = 0.9f * ((2.0f * CL_PI) / 16.0f) / 2.0f;

	if ((float)i / 16 < flux_power)
	    glColor4f(0.5f, 1.0f, 1.0f, 0.5f);
	else
	    glColor4f(0.5f, 1.0f, 1.0f, 0.1f);

	glPushMatrix();
	glRotatef(-25.0f, 1.0f, 0.0f, 0.0f);
	glRotatef(angle+=0.02f, 0.0f, 0.0f, 1.0f);
	glRotatef(360.0f * (float)i / 16, 0.0f, 0.0f, 1.0f);
	glTranslatef(0.0f, 3.0f, 0.0f);

	glBegin(GL_QUADS);
	glVertex2f(-3.0f * taper, 0.0f);
	glVertex2f(3.0f * taper, 0.0f);
	glVertex2f(4.0f * taper, 1.0f);
	glVertex2f(-4.0f * taper, 1.0f);
	glEnd();
	glPopMatrix();
    }
    
    for (i = 0; i < 18; i++)
    {
	static float angle = 0.0f;
	static float taper = 0.9f * ((2.0f * CL_PI) / 18.0f) / 2.0f;

	if(zf_ship_query_super_mode())
	{
	    glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
	}
	else
	{
	    if ((float)i / 18 < ship_power)
		glColor4f(1.0f, 1.0f, 0.5f, 0.5f);
	    else
		glColor4f(1.0f, 1.0f, 0.5f, 0.1f);
	}
	
	glPushMatrix();
	glRotatef(-25.0f, 1.0f, 0.0f, 0.0f);
	glRotatef(angle-=0.02f, 0.0f, 0.0f, 1.0f);
	glRotatef(360.0f * (float)i / 18, 0.0f, 0.0f, 1.0f);
	glTranslatef(0.0f, 1.5f, 0.0f);

	glBegin(GL_QUADS);
	glVertex2f(-1.5f * taper, 0.0f);
	glVertex2f(1.5f * taper, 0.0f);
	glVertex2f(2.5f * taper, 1.0f);
	glVertex2f(-2.5f * taper, 1.0f);
	glEnd();
	glPopMatrix();
    }

    glColor4f(0.4f, 0.7f, 0.5f, 0.8f);
    sprintf(stock_left, "%d\0", zf_weapon_control_query_bomb_tritor_stock());

    glTranslatef(-0.5f, -0.6f, 0.0f); 
    glLineWidth(2.0f);

    zf_text_draw(stock_left);

    glPopMatrix();
}

static void
render_power(float ship_power)
{
    unsigned int i;
    unsigned int j;
    char health[5];  /* 100%\0*/
    int ship_health = 0;
    float one_minus_ship_power;

    glPushMatrix();
    glLoadIdentity();

    glTranslatef(0.0f, 1.0f, -7.0f);

    one_minus_ship_power = 1.0f - ship_power;
    /*render_axis(10.0f);*/

    for (i = 0; i < 50; i++)
    {
	static float angle = 0.0f;
	static float taper = 1.0f * ((2.0f * CL_PI) / 50.0f)/2.0f;


	if ((float)i / 50 < ship_power)
	    glColor4f(one_minus_ship_power, ship_power, 0.1f, 0.7f);
	else
	    glColor4f(one_minus_ship_power, ship_power, 0.1f, 0.1f);


	glPushMatrix();
	glRotatef(-25.0f, 1.0f, 0.0f, 0.0f);
	/* glRotatef(angle+=0.02f, 0.0f, 0.0f, 1.0f); */
	glRotatef(180.0f * (float)i / 50, 0.0f, 0.0f, 1.0f);
	glTranslatef(0.0f, 3.0f, 0.0f);

	glBegin(GL_QUADS);
	glVertex2f(-3.0f * taper, 0.0f);
	glVertex2f(3.0f * taper, 0.0f);
	glVertex2f(4.0f * taper, 1.0f);
	glVertex2f(-4.0f * taper, 1.0f);
	glEnd();
	glPopMatrix();
    }

    glColor4f(1.0f, 1.0f, 0.0f, 0.8f);
    ship_health = (int)(ship_power * 100.0f);
    if(ship_health == 100)	
	sprintf(health, "100%%\0");
    else if(ship_health > 9)
	sprintf(health, "0%d%%\0", ship_health);
    else
	sprintf(health, "00%d%%\0", ship_health);

    glTranslatef(-1.5f, -1.0f, 2.0f); 
    glLineWidth(1.5f);
    zf_text_draw(health);
    glPopMatrix();

}

static void
render_score(void)
{
    char score[15]; /* hack */

    glPushMatrix();
    glLoadIdentity();
    
    if(hud_score < 10)
	sprintf(score, "000000%d\0",hud_score); 
    else if (hud_score < 100)
	sprintf(score, "00000%d\0",hud_score); 
    else if (hud_score < 1000)
	sprintf(score, "0000%d\0",hud_score); 
    else if (hud_score < 10000)
	sprintf(score, "000%d\0",hud_score); 
    else if (hud_score < 100000)
	sprintf(score, "00%d\0",hud_score); 
    else if (hud_score < 1000000)
	sprintf(score, "0%d\0",hud_score); 
    else if (hud_score < 10000000)
	sprintf(score, "%d\0",hud_score); 
    else
	sprintf(score, "9999999\0"); 


    glTranslatef(-2.0f, 1.5f, -10.0f); /* magic number hack */
    glColor4f(0.04f, 0.89f, 0.93f, 1.0f);
	
    zf_text_draw(score);

    glPopMatrix();
}

static void
render_highscore(void)
{
    char score[15]; /* hack */

    glPushMatrix();
    glLoadIdentity();
    if(hud_score >= high_score)
    {
	if(hud_score < 10)
	    sprintf(score, "000000%d\0",hud_score); 
	else if (hud_score < 100)
	    sprintf(score, "00000%d\0",hud_score); 
	else if (hud_score < 1000)
	    sprintf(score, "0000%d\0",hud_score); 
	else if (hud_score < 10000)
	    sprintf(score, "000%d\0",hud_score); 
	else if (hud_score < 100000)
	    sprintf(score, "00%d\0",hud_score); 
	else if (hud_score < 1000000)
	    sprintf(score, "0%d\0",hud_score); 
	else if (hud_score < 10000000)
	    sprintf(score, "%d\0",hud_score); 
	else
	    sprintf(score, "9999999\0"); 
	glColor4f(0.85f, 0.32f, 0.0f, 0.9f);
    }
    else
    {
	if(high_score < 10)
	    sprintf(score, "000000%d\0",high_score); 
	else if (high_score < 100)
	    sprintf(score, "00000%d\0",high_score); 
	else if (high_score < 1000)
	    sprintf(score, "0000%d\0",high_score); 
	else if (high_score < 10000)
	    sprintf(score, "000%d\0",high_score); 
	else if (high_score < 100000)
	    sprintf(score, "00%d\0",high_score); 
	else if (high_score < 1000000)
	    sprintf(score, "0%d\0",high_score); 
	else if (high_score < 10000000)
	    sprintf(score, "%d\0",high_score); 
	else
	    sprintf(score, "9999999\0"); 
	glColor4f(0.42f, 0.0f, 0.f, 0.72f);
    }


    glTranslatef(-5.5f, 0.6f, -10.0f); /* magic number hack */
    zf_text_draw(score);

    glColor4f(0.42f, 0.0f, 0.f, 0.72f);
    glTranslatef(-10.0f, 2.2f, -5.0f); /* magic number hack */
    zf_text_draw("highscore");

    glPopMatrix();
}

static void
render_flux_time(void)
{
    char flux_time[15]; /* hack */

    glPushMatrix();
    glLoadIdentity();
    

    sprintf(flux_time, "%.2f", zf_ship_query_flux_t()); 

    glTranslatef(-2.0f, 1.0f, -10.0f); /* magic number hack */
    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
	
    zf_text_draw(flux_time);

    glPopMatrix();
}

static void
render_boss_countdown(void)
{
    if(boss_mode)
    {
	char count_time[3]; /* hack */
	float ship_flux, end_flux, time_left;

	if(boss_mode != 2)
	{
	    ship_flux = zf_ship_query_flux_t();
	    end_flux = zf_flux_query_max_t() - BOSS_BOMB_TO_FLUX_END_BUFFER; /* need time to watch yourself die */
	    
	    time_left = end_flux - ship_flux;
	    
	    boss_counter = time_left / boss_time * BOSS_TIME_COUNTER_START;
	}

	if(boss_counter == 0)
	{
	    zf_boss_launch_mega_attack();
	    boss_mode = false;
	}


	glPushMatrix();
	glLoadIdentity();
	sprintf(count_time, "%d\0", boss_counter); 

	glTranslatef(-1.0f, -2.0f, -5.0f); /* magic number hack */
	glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
	glLineWidth(2.5f);
	
	zf_text_draw(count_time);

	glPopMatrix();
    }
}


static void
render_ship_lives(void)
{
    int ship_lives = zf_ship_query_lives();
    glPushMatrix();

/*    glEnable(GL_LIGHTING);*/
    glColor4f(0.8f, 0.3f, 0.1f, 0.7f);

    if(ship_lives >=4)
    {
	char lives[3];
	sprintf(lives, "x%d\0",ship_lives);
	glLoadIdentity();    
	glTranslatef(0.0f, 0.0f, -3.0f); /* magic number hack */
	glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
	glRotatef(ship_life_rotate+30.0f, 0.0f, 0.0f, 1.0f);
	clRenderModel(ship_model);
	glLoadIdentity();
	glTranslatef(2.0f, -1.0f, -8.0f);  /* hackity hack */
	zf_text_draw(lives);
    }
    else
    {
	if(ship_lives >= 1)
	{
	    glLoadIdentity();    
	    glTranslatef(1.0f, 0.0f, -3.0f); /* magic number hack */
	    glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
	    glRotatef(ship_life_rotate, 0.0f, 0.0f, 1.0f);

	    clRenderModel(ship_model);
	}

	if(ship_lives >= 2)
	{
	    glLoadIdentity();    
	    glTranslatef(0.0f, 0.0f, -3.0f); /* magic number hack */
	    glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
	    glRotatef(ship_life_rotate+30.0f, 0.0f, 0.0f, 1.0f);
	    clRenderModel(ship_model);
	}
    
	if(ship_lives == 3)
	{
	    glLoadIdentity();    
	    glTranslatef(-1.0f, 0.0f, -3.0f); /* magic number hack */
	    glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
	    glRotatef(ship_life_rotate+60.0f, 0.0f, 0.0f, 1.0f);
	    clRenderModel(ship_model);
	}
    }
    ship_life_rotate += SHIP_LIFE_ROTATE_INC;
    glPopMatrix();
}

void
zf_hud_render(void)
{
    glClear(GL_DEPTH_BUFFER_BIT);

    glPushAttrib(GL_ALL_ATTRIB_BITS); /* WARNING - super conservative! */
    glEnable(GL_BLEND);
    glEnable(GL_LINE_SMOOTH);
    glEnable(GL_POLYGON_SMOOTH);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    /* get viewport! to get ratio */
    glViewport(0.0f, 0.0f, 160, 120); /* WARNING: HAXOR!!! */
    render_weapon_meter(1.0f - zf_weapon_control_query_tritor_countdown(),
			1.0f - zf_weapon_control_query_bomb_countdown());
			

    glViewport(800.0f - 160.0f, 0.0f, 160, 120); /* WARNING: HAXOR!!! */
    render_power(zf_ship_query_power());

    glViewport(160.0f, 400.0f, 400, 250); /* WARNING: HAXOR!!! */
    render_score();

    glViewport(0.0f, 400.0f, 300, 250); /* WARNING: HAXOR!!! */
    render_highscore();

#if 0
    if(!boss_mode)
    {
	glViewport(250.0f, -50.0f, 500, 120); /* WARNING: HAXOR!!! */
	render_flux_time();
    }
#endif
    if(boss_mode)
    {
	glViewport(640.0f, 120.0f, 160, 100); /* WARNING: HAXOR!!! */
	render_boss_countdown();
    }
    
    glViewport(600.0f, 500.0f, 200, 120); /* WARNING: HAXOR!!! */
    render_ship_lives();
    
    /*  clDrawImage(image);*/

    glPopAttrib();

}

void 
zf_hud_increase_score(int increment)
{
    hud_score += increment;
}

/* returns a the score */
unsigned int
zf_hud_query_score(void)
{
    	return hud_score;
}
/*
  STUFF FOR NEW ZF (THE ONE TRUE PATH!!!!... for code)
*/

/* this doesn't really do anything because there is only ever one instance! */

/* these will be the same for all singletons - maybe provide standard
   "empty" functions - MAYBE EVEN A STANDARD zf_static_smart_pointer!
   (OMFG!) */
static bool
is_valid(const void* nothing_to_see_here)
{
    return true;
}

static void
reference(void* nothing_to_see_here)
{
}

static void
release(void* nothing_to_see_here)
{
}
/* end of stuff we don't really need */


static bool
msg_is_valid(ZfHudMessage* msg)
{
    return msg->age < HUD_MESSAGE_LIFESPAN;
}

static void
msg_reference(ZfHudMessage* msg)
{
    msg->ref_count++;
}

static void
msg_release(ZfHudMessage* msg)
{
    msg->ref_count--;
    if(msg->ref_count == 0)
	g_free(msg);
}

static void
msg_animate(ZfHudMessage* msg)
{
    if(msg->activated)
	msg->age++;
}

static void
msg_activate(ZfHudMessage* msg)
{
    msg->activated = true;
}

static void
msg_render(ZfHudMessage* msg)
{
    if(msg->activated)
    {
	glPushAttrib(GL_ALL_ATTRIB_BITS);

	glDisable(GL_LIGHTING);
	glDisable(GL_DEPTH_TEST);
	glDepthMask(GL_FALSE);
	glDisable(GL_BLEND);

	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glLoadIdentity();

	glTranslatef(msg->position.x,msg->position.y,msg->position.z);
	glColor4f(1.0f, 0.0f, 0.0f, 0.95f);
	glLineWidth(1.5f);
	zf_text_draw(msg->message);

	if(msg->type == 2)
	{ 
	    glLoadIdentity();
	    glTranslatef(-8.0f, -6.6f, -25.0f);
	    glColor4f(1.0f, 1.0f, 1.0f, 0.95f);
	    zf_text_draw("press any key");
	}

	glPopMatrix();  
	glPopAttrib();
    }
}

static void
message_pause_render(ZfHudMessage *msg)
{ 
    bool fin = false;

    glClear(GL_DEPTH_BUFFER_BIT);
    
    glPushAttrib(GL_ALL_ATTRIB_BITS);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glDisable(GL_DEPTH_TEST);
    glDepthMask(GL_FALSE);
    /*glEnable(GL_TEXTURE_2D);*/
    glEnable(GL_BLEND);
    glDisable(GL_LIGHTING);
    glDisable(GL_COLOR_MATERIAL);
    
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();
 
    glColor4f(0.1f, 0.1f, 0.1f, 0.5f);
    
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();

    glBegin(GL_QUADS);
    //  glTexCoord2f(0.0f, 0.0f);
    glVertex3d(-1.0f, 1.0f, 0.0f);
    // glTexCoord2f(s, 0.0f);
    glVertex3d(1.0f, 1.0f, 0.0f);
    //glTexCoord2f(s, t);
    glVertex3d(1.0f, -1.0f, 0.0f);
    //glTexCoord2f(0.0f, t);
    glVertex3d(-1.0f, -1.0f, 0.0f);
    glEnd();
    glPopMatrix();    
    SDL_GL_SwapBuffers();

    glMatrixMode(GL_MODELVIEW);

    glDisable(GL_BLEND);
    glTranslatef(msg->position.x,msg->position.y,msg->position.z);
    glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
    glLineWidth(1.5f);

    zf_text_draw(msg->message);

    glLoadIdentity();
    glTranslatef(-8.0f, -6.6f, -25.0f);
    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
    zf_text_draw("press any key");

    glPopMatrix();  
       
    glFlush();
    glFinish();
    SDL_GL_SwapBuffers();
  
    glPopAttrib();

    /* to paused the game until user presses something */
    while(!fin)
    {
	SDL_Event event;

	while(SDL_PollEvent(&event))
	{
	    switch(event.type)
	    {
	    case SDL_KEYDOWN:
		fin = true;
		/* Handle key presses. */
		break;
	    case SDL_QUIT:
		/* Handle quit requests (like Ctrl-c). */
		fin = true;
		break;
	    }
	}
    }
    msg->age = HUD_MESSAGE_LIFESPAN; /* needed to invalidate it */
    zf_game_loop_reset_time();
}

static void
message_read(FILE* stream)
{
    CLvertex position;
    int counter = 0;
    int type;
    float flux_t;
    char message[50];  /*HACK*/
    char check;

    fscanf(stream, "ZfHudMessage\n{\n");
    fscanf(stream, "position = %f %f %f\n",
	   &position.x, &position.y, &position.z);
    fscanf(stream, "flux_t = %f\n", &flux_t);
    fscanf(stream, "type = %d\n", &type);
    fscanf(stream, "msg = '%c", &check);
    while(check!='\'')
    {
	message[counter] = check;
	counter++;
	fscanf(stream, "%c", &check);
    }
    message[counter] = '\0';
    fscanf(stream, "\n}\n");

    zf_hud_new_message(flux_t, type, &position, message);
}

void
zf_hud_message_write(char* filename, GList* hud_message_list)
{
    FILE* stream; 
    GList*  li;
    ZfHudMessage* msg;
    CLvertex position;
    
    printf("%s() : save hud message file %s\n", __FUNCTION__, filename);
    
    stream = fopen(filename, "w");

    fprintf(stream, "ZfHudMessage\n{\n");
    fprintf(stream, "num_msg = %d\n",  g_list_length(hud_message_list));
    fprintf(stream, "messages =\n[\n");

    for (li = hud_message_list; li; li = li->next)
    {
	msg = (ZfHudMessage*)li->data;

	fprintf(stream, "ZfHudMessage\n{\n");
	fprintf(stream, "position = %f %f %f\n",
	       msg->position.x, msg->position.y, msg->position.z);
	fprintf(stream, "flux_t = %f\n", msg->flux_t);
	fprintf(stream, "type = %d\n", msg->type);
	fprintf(stream, "msg = '%s'", msg->message);
    }

    fprintf(stream, "]\n");
    fprintf(stream, "}\n");

    fclose(stream);
}

ZfHudMessage*
zf_hud_new_message(float flux_t, int type, CLvertex *position, char *message)
{
    ZfHudMessage* msg;

    msg = g_new(ZfHudMessage, 1);
    msg->message = strdup(message);
    msg->flux_t = flux_t;
    clCopyVertex(&msg->position, position);

    msg->ref_count = 0;
    msg->age = 0;
    msg->type = type;
    msg->activated = false;
    switch(msg->type)
    {
    case 0:
	zf_trigger_system_add_trigger(flux_t,
				      msg,
				      &msg_smart_pointer,
				      (ZfSpawn*)message_pause_render); 
	break;
    case 1:
	zf_trigger_system_add_trigger(flux_t,
				      msg,
				      &msg_smart_pointer,
				      (ZfSpawn*)msg_activate); 
	
	zf_animation_system_add(msg,
				&msg_smart_pointer,
				(ZfAnimate*) msg_animate);
	
	zf_render_system_add_translucent(msg,
					 &msg_smart_pointer,
					 (ZfRender*)msg_render);
	break;
    case 2:
	/* no trigger - activate now*/
	msg->activated = true;
	zf_render_system_add_translucent(msg,
					 &msg_smart_pointer,
					 (ZfRender*)msg_render);
	break;
    }

    return msg;
}

void
zf_hud_message_kill(ZfHudMessage* msg)
{
    msg->activated = false;
    msg->age = HUD_MESSAGE_LIFESPAN;
}

void
zf_hud_init(char* filename)
{
    smart_pointer.is_valid = (ZfIsValid*)is_valid;
    smart_pointer.reference = (ZfReference*)reference;
    smart_pointer.release = (ZfRelease*)release;

    msg_smart_pointer.is_valid = (ZfIsValid*)msg_is_valid;
    msg_smart_pointer.reference = (ZfReference*)msg_reference;
    msg_smart_pointer.release =(ZfRelease*) msg_release;

    hud_energy = 100.0f;
    hud_speed = 10000000.0f;

    hud_angle = 0.0f;
    hud_score = 0;
    high_score = zf_menu_loop_query_highscore();

    boss_mode = false;
    boss_counter = 100;

    ship_life_rotate = 0.0f;

    /*    hud_sound = zf_audio_sample_load("../data/samples/laser01.wav");
	  zf_audio_sample_set_looping(hud_sound, false)    */
    
    zf_animation_system_add(0,
			    &smart_pointer,
			    (ZfAnimate*) animate);


    context = clDefaultContext(clNewContext());
    ship_model = clioLoadModel(context, "../data/models/manta/manta.3DS");
    
    /* not clean to just exit, but use this until we have a good error
       system */
    if (!ship_model)
    {
	printf("could not load manta for HUD\n");
	exit(1);
    }
    
    cluModelScaleUnitCube(ship_model);
    cluModelScale(ship_model, 1.0f);
    clUpdateContext(ship_model->context);

    /* CHANGE THIS TO USE AN IMAGE!!! */
    /*image = clDefaultImage(clNewImage()); */
    image = clioLoadImage("../data/images/menu/controls.png"); 

    /* loading the hud messages */
    {
	unsigned int i;
	int num_msg;
    
	FILE* stream;
	
	stream = fopen(filename, "r");

	/* check fopen */
	if (!stream)
	{
	    printf("%s() : ERROR : cant load hud messages file %s\n", __FUNCTION__, filename);
	    exit(1);
	}

	fscanf(stream, "ZfHudMessage\n{\n");
	fscanf(stream, "num_msg = %d\n", &num_msg);
	fscanf(stream, "messages =\n[\n");

	/* todo: seperate into read()?*/
	for (i = 0; i < num_msg; i++)
	{
	    message_read(stream);   
	}

	fscanf(stream, "]\n");
	fscanf(stream, "}\n");

	fclose(stream);
    }


}

void
zf_hud_close(void)
{
    clDeleteContext(context);
    clDeleteImage(image);
}

void
zf_hud_set_boss_mode(int mode)
{
    boss_mode = mode;
    if(boss_mode)
    {
	float ship_flux, end_flux;
	
	ship_flux = zf_ship_query_flux_t();
	end_flux = zf_flux_query_max_t() - BOSS_BOMB_TO_FLUX_END_BUFFER; /* need time to watch yourself die */

	boss_time = end_flux - ship_flux;
    }
}
