#include <stdlib.h>

#include "gamesequence.h"
#include "font.h"
#include "key.h"
#include "bmpman.h"
#include "2d.h"
#include "timer.h"
#include "gamesnd.h"
#include "audiostr.h"
#include "eventmusic.h"	
#include "cfile.h"
#include "ui.h"
#include "missionscreencommon.h"
#include "player.h"
#include "freespace.h"
#include "alphacolors.h"
#include "localize.h"

#define CREDITS_MUSIC_DELAY	2000
#define CREDITS_SCROLL_RATE	15.0f
#define CREDITS_ARTWORK_DISPLAY_TIME	9.0f
#define CREDITS_ARTWORK_FADE_TIME		1.0f

#define NUM_BUTTONS				5
#define NUM_IMAGES				46

#define TECH_DATABASE_BUTTON	0
#define SIMULATOR_BUTTON		1
#define CUTSCENES_BUTTON		2
#define CREDITS_BUTTON			3
#define EXIT_BUTTON				4

#define CREDITS_X_COORD 0
#define CREDITS_Y_COORD 1
#define CREDITS_W_COORD 2
#define CREDITS_H_COORD 3

static const char* Credits_bitmap_fname[GR_NUM_RESOLUTIONS] = {
	"Credits",			
	"2_Credits"
};

static const char* Credits_bitmap_mask_fname[GR_NUM_RESOLUTIONS] = {
	"Credits-M",			
	"2_Credits-M"
};

int Credits_image_coords[GR_NUM_RESOLUTIONS][4] = {
	{
#ifdef MAKE_FS1
		225, 15, 400, 292
#else
		219, 15, 394, 286			
#endif
	},
	{
		351, 25, 629, 455			
	}
};

int Credits_text_coords[GR_NUM_RESOLUTIONS][4] = {
	{
#ifdef MAKE_FS1
		46, 321, 450, 134
#else
		26, 316, 482, 157			
#endif
	},
	{
		144, 507, 568, 249			
	}
};

struct credits_screen_buttons {
	const char *filename;
	int x, y, xt, yt;
	int hotspot;
	UI_BUTTON button;  

	credits_screen_buttons(const char *name, int x1, int y1, int xt1, int yt1, int h) : filename(name), x(x1), y(y1), xt(xt1), yt(yt1), hotspot(h) {}
};

static int Background_bitmap;
#ifdef MAKE_FS1
static int CreditsWin01 = -1;
static int CreditsWin02 = -1;
static int CreditsWin03 = -1;
static int CreditsWin04 = -1;
#endif

static UI_WINDOW Ui_window;

static credits_screen_buttons Buttons[NUM_BUTTONS][GR_NUM_RESOLUTIONS] = {

#ifdef MAKE_FS1
    {
			credits_screen_buttons("TDB_00", 0, 0, -1, -1, 0),		
			credits_screen_buttons("2_TDB_00", 12, 5, 59, 12, 0)		
    },
    {
			credits_screen_buttons("TDB_01", 0, 19, -1, -1, 1),		
			credits_screen_buttons("2_TDB_01", 12, 31, 59, 37, 1)		
    },
    {
			credits_screen_buttons("TDB_02", 0, 35, -1, -1, 2),		
			credits_screen_buttons("2_TDB_02", 12, 56, 59, 62, 2)		
    },
    {
			credits_screen_buttons("TDB_03", 0, 56, -1, -1, 3),		
			credits_screen_buttons("2_TDB_03", 12, 81, 59, 88, 3)		
    },
    {
			credits_screen_buttons("CRB_04", 561, 411, -1, -1, 4),	
			credits_screen_buttons("2_CRB_04", 914, 681, 953, 68, 4)	
    }
#else
	{
			credits_screen_buttons("TDB_00", 7, 3, 37, 7, 0),			
			credits_screen_buttons("2_TDB_00", 12, 5, 59, 12, 0)			
	},
	{
			credits_screen_buttons("TDB_01", 7, 18, 37, 23,	1),		
			credits_screen_buttons("2_TDB_01", 12, 31, 59, 37, 1)		
	},
	{
			credits_screen_buttons("TDB_02", 7, 34, 37, 38, 2),		
			credits_screen_buttons("2_TDB_02", 12, 56, 59, 62, 2)		
	},
	{
			credits_screen_buttons("TDB_03", 7, 49, 37, 54,	3),		
			credits_screen_buttons("2_TDB_03", 12, 81, 59, 88, 3)		
	},
	{
			credits_screen_buttons("CRB_04", 571, 425, 588, 413, 4),	
			credits_screen_buttons("2_CRB_04", 914, 681, 953, 668, 4)	
	}
#endif

};

static int	Credits_music_handle = -1;
static int	Credits_music_begin_timestamp;

static int	Credits_frametime;		
static int	Credits_last_time;		
static float Credits_counter;
static int Credits_artwork_index;
static int Credits_bmps[NUM_IMAGES];

char *Credit_text = NULL;

float Credit_start_pos, Credit_stop_pos, Credit_position = 0.0f;

void credits_stop_music()
{
	if ( Credits_music_handle != -1 ) {
		audiostream_close_file(Credits_music_handle);
		Credits_music_handle = -1;
	}
}

void credits_load_music(const char* fname)
{
	if ( Credits_music_handle != -1 ){
		return;
	}

	if ( fname ){
		Credits_music_handle = audiostream_open( fname, ASF_EVENTMUSIC );
	}
}

void credits_start_music()
{
	if (Credits_music_handle != -1) {
		if ( !audiostream_is_playing(Credits_music_handle) ){
			audiostream_play(Credits_music_handle, Master_event_music_volume);
		}
	} else {
		nprintf(("Warning", "Cannot play credits music\n"));
	}
}

