#include <stdio.h>
#include <ctype.h>
#include <string.h>


#ifndef _DEBUG
#define ALLEGRO_STATICLINK
#endif

#include <allegro.h>
#include "speechy.h"
#include "voice_mgr.h"

static int gui = TRUE;
static int quit = FALSE;
char path[256] = "allophones/";
static char speech_buffer[4096];

void handle_args(int argc, char* argv[])
{
	// TODO: parse allophone input text
	// TODO: parse allophone path
	strcat(path, "sam");
	gui = TRUE;
}

void close_window_callback(void)
{
	quit = TRUE;
}


void say(VOICE_MGR *voice_mgr, char* text, int save)
{
	int length, length2, id;
	SAMPLE* speak;
	short codes[512];

	voice_parse(voice_mgr, text, codes, 512);
	length = speechy_sequence(voice_mgr->voice, codes);

	if(!length) return;

	speak = create_sample(8, FALSE, voice_mgr->freq, length);
	length2 = speechy_read(voice_mgr->voice, speak->data, length);

	id = play_sample(speak, 255, 128, 1000, 0);

	if(save)
	{
		PACKFILE *pfp;
		int bps = speak->bits/8 * ((speak->stereo) ? 2 : 1);
		int i, s;
		pfp = pack_fopen("out.wav", F_WRITE);
		pack_fputs("RIFF", pfp);                                // RIFF header
		pack_iputl(36+length2, pfp);                            // size of RIFF chunk
		pack_fputs("WAVE", pfp);                                // WAV definition
		pack_fputs("fmt ", pfp);                                // format chunk
		pack_iputl(16, pfp);                                    // size of format chunk
		pack_iputw(1, pfp);                                     // PCM data
		pack_iputw((speak->stereo) ? 2 : 1, pfp);				// mono/stereo data
		pack_iputl(speak->freq, pfp);                           // sample frequency
		pack_iputl(speak->freq*bps, pfp);						// avg. bytes per sec
		pack_iputw(bps, pfp);                                   // block alignment
		pack_iputw(speak->bits, pfp);                           // bits per sample
		pack_fputs("data", pfp);                                // data chunk
		pack_iputl(length2, pfp);                               // actual data length

		if (speak->bits == 8)
		{
			pack_fwrite(speak->data, length2, pfp);				// write the data
		}
		else
		{
			for (i=0; i < (int)speak->len * ((speak->stereo) ? 2 : 1); i++)
			{
				s = ((signed short *)speak->data)[i];
				pack_iputw(s^0x8000, pfp);
			}
		}
		pack_fclose(pfp);    
	}

	while(voice_check(id))
	{
		rest(1);
	}

	destroy_sample(speak);
}

void do_gui(VOICE_MGR* voice)
{
	char text[1025];
	int index = 0;

	while(!quit)
	{
		int keycode; 
		int i, x, y;
		
		x = 0;
		y = 16;

		textout(screen, font, "ENTER to say, TAB to save, and ESC to quit", x, y, 
			makecol(255, 255, 255));

		y += 32;

		for(i = 0; i < (int)voice->phon_count; i++)
		{
			textout(screen, font, voice->phon_list[i].name, x, 16+y, 
				makecol(255, 255, 255));

			x += 4 * 8;
			if(x > SCREEN_W - 4 * 8)
			{
				x = 0;
				y += 16;
			}
		}					
	
		if(keypressed())
		{
			keycode = readkey();

			switch(keycode >> 8)
			{
				case KEY_ESC:
					quit = TRUE;
					break;

				case KEY_TAB:
					say(voice, text, TRUE);
					break;

				case KEY_ENTER:
					say(voice, text, FALSE);
					break;

				case KEY_BACKSPACE:
					index--;
					if(index < 0)
						index = 0;
					break;

				case KEY_DEL:
					index = 0;
					rectfill(screen, 0, SCREEN_H / 2, SCREEN_W - 1, SCREEN_H - 32, 
						makecol(0, 0, 0));
					break;

				default:
					text[index] = keycode & 0xff;
					index++;
					if(index >= 1024)
						index = 1023;
			}

			{
				int i = 0, row = 0, col = 0;
				char str[81];

				for(i = 0; i < 1024; i++)
				{
					if(i<index)
						str[col] = text[i];
					else
						break;

					col++;

					if(col>75)
					{
						str[col] = 0;
						textprintf(screen, font, 16, SCREEN_H / 2 + row * 8,
							makecol(255, 255, 255), "%s ", str);
						col = 0;
						row++;
					}
				}
				
				str[col] = 0;

				textprintf(screen, font, 16, SCREEN_H / 2 + row * 8, 
					makecol(255, 255, 255), "%s ", str);
			}
		}

		rest(10);

		textout(screen, font, "> ", 0, SCREEN_H / 2, makecol(255, 255, 255));
		text[index] = 0;
	}

}

int main(int argc, char *argv[])
{
	VOICE_MGR* voice = NULL;

	if(argc < 2)
	{
		strcat(path, "sam");
	}
	else
	{
		handle_args(argc, argv);
	}

	strcat(path, ".txt");

	allegro_init();
	install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL);

	if(gui)
	{
		install_keyboard();
		set_color_depth(desktop_color_depth());
		set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
		set_close_button_callback(close_window_callback);
	}

	voice = voice_load(path);

	if(!voice)
		return -1;

	if(gui)
	{
		do_gui(voice);	
	}
	else
	{
	}

	voice_unload(voice);

	return 0;
}
END_OF_MAIN()