/** 
 * One time initializations done when we want to display a new training mission.
 * 
 * This does all the processing and setup required to actually display it, including 
 * starting the voice file playing
 */
void message_training_setup(int m, int length, char *special_message)
{
	if ((m < 0) || !Messages[m].message[0]) {  // remove current message from the screen
		Training_num_lines = 0;
		return;
	}

	// translate tokens in message to the real things
	if (special_message == NULL)
		message_translate_tokens(Training_buf, Messages[m].message);
	else
		message_translate_tokens(Training_buf, special_message);

	HUD_add_to_scrollback(Training_buf, HUD_SOURCE_TRAINING);

	// moved from message_training_display() because we got rid of an extra buffer and we have to determine
	// the number of lines earlier to avoid inadvertant modification of Training_buf.  - taylor
	training_process_message(Training_buf);
	Training_num_lines = split_str(Training_buf, TRAINING_LINE_WIDTH, Training_line_lengths, Training_lines, MAX_TRAINING_MESSAGE_LINES);

	Assert( Training_num_lines >= 0 );

	if (message_play_training_voice(Messages[m].wave_info.index) < 0) {
		if (length > 0)
			Training_message_timestamp = timestamp(length * 1000);
		else
			Training_message_timestamp = timestamp(TRAINING_TIMING_BASE + strlen(Messages[m].message) * TRAINING_TIMING);  // no voice file playing

	} else
		Training_message_timestamp = 0;
}
// processes a new training message to get hilighting information and store it in internal structures.
void training_process_msg(char *msg)
{
	int count;
	char *src, *dest, buf[8192];

	message_translate_tokens(buf, msg);
	count = 0;
	src = buf;
	dest = Training_buf;
	while (*src) {
		if (!strnicmp(src, NOX("<b>"), 3)) {
			Assert(count < MAX_TRAINING_MSG_MODS);
			src += 3;
			Training_msg_mods[count].pos = dest;
			Training_msg_mods[count].mode = TMMOD_BOLD;
			count++;
		}

		if (!strnicmp(src, NOX("</b>"), 4)) {
			Assert(count < MAX_TRAINING_MSG_MODS);
			src += 4;
			Training_msg_mods[count].pos = dest;
			Training_msg_mods[count].mode = TMMOD_NORMAL;
			count++;
		}

		*dest++ = *src++;
	}

	*dest = 0;
	if (count < MAX_TRAINING_MSG_MODS)
		Training_msg_mods[count].pos = NULL;
}
// one time initializations done when we want to display a new training mission.  This does
// all the processing and setup required to actually display it, including starting the
// voice file playing
void message_training_setup(int m, int length)
{
	if ((m < 0) || !Messages[m].message[0]) {  // remove current message from the screen
		Training_num_lines = 0;
		return;
	}

	message_translate_tokens(Training_buf, Messages[m].message);
	HUD_add_to_scrollback(Training_buf, HUD_SOURCE_TRAINING);
	strcpy(Training_text, Messages[m].message);

	if (message_play_training_voice(Messages[m].wave_info.index) < 0) {
		if (length > 0)
			Training_msg_timestamp = timestamp(length * 1000);
		else
			Training_msg_timestamp = timestamp(TRAINING_TIMING_BASE + strlen(Messages[m].message) * TRAINING_TIMING);  // no voice file playing

	} else
		Training_msg_timestamp = 0;
}
// displays (renders) the training objectives list
void training_obj_display()
{
		
	char buf[256], *second_line;
	int i, t, x, y, z, height, end, offset, bx, by, y_count;
	color *c;

	if (!Training_obj_num_lines){
		return;
	}

	if ( !hud_gauge_active(HUD_DIRECTIVES_VIEW) ) {
		// Always draw the directives display if this is a training mission
		if ( !(The_mission.game_type & MISSION_TYPE_TRAINING) ) {
			return;
		}
	}

	// don't ever display directives display in multiplayer missions
	// if ( Game_mode & GM_MULTIPLAYER ){
	// 	return;
	// }

	height = gr_get_font_height();

	offset = 0;
	end = Training_obj_num_lines;
	if (end > TRAINING_OBJ_DISPLAY_LINES) {
		end = TRAINING_OBJ_DISPLAY_LINES;
		offset = Training_obj_num_lines - end;
	}

	// draw top of objective display
	// hud_set_default_color();
	hud_set_gauge_color(HUD_DIRECTIVES_VIEW);

	GR_AABITMAP(Directive_gauge[0].first_frame, Directive_coords[gr_screen.res][DIRECTIVE_COORDS_TOP][0]+fl2i(HUD_offset_x), Directive_coords[gr_screen.res][DIRECTIVE_COORDS_TOP][1]+fl2i(HUD_offset_y));
	// gr_set_bitmap(Directive_gauge[0].first_frame);
	// gr_aabitmap(Directive_coords[DIRECTIVE_COORDS_TOP][0]+fl2i(HUD_offset_x), Directive_coords[DIRECTIVE_COORDS_TOP][1]+fl2i(HUD_offset_y));

	// print out title
	emp_hud_printf(Directive_coords[gr_screen.res][DIRECTIVE_COORDS_TITLE][0]+fl2i(HUD_offset_x), Directive_coords[gr_screen.res][DIRECTIVE_COORDS_TITLE][1]+fl2i(HUD_offset_y), EG_OBJ_TITLE, XSTR( "Directives", 422));
	// gr_printf(Directive_coords[DIRECTIVE_COORDS_TITLE][0]+fl2i(HUD_offset_x), Directive_coords[DIRECTIVE_COORDS_TITLE][1]+fl2i(HUD_offset_y), XSTR( "directives", 422));
	
	bx = DIRECTIVE_X+fl2i(HUD_offset_x);
	by = Directive_coords[gr_screen.res][DIRECTIVE_COORDS_MIDDLE][1]+fl2i(HUD_offset_y);

	y_count = 0;
	for (i=0; i<end; i++) {
		x = DIRECTIVE_X + 5 + fl2i(HUD_offset_x);
		y = Training_obj_window_coords[gr_screen.res][1] + fl2i(HUD_offset_y) + y_count * height + height / 2 + 1;
		z = TRAINING_OBJ_LINES_MASK(i + offset);

		c = &Color_normal;
		if (Training_obj_lines[i + offset] & TRAINING_OBJ_LINES_KEY) {
			message_translate_tokens(buf, Mission_events[z].objective_key_text);  // remap keys
//			gr_set_color_fast(&Color_normal);
			c = &Color_bright_green;
		} else {
			strcpy(buf, Mission_events[z].objective_text);
			if (Mission_events[z].count){
				sprintf(buf + strlen(buf), NOX(" [%d]"), Mission_events[z].count);
			}

#ifndef NO_NETWORK
			// if this is a multiplayer tvt game, and this is event is not for my team, don't display it
			if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_TEAM) && (Net_player != NULL)){
				if((Mission_events[z].team != -1) && (Net_player->p_info.team != Mission_events[z].team)){
					continue;
				}
			}
#endif

			switch (mission_get_event_status(z)) {
			case EVENT_CURRENT:
//				gr_set_color_fast(&Color_bright_white);
				c = &Color_bright_white;
				break;

			case EVENT_FAILED:
//				gr_set_color_fast(&Color_bright_red);
				c = &Color_bright_red;
				break;

			case EVENT_SATISFIED:
//				gr_set_color_fast(&Color_bright_blue);
				t = Mission_events[z].satisfied_time;
				if (t + i2f(2) > Missiontime) {
					if (Missiontime % fl2f(.4f) < fl2f(.2f)){
						c = &Color_bright_blue;
					} else {
						c = &Color_bright_white;
					}
				} else {
					c = &Color_bright_blue;
				}
				break;
			}
		}

		// maybe split the directives line
		second_line = split_str_once(buf, 167);

		// blit the background frames
		// hud_set_default_color();
		hud_set_gauge_color(HUD_DIRECTIVES_VIEW);

		GR_AABITMAP(Directive_gauge[1].first_frame, bx, by);
		// gr_set_bitmap(Directive_gauge[1].first_frame);
		// gr_aabitmap(bx, by);
		
		by += DIRECTIVE_H;

		if ( second_line ) {
			GR_AABITMAP(Directive_gauge[1].first_frame, bx, by);
			// gr_set_bitmap(Directive_gauge[1].first_frame);
			// gr_aabitmap(bx, by);
			
			by += DIRECTIVE_H;
		}

		// blit the text
		gr_set_color_fast(c);
		
		emp_hud_string(x, y, EG_OBJ1 + i, buf);
		// gr_printf(x, y, buf);
		
		y_count++;

		if ( second_line ) {
			y = Training_obj_window_coords[gr_screen.res][1] + fl2i(HUD_offset_y) + y_count * height + height / 2 + 1;
			
			emp_hud_string(x+12, y, EG_OBJ1 + i + 1, second_line);
			// gr_printf(x+12, y, second_line);
			
			y_count++;
		}
	}

	// draw the bottom of objective display
	// hud_set_default_color();
	hud_set_gauge_color(HUD_DIRECTIVES_VIEW);

	GR_AABITMAP(Directive_gauge[2].first_frame, bx, by);
	// gr_set_bitmap(Directive_gauge[2].first_frame);
	// gr_aabitmap(bx, by);
}
// displays (renders) the training message to the screen
void message_training_display()
{
	char *str, buf[256];
	int i, z, x, y, height, mode, count;

	Training_msg_visible = 0;
	message_training_que_check();
	training_obj_display();

	if (Training_failure){
		return;
	}

	if (timestamp_elapsed(Training_msg_timestamp) || !strlen(Training_text)){
		return;
	}

	message_translate_tokens(Training_buf, Training_text);
	training_process_msg(Training_text);
	Training_num_lines = split_str(Training_buf, TRAINING_LINE_WIDTH, Training_line_sizes, Training_lines, MAX_TRAINING_MSG_LINES);
	Assert(Training_num_lines > 0);
	for (i=0; i<Training_num_lines; i++) {
		Training_lines[i][Training_line_sizes[i]] = 0;
		drop_leading_white_space(Training_lines[i]);
	}

	if (Training_num_lines <= 0){
		return;
	}

	height = gr_get_font_height();
	gr_set_shader(&Training_msg_glass);
	gr_shade(Training_msg_window_coords[gr_screen.res][0], Training_msg_window_coords[gr_screen.res][1], TRAINING_MSG_WINDOW_WIDTH, Training_num_lines * height + height);

	gr_set_color_fast(&Color_bright_blue);
	mode = count = 0;
	Training_msg_visible = 1;
	for (i=0; i<Training_num_lines; i++) {  // loop through all lines of message
		str = Training_lines[i];
		z = 0;
		x = Training_msg_window_coords[gr_screen.res][0] + (TRAINING_MSG_WINDOW_WIDTH - TRAINING_LINE_WIDTH) / 2;
		y = Training_msg_window_coords[gr_screen.res][1] + i * height + height / 2 + 1;

		while (*str) {  // loop through each character of each line
			if ((count < MAX_TRAINING_MSG_MODS) && (str == Training_msg_mods[count].pos)) {
				buf[z] = 0;
				gr_printf(x, y, buf);
				gr_get_string_size(&z, NULL, buf);
				x += z;
				z = 0;

				mode = Training_msg_mods[count++].mode;
				switch (mode) {
					case TMMOD_NORMAL:
						gr_set_color_fast(&Color_bright_blue);
						break;

					case TMMOD_BOLD:
						gr_set_color_fast(&Color_white);
						break;
				}
			}

			buf[z++] = *str++;
		}

		if (z) {
			buf[z] = 0;
			gr_printf(x, y, "%s", buf);
		}
	}

	Training_msg_method = 0;
//	if (Training_msg_method) {
//		char *msg = "Press a key to continue";

//		gr_get_string_size(&i, NULL, msg);
//		gr_printf(TRAINING_MSG_WINDOW_X + TRAINING_MSG_WINDOW_WIDTH / 2 - i / 2, TRAINING_MSG_WINDOW_Y + (Training_num_lines + 2) * height, msg);
//	}

	if ((Training_voice >= 0) && (Training_num_lines > 0) && !(Training_msg_timestamp)) {
		if (Training_voice_type)
			z = audiostream_is_playing(Training_voice_handle);
		else
			z = snd_is_playing(Training_voice_handle);

		if (!z)
			Training_msg_timestamp = timestamp(2000);  // 2 second delay
 	}
}
void HudGaugeDirectives::render(float frametime)
{
	char buf[256], *second_line;
	int i, t, x, y, z, end, offset, bx, by, y_count;
	color *c;

	if (!Training_obj_num_lines){
		return;
	}

	offset = 0;
	end = Training_obj_num_lines;
	if (end > Max_directives) {
		end = Max_directives;
		offset = Training_obj_num_lines - end;
	}

	// draw top of objective display
	setGaugeColor();

	renderBitmap(directives_top.first_frame, position[0], position[1]);

	// print out title
	renderPrintf(position[0] + header_offsets[0], position[1] + header_offsets[1], EG_OBJ_TITLE, XSTR( "directives", 422));

	bx = position[0];
	by = position[1] + middle_frame_offset_y;

	y_count = 0;
	for (i=0; i<end; i++) {
		x = position[0] + text_start_offsets[0];
		y = position[1] + text_start_offsets[1] + y_count * text_h;
		z = TRAINING_OBJ_LINES_MASK(i + offset);

		c = &Color_normal;
		if (Training_obj_lines[i + offset] & TRAINING_OBJ_LINES_KEY) {
			message_translate_tokens(buf, Mission_events[z].objective_key_text);  // remap keys
			c = &Color_bright_green;
		} else {
			strcpy_s(buf, Mission_events[z].objective_text);
			if (Mission_events[z].count){
				sprintf(buf + strlen(buf), NOX(" [%d]"), Mission_events[z].count);
			}

			// if this is a multiplayer tvt game, and this is event is not for my team, don't display it
			if((MULTI_TEAM) && (Net_player != NULL)){
				if((Mission_events[z].team != -1) && (Net_player->p_info.team != Mission_events[z].team)){
					continue;
				}
			}

			switch (mission_get_event_status(z)) {
			case EVENT_CURRENT:
				c = &Color_bright_white;
				break;

			case EVENT_FAILED:
				c = &Color_bright_red;
				break;

			case EVENT_SATISFIED:
				t = Mission_events[z].satisfied_time;
				if (t + i2f(2) > Missiontime) {
					if (Missiontime % fl2f(.4f) < fl2f(.2f)){
						c = &Color_bright_blue;
					} else {
						c = &Color_bright_white;
					}
				} else {
					c = &Color_bright_blue;
				}
				break;
			}
		}

		// maybe split the directives line
		second_line = split_str_once(buf, max_line_width);
		Assert( second_line != buf );

		// blit the background frames
		setGaugeColor();

		renderBitmap(directives_middle.first_frame, bx, by);
		
		by += text_h;

		if ( second_line ) {
			renderBitmap(directives_middle.first_frame, bx, by);
			
			by += text_h;
		}

		// blit the text
		gr_set_color_fast(c);
		
		renderString(x, y, EG_OBJ1 + i, buf);
		
		y_count++;

		if ( second_line ) {
			y = position[1] + text_start_offsets[1] + y_count * text_h;
			
			renderString(x+12, y, EG_OBJ1 + i + 1, second_line);
			
			y_count++;
		}
	}

	// draw the bottom of objective display
	setGaugeColor();

	renderBitmap(directives_bottom.first_frame, bx, by + bottom_bg_offset);
}