int credits_screen_button_pressed(int n)
{
	switch (n) {
	case TECH_DATABASE_BUTTON:
		gamesnd_play_iface(SND_SWITCH_SCREENS);
		gameseq_post_event(GS_EVENT_TECH_MENU);
		return 1;

	case SIMULATOR_BUTTON:
		gamesnd_play_iface(SND_SWITCH_SCREENS);
		gameseq_post_event(GS_EVENT_SIMULATOR_ROOM);
		return 1;

	case CUTSCENES_BUTTON:
		gamesnd_play_iface(SND_SWITCH_SCREENS);
		gameseq_post_event(GS_EVENT_GOTO_VIEW_CUTSCENES_SCREEN);
		return 1;

	case EXIT_BUTTON:
		gamesnd_play_iface(SND_COMMIT_PRESSED);
		gameseq_post_event(GS_EVENT_MAIN_MENU);
		game_flush();
		break;
	}

	return 0;
}

void credits_init()
{
	int i, w, h;
	credits_screen_buttons *b;
	char line[512] = "";	
	char *linep1, *linep2;	

	int credits_spooled_music_index = event_music_get_spooled_music_index("Cinema");	
	if(credits_spooled_music_index != -1){
		char *credits_wavfile_name = Spooled_music[credits_spooled_music_index].filename;		
		if(credits_wavfile_name != NULL){
			credits_load_music(credits_wavfile_name);
		}
	}

	Credits_music_begin_timestamp = timestamp(CREDITS_MUSIC_DELAY);

	Credits_frametime = 0;
	Credits_last_time = timer_get_milliseconds();

	Credit_text = NULL;

	CFILE *fp = cfopen( NOX("credits.tbl"), "rb" );
	if(fp != NULL){
		int size;
		size = cfilelength(fp);
		Credit_text = (char *) malloc(size + 200);
		cfclose(fp);

		lcl_ext_open();
		read_file_text("credits.tbl");
		reset_parse();

		strcpy(Credit_text,"");		
#ifndef MAKE_FS1
		while(!check_for_string_raw("#end")){
#else
		char *ugh = Mp;
		char ch;
		int line_count = 0;

		while (*ugh && *ugh != EOF_CHAR) {
			ch = *ugh;

			if (ch == '\n'){
				line_count++;
			}
			ugh++;
		}

		while(line_count > 0){
			line_count--;
#endif
			stuff_string_line(line, 511);
			linep1 = line;

			do {
				linep2 = split_str_once(linep1, Credits_text_coords[gr_screen.res][2]);
				strcat(Credit_text, linep1);
				strcat(Credit_text, "\n");			
				linep1 = linep2;
			} while (linep2 != NULL);
		}		

		lcl_ext_close();	
	} else {
		Credit_text = (char *) malloc(25 + 200);
		strcpy(Credit_text, NOX("No credits available.\n"));
	}	

	int ch;
	for ( i = 0; Credit_text[i]; i++ ) {
			ch = Credit_text[i];
			switch (ch) {
			case -4:
				ch = 129;
				break;

			case -28:
				ch = 132;
				break;

			case -10:
				ch = 148;
				break;

			case -23:
				ch = 130;
				break;

			case -30:
				ch = 131;
				break;

			case -25:
				ch = 135;
				break;

			case -21:
				ch = 137;
				break;

			case -24:
				ch = 138;
				break;

			case -17:
				ch = 139;
				break;

			case -18:
				ch = 140;
				break;

			case -60:
				ch = 142;
				break;

			case -55:
				ch = 144;
				break;

			case -12:
				ch = 147;
				break;

			case -14:
				ch = 149;
				break;

			case -5:
				ch = 150;
				break;

			case -7:
				ch = 151;
				break;

			case -42:
				ch = 153;
				break;

			case -36:
				ch = 154;
				break;

			case -31:
				ch = 160;
				break;

			case -19:
				ch = 161;
				break;

			case -13:
				ch = 162;
				break;

			case -6:
				ch = 163;
				break;

			case -32:
				ch = 133;
				break;

			case -22:
				ch = 136;
				break;

			case -20:
				ch = 141;
				break;
			}
			Credit_text[i] = (char)ch;
	}

	gr_get_string_size(&w, &h, Credit_text);

	Credit_start_pos = i2fl(Credits_text_coords[gr_screen.res][CREDITS_H_COORD]);
	Credit_stop_pos = -i2fl(h);
	Credit_position = Credit_start_pos;

	Ui_window.create(0, 0, gr_screen.max_w, gr_screen.max_h, 0);
	Ui_window.set_mask_bmap(Credits_bitmap_mask_fname[gr_screen.res]);
	common_set_interface_palette("InterfacePalette");  

	for (i=0; i<NUM_BUTTONS; i++) {
		b = &Buttons[i][gr_screen.res];

		b->button.create(&Ui_window, "", b->x, b->y, 60, 30, (i < 2), 1);

		b->button.set_highlight_action(common_play_highlight_sound);
		b->button.set_bmaps(b->filename);
		b->button.link_hotspot(b->hotspot);
	}

#ifndef MAKE_FS1

	Ui_window.add_XSTR("Technical Database", 1055, Buttons[TECH_DATABASE_BUTTON][gr_screen.res].xt,  Buttons[TECH_DATABASE_BUTTON][gr_screen.res].yt, &Buttons[TECH_DATABASE_BUTTON][gr_screen.res].button, UI_XSTR_COLOR_GREEN);
	Ui_window.add_XSTR("Mission Simulator", 1056, Buttons[SIMULATOR_BUTTON][gr_screen.res].xt,  Buttons[SIMULATOR_BUTTON][gr_screen.res].yt, &Buttons[SIMULATOR_BUTTON][gr_screen.res].button, UI_XSTR_COLOR_GREEN);
	Ui_window.add_XSTR("Cutscenes", 1057, Buttons[CUTSCENES_BUTTON][gr_screen.res].xt,  Buttons[CUTSCENES_BUTTON][gr_screen.res].yt, &Buttons[CUTSCENES_BUTTON][gr_screen.res].button, UI_XSTR_COLOR_GREEN);
	Ui_window.add_XSTR("Credits", 1058, Buttons[CREDITS_BUTTON][gr_screen.res].xt,  Buttons[CREDITS_BUTTON][gr_screen.res].yt, &Buttons[CREDITS_BUTTON][gr_screen.res].button, UI_XSTR_COLOR_GREEN);
	Ui_window.add_XSTR("Exit", 1420, Buttons[EXIT_BUTTON][gr_screen.res].xt,  Buttons[EXIT_BUTTON][gr_screen.res].yt, &Buttons[EXIT_BUTTON][gr_screen.res].button, UI_XSTR_COLOR_PINK);
#endif

	if (Player->flags & PLAYER_FLAGS_IS_MULTI) {
		Buttons[SIMULATOR_BUTTON][gr_screen.res].button.disable();
		Buttons[CUTSCENES_BUTTON][gr_screen.res].button.disable();
	}

	Buttons[EXIT_BUTTON][gr_screen.res].button.set_hotkey(KEY_CTRLED | KEY_ENTER);

	Background_bitmap = bm_load(Credits_bitmap_fname[gr_screen.res]);
	Credits_artwork_index = rand() % NUM_IMAGES;
	for (i=0; i<NUM_IMAGES; i++){
		Credits_bmps[i] = -1;
	}

#ifdef MAKE_FS1
	CreditsWin01 = bm_load(NOX("CreditsWin01"));
	CreditsWin02 = bm_load(NOX("CreditsWin02"));
	CreditsWin03 = bm_load(NOX("CreditsWin03"));
	CreditsWin04 = bm_load(NOX("CreditsWin04"));
#endif
}

void credits_close()
{	
	int i;

#ifdef MAKE_FS1
	if (CreditsWin01 != -1){
		bm_unload(CreditsWin01);
		CreditsWin01 = -1;
	}
	if (CreditsWin02 != -1){
		bm_unload(CreditsWin02);
		CreditsWin02 = -1;
	}
	if (CreditsWin03 != -1){
		bm_unload(CreditsWin03);
		CreditsWin03 = -1;
	}
	if (CreditsWin04 != -1){
		bm_unload(CreditsWin04);
		CreditsWin04 = -1;
	}
#endif

	for (i=0; i<NUM_IMAGES; i++){
		if (Credits_bmps[i] >= 0){
			bm_unload(Credits_bmps[i]);
			Credits_bmps[i] = -1;
		}
	}	

	credits_stop_music();

	if (Credit_text) {
		free(Credit_text);
		Credit_text = NULL;
	}

	if (Background_bitmap){
		bm_unload(Background_bitmap);
	}

	Ui_window.destroy();
	common_free_interface_palette();		
}

void credits_do_frame(float frametime)
{
	int i, k, next, percent, bm1, bm2;
	int bx1, by1, bw1, bh1;
	int bx2, by2, bw2, bh2;

	if ( timestamp_elapsed(Credits_music_begin_timestamp) ) {
		Credits_music_begin_timestamp = 0;
		credits_start_music();
	}

	k = Ui_window.process();
	switch (k) {
	case KEY_ESC:
		gameseq_post_event(GS_EVENT_MAIN_MENU);
		key_flush();
		break;

	case KEY_CTRLED | KEY_UP:
	case KEY_SHIFTED | KEY_TAB:
		if ( !(Player->flags & PLAYER_FLAGS_IS_MULTI) ) {
			credits_screen_button_pressed(CUTSCENES_BUTTON);
			break;
		}

	case KEY_CTRLED | KEY_DOWN:
	case KEY_TAB:
		credits_screen_button_pressed(TECH_DATABASE_BUTTON);
		break;

	default:
		break;
	} 

	for (i=0; i<NUM_BUTTONS; i++){
		if (Buttons[i][gr_screen.res].button.pressed()){
			if (credits_screen_button_pressed(i)){
				return;
			}
		}
	}

	gr_reset_clip();	
	GR_MAYBE_CLEAR_RES(Background_bitmap);
	if (Background_bitmap >= 0) {
		gr_set_bitmap(Background_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
		gr_bitmap(0, 0);
	} 

	percent = (int) (100.0f - (CREDITS_ARTWORK_DISPLAY_TIME - Credits_counter) * 100.0f / CREDITS_ARTWORK_FADE_TIME);
	if (percent < 0){
		percent = 0;
	}

	next = Credits_artwork_index + 1;
	if (next >= NUM_IMAGES){
		next = 0;
	}

	if (Credits_bmps[Credits_artwork_index] < 0) {
		char buf[40];

		if (gr_screen.res == GR_1024) {
			sprintf(buf, NOX("2_CrIm%.2d"), Credits_artwork_index);
		} else {
			sprintf(buf, NOX("CrIm%.2d"), Credits_artwork_index);
		}
		Credits_bmps[Credits_artwork_index] = bm_load(buf);
	}

	if (Credits_bmps[next] < 0) {
		char buf[40];

		if (gr_screen.res == GR_1024) {
			sprintf(buf, NOX("2_CrIm%.2d"), Credits_artwork_index);
		} else {
			sprintf(buf, NOX("CrIm%.2d"), next);
		}
		Credits_bmps[next] = bm_load(buf);
	}

	bm1 = Credits_bmps[Credits_artwork_index];
	bm2 = Credits_bmps[next];

	if((bm1 != -1) && (bm2 != -1)){
		Assert(percent >= 0 && percent <= 100);

		bm_get_info(bm1, &bw1, &bh1, NULL, NULL, NULL);	
		bm_get_info(bm2, &bw2, &bh2, NULL, NULL, NULL);	

		bx1 = Credits_image_coords[gr_screen.res][CREDITS_X_COORD] + ((Credits_image_coords[gr_screen.res][CREDITS_W_COORD] - bw1)/2);
		by1 = Credits_image_coords[gr_screen.res][CREDITS_Y_COORD] + ((Credits_image_coords[gr_screen.res][CREDITS_H_COORD] - bh1)/2);
		bx2 = Credits_image_coords[gr_screen.res][CREDITS_X_COORD] + ((Credits_image_coords[gr_screen.res][CREDITS_W_COORD] - bw2)/2);
		by2 = Credits_image_coords[gr_screen.res][CREDITS_Y_COORD] + ((Credits_image_coords[gr_screen.res][CREDITS_H_COORD] - bh2)/2);

		gr_cross_fade(bm1, bm2, bx1, by1, bx2, by2, (float)percent / 100.0f);
	}

#ifdef MAKE_FS1
	if (CreditsWin01 != -1) {
		gr_set_bitmap(CreditsWin01, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
		gr_bitmap(233, 5);
	}

	if (CreditsWin02 != -1) {
		gr_set_bitmap(CreditsWin02, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
		gr_bitmap(616, 8);
	}

	if (CreditsWin03 != -1) {
		gr_set_bitmap(CreditsWin03, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
		gr_bitmap(233, 299);
	}

	if (CreditsWin04 != -1) {
		gr_set_bitmap(CreditsWin04, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
		gr_bitmap(215, 8);
	}
#endif

	Ui_window.draw();

	for (i=TECH_DATABASE_BUTTON; i<=CREDITS_BUTTON; i++){
		if (Buttons[i][gr_screen.res].button.button_down()){
			break;
		}
	}

	if (i > CREDITS_BUTTON){
		Buttons[CREDITS_BUTTON][gr_screen.res].button.draw_forced(2);
	}

	gr_set_clip(Credits_text_coords[gr_screen.res][CREDITS_X_COORD], Credits_text_coords[gr_screen.res][CREDITS_Y_COORD], Credits_text_coords[gr_screen.res][CREDITS_W_COORD], Credits_text_coords[gr_screen.res][CREDITS_H_COORD]);
	gr_set_font(FONT1);
	gr_set_color_fast(&Color_normal);

	int sy;
	if ( Credit_position > 0 ) {
		sy = fl2i(Credit_position+0.5f);
	} else {
		sy = fl2i(Credit_position-0.5f);
	}

	if(gr_screen.mode == GR_GLIDE){
#ifndef PLAT_UNIX
		extern void gr_glide_string_hack(int sx, int sy, char *s);
		gr_glide_string_hack(0x8000, sy, Credit_text);
#endif
	} else {
		gr_string(0x8000, sy, Credit_text);
	}

	int temp_time;
	temp_time = timer_get_milliseconds();

	Credits_frametime = temp_time - Credits_last_time;
	Credits_last_time = temp_time;
	timestamp_inc(Credits_frametime / 1000.0f);

	float fl_frametime = i2fl(Credits_frametime) / 1000.f;
	if (keyd_pressed[KEY_LSHIFT]) {
		Credit_position -= fl_frametime * CREDITS_SCROLL_RATE * 4.0f;
	} else {
		Credit_position -= fl_frametime * CREDITS_SCROLL_RATE;
	}

	if (Credit_position < Credit_stop_pos){
		Credit_position = Credit_start_pos;
	}

	Credits_counter += fl_frametime;
	while (Credits_counter >= CREDITS_ARTWORK_DISPLAY_TIME) {
		Credits_counter -= CREDITS_ARTWORK_DISPLAY_TIME;
		Credits_artwork_index = next;
	}

	gr_flip();
}
/*
 * Copyright (C) Volition, Inc. 1999.  All rights reserved.
 *
 * All source code herein is the property of Volition, Inc. You may not sell 
 * or otherwise commercially exploit the source or things you created based on
 * the source.
 */

/*
 * $Logfile: /Freespace2/code/MenuUI/Credits.cpp $
 * $Revision: 307 $
 * $Date: 2010-02-08 09:09:13 +0100 (Mon, 08 Feb 2010) $
 * $Author: taylor $
 *
 * C source file for displaying game credits
 *
 * $Log$
 * Revision 1.9  2005/03/29 02:18:47  taylor
 * Various 64-bit platform fixes
 * Fix compiler errors with MAKE_FS1 and fix gr_set_bitmap() too
 * Make sure that turrets can fire at asteroids for FS1 (needed for a couple missions)
 * Streaming audio support (big thanks to Pierre Willenbrock!!)
 * Removed dependance on strings.tbl for FS1 since we don't actually need it now
 *
 * Revision 1.8  2004/09/20 01:31:44  theoddone33
 * GCC 3.4 fixes.
 *
 * Revision 1.7  2003/08/03 16:10:29  taylor
 * cleanup; compile warning fixes
 *
 * Revision 1.6  2003/06/11 18:30:32  taylor
 * plug memory leaks
 *
 * Revision 1.5  2003/05/25 02:30:42  taylor
 * Freespace 1 support
 *
 * Revision 1.4  2002/06/09 04:41:22  relnev
 * added copyright header
 *
 * Revision 1.3  2002/05/27 22:43:02  theoddone33
 * Fix more glide symbols
 *
 * Revision 1.2  2002/05/07 03:16:46  theoddone33
 * The Great Newline Fix
 *
 * Revision 1.1.1.1  2002/05/03 03:28:09  root
 * Initial import.
 *
 * 
 * 20    9/14/99 5:14a Dave
 * Fixed credits drawing in Glide.
 * 
 * 19    9/13/99 1:53p Dave
 * Fixed completely brain dead code in credits_init().
 * 
 * 18    9/09/99 10:55a Jefff
 * 
 * 17    9/03/99 11:45a Jefff
 * 
 * 16    9/01/99 5:28p Jefff
 * hi res art shows up now
 * 
 * 15    9/01/99 4:20p Jefff
 * mo' pictures
 * 
 * 14    9/01/99 12:19p Jefff
 * text splitting for long lines
 * 
 * 13    7/19/99 2:13p Dave
 * Added some new strings for Heiko.
 * 
 * 12    2/03/99 6:06p Dave
 * Groundwork for FS2 PXO usertracker support.  Gametracker support next.
 * 
 * 11    2/03/99 11:44a Dave
 * Fixed d3d transparent textures.
 * 
 * 10    2/01/99 5:55p Dave
 * Removed the idea of explicit bitmaps for buttons. Fixed text
 * highlighting for disabled gadgets.
 * 
 * 9     1/30/99 9:01p Dave
 * Coord fixes.
 * 
 * 8     1/30/99 5:08p Dave
 * More new hi-res stuff.Support for nice D3D textures.
 * 
 * 7     1/29/99 12:47a Dave
 * Put in sounds for beam weapon. A bunch of interface screens (tech
 * database stuff).
 * 
 * 6     1/28/99 1:46a Dave
 * Updated coords and bitmaps.
 * 
 * 5     1/14/99 5:15p Neilk
 * changed credits, command debrief interfaces to high resolution support
 * 
 * 4     11/20/98 4:08p Dave
 * Fixed flak effect in multiplayer.
 * 
 * 3     10/13/98 9:28a Dave
 * Started neatening up freespace.h. Many variables renamed and
 * reorganized. Added AlphaColors.[h,cpp]
 * 
 * 2     10/07/98 10:53a Dave
 * Initial checkin.
 * 
 * 1     10/07/98 10:49a Dave
 * 
 * 18    6/19/98 3:51p Lawrance
 * deal with foreign chars in the credits
 * 
 * 17    6/01/98 11:43a John
 * JAS & MK:  Classified all strings for localization.
 * 
 * 16    5/24/98 9:01p Lawrance
 * Add commit sounds when accept is pressed
 * 
 * 15    5/20/98 1:04p Hoffoss
 * Made credits screen use new artwork and removed rating field usage from
 * Fred (a goal struct member).
 * 
 * 14    5/12/98 4:17p Hoffoss
 * Make ctrl-arrows (up/down) switch between tech room screens.
 * 
 * 13    5/12/98 11:21a Hoffoss
 * Disabled cutscene screen and simulator room.
 * 
 * 12    5/11/98 8:04p Hoffoss
 * Fixed minor bugs.
 * 
 * 11    4/22/98 3:35p John
 * String externalization marking
 * 
 * 10    4/22/98 10:46a Hoffoss
 * Added images to credits screen.
 * 
 * 9     4/21/98 7:07p Hoffoss
 * Fixed problem where when switching screens flashes old tab hilight once
 * before switching to new state.
 * 
 * 8     4/17/98 3:28p Hoffoss
 * Added new credits screen code.
 * 
 * 7     3/05/98 11:15p Hoffoss
 * Changed non-game key checking to use game_check_key() instead of
 * game_poll().
 * 
 * 6     2/22/98 12:19p John
 * Externalized some strings
 * 
 * 5     1/05/98 2:30p John
 * made credits.tbl display
 * 
 * 4     9/19/97 5:14p Lawrance
 * use new naming convention for spooled music
 * 
 * 3     8/31/97 6:38p Lawrance
 * pass in frametime to do_frame loop
 * 
 * 2     4/22/97 11:06a Lawrance
 * credits music playing, credits screen is a separate state
 *
 * $NoKeywords: $
 */

#include <stdlib.h>

#include "gamesequence.h"
#include "font.h"
#include "key.h"
#include "bmpman.h"
#include "2d.h"
#include "timer.h"
#include "gamesnd.h"
#include "audiostr.h"
#include "eventmusic.h"	/* for Master_event_music_volume */
#include "cfile.h"
#include "ui.h"
#include "missionscreencommon.h"
#include "player.h"
#include "freespace.h"
#include "alphacolors.h"
#include "localize.h"

#define CREDITS_MUSIC_DELAY	2000
#define CREDITS_SCROLL_RATE	15.0f
#define CREDITS_ARTWORK_DISPLAY_TIME	9.0f
#define CREDITS_ARTWORK_FADE_TIME		1.0f

#define NUM_BUTTONS				5
#define NUM_IMAGES				46

#define TECH_DATABASE_BUTTON	0
#define SIMULATOR_BUTTON		1
#define CUTSCENES_BUTTON		2
#define CREDITS_BUTTON			3
#define EXIT_BUTTON				4

// inidicies for coordinates
#define CREDITS_X_COORD 0
#define CREDITS_Y_COORD 1
#define CREDITS_W_COORD 2
#define CREDITS_H_COORD 3

static const char* Credits_bitmap_fname[GR_NUM_RESOLUTIONS] = {
	"Credits",			// GR_640
	"2_Credits"
};

static const char* Credits_bitmap_mask_fname[GR_NUM_RESOLUTIONS] = {
	"Credits-M",			// GR_640
	"2_Credits-M"
};

int Credits_image_coords[GR_NUM_RESOLUTIONS][4] = {
	{
#ifdef MAKE_FS1
		225, 15, 400, 292
#else
		219, 15, 394, 286			// GR_640
#endif
	},
	{
		351, 25, 629, 455			// GR_1024
	}
};

// x, y, w, h
int Credits_text_coords[GR_NUM_RESOLUTIONS][4] = {
	{
#ifdef MAKE_FS1
		46, 321, 450, 134
#else
		26, 316, 482, 157			// GR_640
#endif
	},
	{
		144, 507, 568, 249			// GR_640
	}
};

struct credits_screen_buttons {
	const char *filename;
	int x, y, xt, yt;
	int hotspot;
	UI_BUTTON button;  // because we have a class inside this struct, we need the constructor below..

	credits_screen_buttons(const char *name, int x1, int y1, int xt1, int yt1, int h) : filename(name), x(x1), y(y1), xt(xt1), yt(yt1), hotspot(h) {}
};

static int Background_bitmap;
#ifdef MAKE_FS1
static int CreditsWin01 = -1;
static int CreditsWin02 = -1;
static int CreditsWin03 = -1;
static int CreditsWin04 = -1;
#endif

static UI_WINDOW Ui_window;

static credits_screen_buttons Buttons[NUM_BUTTONS][GR_NUM_RESOLUTIONS] = {
//XSTR:OFF
#ifdef MAKE_FS1
    {
			credits_screen_buttons("TDB_00", 0, 0, -1, -1, 0),		// GR_640
			credits_screen_buttons("2_TDB_00", 12, 5, 59, 12, 0)		// GR_1024
    },
    {
			credits_screen_buttons("TDB_01", 0, 19, -1, -1, 1),		// GR_640
			credits_screen_buttons("2_TDB_01", 12, 31, 59, 37, 1)		// GR_1024
    },
    {
			credits_screen_buttons("TDB_02", 0, 35, -1, -1, 2),		// GR_640
			credits_screen_buttons("2_TDB_02", 12, 56, 59, 62, 2)		// GR_1024
    },
    {
			credits_screen_buttons("TDB_03", 0, 56, -1, -1, 3),		// GR_640
			credits_screen_buttons("2_TDB_03", 12, 81, 59, 88, 3)		// GR_1024
    },
    {
			credits_screen_buttons("CRB_04", 561, 411, -1, -1, 4),	// GR_640
			credits_screen_buttons("2_CRB_04", 914, 681, 953, 68, 4)	// GR_1024
    }
#else
	{
			credits_screen_buttons("TDB_00", 7, 3, 37, 7, 0),			// GR_640
			credits_screen_buttons("2_TDB_00", 12, 5, 59, 12, 0)			// GR_1024
	},
	{
			credits_screen_buttons("TDB_01", 7, 18, 37, 23,	1),		// GR_640
			credits_screen_buttons("2_TDB_01", 12, 31, 59, 37, 1)		// GR_1024
	},
	{
			credits_screen_buttons("TDB_02", 7, 34, 37, 38, 2),		// GR_640
			credits_screen_buttons("2_TDB_02", 12, 56, 59, 62, 2)		// GR_1024
	},
	{
			credits_screen_buttons("TDB_03", 7, 49, 37, 54,	3),		// GR_640
			credits_screen_buttons("2_TDB_03", 12, 81, 59, 88, 3)		// GR_1024
	},
	{
			credits_screen_buttons("CRB_04", 571, 425, 588, 413, 4),	// GR_640
			credits_screen_buttons("2_CRB_04", 914, 681, 953, 668, 4)	// GR_1024
	}
#endif
//XSTR:ON
};

static int	Credits_music_handle = -1;
static int	Credits_music_begin_timestamp;

static int	Credits_frametime;		// frametime of credits_do_frame() loop in ms
static int	Credits_last_time;		// timestamp used to calc frametime (in ms)
static float Credits_counter;
static int Credits_artwork_index;
static int Credits_bmps[NUM_IMAGES];

char *Credit_text = NULL;

// Positions for credits...
float Credit_start_pos, Credit_stop_pos, Credit_position = 0.0f;

void credits_stop_music()
{
	if ( Credits_music_handle != -1 ) {
		audiostream_close_file(Credits_music_handle);
		Credits_music_handle = -1;
	}
}

void credits_load_music(const char* fname)
{
	if ( Credits_music_handle != -1 ){
		return;
	}

	if ( fname ){
		Credits_music_handle = audiostream_open( fname, ASF_EVENTMUSIC );
	}
}

void credits_start_music()
{
	if (Credits_music_handle != -1) {
		if ( !audiostream_is_playing(Credits_music_handle) ){
			audiostream_play(Credits_music_handle, Master_event_music_volume);
		}
	} else {
		nprintf(("Warning", "Cannot play credits music\n"));
	}
}

int credits_screen_button_pressed(int n)
{
	switch (n) {
	case TECH_DATABASE_BUTTON:
		gamesnd_play_iface(SND_SWITCH_SCREENS);
		gameseq_post_event(GS_EVENT_TECH_MENU);
		return 1;

	case SIMULATOR_BUTTON:
		gamesnd_play_iface(SND_SWITCH_SCREENS);
		gameseq_post_event(GS_EVENT_SIMULATOR_ROOM);
		return 1;

	case CUTSCENES_BUTTON:
		gamesnd_play_iface(SND_SWITCH_SCREENS);
		gameseq_post_event(GS_EVENT_GOTO_VIEW_CUTSCENES_SCREEN);
		return 1;

	case EXIT_BUTTON:
		gamesnd_play_iface(SND_COMMIT_PRESSED);
		gameseq_post_event(GS_EVENT_MAIN_MENU);
		game_flush();
		break;
	}

	return 0;
}

void credits_init()
{
	int i, w, h;
	credits_screen_buttons *b;
	char line[512] = "";	
	char *linep1, *linep2;	

	int credits_spooled_music_index = event_music_get_spooled_music_index("Cinema");	
	if(credits_spooled_music_index != -1){
		char *credits_wavfile_name = Spooled_music[credits_spooled_music_index].filename;		
		if(credits_wavfile_name != NULL){
			credits_load_music(credits_wavfile_name);
		}
	}

	// Use this id to trigger the start of music playing on the briefing screen
	Credits_music_begin_timestamp = timestamp(CREDITS_MUSIC_DELAY);

	Credits_frametime = 0;
	Credits_last_time = timer_get_milliseconds();

	Credit_text = NULL;

	// allocate enough space for credits text
	CFILE *fp = cfopen( NOX("credits.tbl"), "rb" );
	if(fp != NULL){
		int size;
		size = cfilelength(fp);
		Credit_text = (char *) malloc(size + 200);
		cfclose(fp);

		// open localization and parse
		lcl_ext_open();
		read_file_text("credits.tbl");
		reset_parse();

		// keep reading everything in
		strcpy(Credit_text,"");		
#ifndef MAKE_FS1
		while(!check_for_string_raw("#end")){
#else
		char *ugh = Mp;
		char ch;
		int line_count = 0;

		// get the line count, probably a crappy way to do it but it's the best way i've
		// found to step through the credits without crashing problems since there's no
		// definite end line in FS1
		while (*ugh && *ugh != EOF_CHAR) {
			ch = *ugh;

			if (ch == '\n'){
				line_count++;
			}
			ugh++;
		}

		while(line_count > 0){
			line_count--;
#endif
			stuff_string_line(line, 511);
			linep1 = line;

			do {
				linep2 = split_str_once(linep1, Credits_text_coords[gr_screen.res][2]);
				strcat(Credit_text, linep1);
				strcat(Credit_text, "\n");			
				linep1 = linep2;
			} while (linep2 != NULL);
		}		

		// close localization
		lcl_ext_close();	
	} else {
		Credit_text = (char *) malloc(25 + 200);
		strcpy(Credit_text, NOX("No credits available.\n"));
	}	

	int ch;
	for ( i = 0; Credit_text[i]; i++ ) {
			ch = Credit_text[i];
			switch (ch) {
			case -4:
				ch = 129;
				break;

			case -28:
				ch = 132;
				break;

			case -10:
				ch = 148;
				break;

			case -23:
				ch = 130;
				break;

			case -30:
				ch = 131;
				break;

			case -25:
				ch = 135;
				break;

			case -21:
				ch = 137;
				break;

			case -24:
				ch = 138;
				break;

			case -17:
				ch = 139;
				break;

			case -18:
				ch = 140;
				break;

			case -60:
				ch = 142;
				break;

			case -55:
				ch = 144;
				break;

			case -12:
				ch = 147;
				break;

			case -14:
				ch = 149;
				break;

			case -5:
				ch = 150;
				break;

			case -7:
				ch = 151;
				break;

			case -42:
				ch = 153;
				break;

			case -36:
				ch = 154;
				break;

			case -31:
				ch = 160;
				break;

			case -19:
				ch = 161;
				break;

			case -13:
				ch = 162;
				break;

			case -6:
				ch = 163;
				break;

			case -32:
				ch = 133;
				break;

			case -22:
				ch = 136;
				break;

			case -20:
				ch = 141;
				break;
			}
			Credit_text[i] = (char)ch;
	}

	gr_get_string_size(&w, &h, Credit_text);

	Credit_start_pos = i2fl(Credits_text_coords[gr_screen.res][CREDITS_H_COORD]);
	Credit_stop_pos = -i2fl(h);
	Credit_position = Credit_start_pos;

	Ui_window.create(0, 0, gr_screen.max_w, gr_screen.max_h, 0);
	Ui_window.set_mask_bmap(Credits_bitmap_mask_fname[gr_screen.res]);
	common_set_interface_palette("InterfacePalette");  // set the interface palette

	for (i=0; i<NUM_BUTTONS; i++) {
		b = &Buttons[i][gr_screen.res];

		b->button.create(&Ui_window, "", b->x, b->y, 60, 30, (i < 2), 1);
		// set up callback for when a mouse first goes over a button
		b->button.set_highlight_action(common_play_highlight_sound);
		b->button.set_bmaps(b->filename);
		b->button.link_hotspot(b->hotspot);
	}

#ifndef MAKE_FS1
	// add some text
	Ui_window.add_XSTR("Technical Database", 1055, Buttons[TECH_DATABASE_BUTTON][gr_screen.res].xt,  Buttons[TECH_DATABASE_BUTTON][gr_screen.res].yt, &Buttons[TECH_DATABASE_BUTTON][gr_screen.res].button, UI_XSTR_COLOR_GREEN);
	Ui_window.add_XSTR("Mission Simulator", 1056, Buttons[SIMULATOR_BUTTON][gr_screen.res].xt,  Buttons[SIMULATOR_BUTTON][gr_screen.res].yt, &Buttons[SIMULATOR_BUTTON][gr_screen.res].button, UI_XSTR_COLOR_GREEN);
	Ui_window.add_XSTR("Cutscenes", 1057, Buttons[CUTSCENES_BUTTON][gr_screen.res].xt,  Buttons[CUTSCENES_BUTTON][gr_screen.res].yt, &Buttons[CUTSCENES_BUTTON][gr_screen.res].button, UI_XSTR_COLOR_GREEN);
	Ui_window.add_XSTR("Credits", 1058, Buttons[CREDITS_BUTTON][gr_screen.res].xt,  Buttons[CREDITS_BUTTON][gr_screen.res].yt, &Buttons[CREDITS_BUTTON][gr_screen.res].button, UI_XSTR_COLOR_GREEN);
	Ui_window.add_XSTR("Exit", 1420, Buttons[EXIT_BUTTON][gr_screen.res].xt,  Buttons[EXIT_BUTTON][gr_screen.res].yt, &Buttons[EXIT_BUTTON][gr_screen.res].button, UI_XSTR_COLOR_PINK);
#endif

	if (Player->flags & PLAYER_FLAGS_IS_MULTI) {
		Buttons[SIMULATOR_BUTTON][gr_screen.res].button.disable();
		Buttons[CUTSCENES_BUTTON][gr_screen.res].button.disable();
	}

	Buttons[EXIT_BUTTON][gr_screen.res].button.set_hotkey(KEY_CTRLED | KEY_ENTER);

	Background_bitmap = bm_load(Credits_bitmap_fname[gr_screen.res]);
	Credits_artwork_index = rand() % NUM_IMAGES;
	for (i=0; i<NUM_IMAGES; i++){
		Credits_bmps[i] = -1;
	}

#ifdef MAKE_FS1
	CreditsWin01 = bm_load(NOX("CreditsWin01"));
	CreditsWin02 = bm_load(NOX("CreditsWin02"));
	CreditsWin03 = bm_load(NOX("CreditsWin03"));
	CreditsWin04 = bm_load(NOX("CreditsWin04"));
#endif
}

void credits_close()
{	
	int i;

#ifdef MAKE_FS1
	if (CreditsWin01 != -1){
		bm_unload(CreditsWin01);
		CreditsWin01 = -1;
	}
	if (CreditsWin02 != -1){
		bm_unload(CreditsWin02);
		CreditsWin02 = -1;
	}
	if (CreditsWin03 != -1){
		bm_unload(CreditsWin03);
		CreditsWin03 = -1;
	}
	if (CreditsWin04 != -1){
		bm_unload(CreditsWin04);
		CreditsWin04 = -1;
	}
#endif

	for (i=0; i<NUM_IMAGES; i++){
		if (Credits_bmps[i] >= 0){
			bm_unload(Credits_bmps[i]);
			Credits_bmps[i] = -1;
		}
	}	

	credits_stop_music();

	if (Credit_text) {
		free(Credit_text);
		Credit_text = NULL;
	}

	if (Background_bitmap){
		bm_unload(Background_bitmap);
	}

	Ui_window.destroy();
	common_free_interface_palette();		// restore game palette
}

void credits_do_frame(float frametime)
{
	int i, k, next, percent, bm1, bm2;
	int bx1, by1, bw1, bh1;
	int bx2, by2, bw2, bh2;

	// Use this id to trigger the start of music playing on the credits screen
	if ( timestamp_elapsed(Credits_music_begin_timestamp) ) {
		Credits_music_begin_timestamp = 0;
		credits_start_music();
	}

	k = Ui_window.process();
	switch (k) {
	case KEY_ESC:
		gameseq_post_event(GS_EVENT_MAIN_MENU);
		key_flush();
		break;

	case KEY_CTRLED | KEY_UP:
	case KEY_SHIFTED | KEY_TAB:
		if ( !(Player->flags & PLAYER_FLAGS_IS_MULTI) ) {
			credits_screen_button_pressed(CUTSCENES_BUTTON);
			break;
		}
		// else, react like tab key.

	case KEY_CTRLED | KEY_DOWN:
	case KEY_TAB:
		credits_screen_button_pressed(TECH_DATABASE_BUTTON);
		break;

	default:
		break;
	} // end switch

	for (i=0; i<NUM_BUTTONS; i++){
		if (Buttons[i][gr_screen.res].button.pressed()){
			if (credits_screen_button_pressed(i)){
				return;
			}
		}
	}

	gr_reset_clip();	
	GR_MAYBE_CLEAR_RES(Background_bitmap);
	if (Background_bitmap >= 0) {
		gr_set_bitmap(Background_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
		gr_bitmap(0, 0);
	} 

	percent = (int) (100.0f - (CREDITS_ARTWORK_DISPLAY_TIME - Credits_counter) * 100.0f / CREDITS_ARTWORK_FADE_TIME);
	if (percent < 0){
		percent = 0;
	}

	next = Credits_artwork_index + 1;
	if (next >= NUM_IMAGES){
		next = 0;
	}

	if (Credits_bmps[Credits_artwork_index] < 0) {
		char buf[40];

		if (gr_screen.res == GR_1024) {
			sprintf(buf, NOX("2_CrIm%.2d"), Credits_artwork_index);
		} else {
			sprintf(buf, NOX("CrIm%.2d"), Credits_artwork_index);
		}
		Credits_bmps[Credits_artwork_index] = bm_load(buf);
	}

	if (Credits_bmps[next] < 0) {
		char buf[40];

		if (gr_screen.res == GR_1024) {
			sprintf(buf, NOX("2_CrIm%.2d"), Credits_artwork_index);
		} else {
			sprintf(buf, NOX("CrIm%.2d"), next);
		}
		Credits_bmps[next] = bm_load(buf);
	}

	bm1 = Credits_bmps[Credits_artwork_index];
	bm2 = Credits_bmps[next];

	if((bm1 != -1) && (bm2 != -1)){
		Assert(percent >= 0 && percent <= 100);

		// get width and height
		bm_get_info(bm1, &bw1, &bh1, NULL, NULL, NULL);	
		bm_get_info(bm2, &bw2, &bh2, NULL, NULL, NULL);	
	
		// determine where to draw the coords
		bx1 = Credits_image_coords[gr_screen.res][CREDITS_X_COORD] + ((Credits_image_coords[gr_screen.res][CREDITS_W_COORD] - bw1)/2);
		by1 = Credits_image_coords[gr_screen.res][CREDITS_Y_COORD] + ((Credits_image_coords[gr_screen.res][CREDITS_H_COORD] - bh1)/2);
		bx2 = Credits_image_coords[gr_screen.res][CREDITS_X_COORD] + ((Credits_image_coords[gr_screen.res][CREDITS_W_COORD] - bw2)/2);
		by2 = Credits_image_coords[gr_screen.res][CREDITS_Y_COORD] + ((Credits_image_coords[gr_screen.res][CREDITS_H_COORD] - bh2)/2);

		gr_cross_fade(bm1, bm2, bx1, by1, bx2, by2, (float)percent / 100.0f);
	}

#ifdef MAKE_FS1
	if (CreditsWin01 != -1) {
		gr_set_bitmap(CreditsWin01, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
		gr_bitmap(233, 5);
	}

	if (CreditsWin02 != -1) {
		gr_set_bitmap(CreditsWin02, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
		gr_bitmap(616, 8);
	}

	if (CreditsWin03 != -1) {
		gr_set_bitmap(CreditsWin03, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
		gr_bitmap(233, 299);
	}

	if (CreditsWin04 != -1) {
		gr_set_bitmap(CreditsWin04, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
		gr_bitmap(215, 8);
	}
#endif

	Ui_window.draw();

	for (i=TECH_DATABASE_BUTTON; i<=CREDITS_BUTTON; i++){
		if (Buttons[i][gr_screen.res].button.button_down()){
			break;
		}
	}

	if (i > CREDITS_BUTTON){
		Buttons[CREDITS_BUTTON][gr_screen.res].button.draw_forced(2);
	}

	gr_set_clip(Credits_text_coords[gr_screen.res][CREDITS_X_COORD], Credits_text_coords[gr_screen.res][CREDITS_Y_COORD], Credits_text_coords[gr_screen.res][CREDITS_W_COORD], Credits_text_coords[gr_screen.res][CREDITS_H_COORD]);
	gr_set_font(FONT1);
	gr_set_color_fast(&Color_normal);

	int sy;
	if ( Credit_position > 0 ) {
		sy = fl2i(Credit_position+0.5f);
	} else {
		sy = fl2i(Credit_position-0.5f);
	}

	// HACK - I don't want to change the string code, so we'll just use a special version here
	if(gr_screen.mode == GR_GLIDE){
#ifndef PLAT_UNIX
		extern void gr_glide_string_hack(int sx, int sy, char *s);
		gr_glide_string_hack(0x8000, sy, Credit_text);
#endif
	} else {
		gr_string(0x8000, sy, Credit_text);
	}

	int temp_time;
	temp_time = timer_get_milliseconds();

	Credits_frametime = temp_time - Credits_last_time;
	Credits_last_time = temp_time;
	timestamp_inc(Credits_frametime / 1000.0f);

	float fl_frametime = i2fl(Credits_frametime) / 1000.f;
	if (keyd_pressed[KEY_LSHIFT]) {
		Credit_position -= fl_frametime * CREDITS_SCROLL_RATE * 4.0f;
	} else {
		Credit_position -= fl_frametime * CREDITS_SCROLL_RATE;
	}

	if (Credit_position < Credit_stop_pos){
		Credit_position = Credit_start_pos;
	}

	Credits_counter += fl_frametime;
	while (Credits_counter >= CREDITS_ARTWORK_DISPLAY_TIME) {
		Credits_counter -= CREDITS_ARTWORK_DISPLAY_TIME;
		Credits_artwork_index = next;
	}

	gr_flip();
}

