#include "quiz.h"
#include "trans.h"


static char *z;


extern char *translate_syllable ();
extern char calc_tone ();


char *
translate ( input )
char *input;
{
	static char buf[ MAX_STRING ];
	char *oldz;
	char *bp;
	char *extra;

	z = input;
	bp = buf;
	*bp = '\0';
	while ( *z != '\0' ) {
		oldz = z;
		extra = translate_syllable ();
		if ( extra != NULL ) {
			strcat ( buf , extra );
			strcat ( buf , " " );
		}
		if ( z == oldz )
			break;	/* algorithm failed - give up */
	}
	return ( buf );
}


/*
 *  Does not yet handle:
 *
 * TAH! NAI  (TAW_TAH_HAHN NAW_NOO AH YAW_YAHK)
 * also final consonant seems to be optional 
 *
 */


static char *
translate_syllable ()
{
	static char buf[ 10 ];

	char *initial = NULL;
	char *vowel = NULL;
	char *final = NULL;
	char tone = 'c';
	char initial_char = '\0';
	char final_char = '\0';
	char tone_mark = '\0';

	if ( *z == TC_EH ) {
		z++;
		if ( *z == TC_EH ) {
			z++;
			initial_consonant ( &initial , &initial_char , &tone_mark );
			if ( *z == TC_SHORT_AH ) {
				vowel = "AA!";
				z++;
			}
			else {
				vowel = "AA";
				final_consonant ( &final , &final_char );
			}
		}
		else {
			initial_consonant ( &initial , &initial_char , &tone_mark );
			switch ( *z ) {

			case TC_AW :
				z++;
				if ( *z == TC_SHORT_AH ) {
					z++;
					vowel = "UH!";
				}
				else
					vowel = "UH";
				break;

			case TC_SHORT_AH :
				z++;
				vowel = "EH!";
				break;

			case TC_LONG_AH :
				z++;
				if ( *z == TC_SHORT_AH ) {
					z++;
					vowel = "AW!";
				}
				else {
					vowel = "AO!";
					final_consonant ( &final , &final_char );
				}
				break;

			case TC_IH :
				z++;
				vowel = "UH";
				final_consonant ( &final , &final_char );
				break;

			case TC_EE :
				if ( *(z+1) == TC_YAW_YAHK ) {
					z += 2;
					if ( *z == TC_SHORT_AH ) {
						z++;
						vowel = "IA!";
					}
					else {
						vowel = "IA";
						final_consonant ( &final , &final_char );
					}
				}
				else
					vowel = NULL;	/* error really */
				break;

			case TC_LONG_EU :
				if ( *(z+1) == TC_AW ) {
					z += 2;
					if ( *z == TC_SHORT_AH ) {
						z++;
						vowel = "EUA!";
					}
					else {
						vowel = "EUA";
						final_consonant ( &final , &final_char );
					}
				}
				else
					vowel = NULL;	/* error really */
				break;

			default :
				vowel = "EH";
				final_consonant ( &final , &final_char );
				break;
			}
		}
	}
	else if ( *z == TC_OH ) {
		z++;
		initial_consonant ( &initial , &initial_char , &tone_mark );
		if ( *z == TC_SHORT_AH ) {
			z++;
			vowel = "OH!";
		}
		else {
			vowel = "OH";
			final_consonant ( &final , &final_char );
		}
	}
	else if ( *z == TC_AI20  ||  *z == TC_AI ) {
		z++;
		initial_consonant ( &initial , &initial_char , &tone_mark );
		vowel = "AI!";
		final_consonant ( &final , &final_char );
	}
	else {
		initial_consonant ( &initial , &initial_char , &tone_mark );
		if ( *z == TC_WAW  &&  isconsonant( *(z+1) ) ) {
			z++;
			vowel = "UA";
			final_consonant ( &final , &final_char );
		}
		else if ( *z == TC_RAW_REUA  &&  *(z+1) == TC_RAW_REUA ) {
			vowel = "AH!";
			final_consonant ( &final , &final_char );
		}
		else {
			switch ( *z ) {

			case TC_SHORT_AH :
				z++;
				vowel = "AH!";
				break;

			case TC_SHORT_AH_ABOVE :
				z++;
				if ( *z == TC_WAW ) {
					z++;
					vowel = "UA!";
				}
				else {
					vowel = "AH!";
					final_consonant ( &final , &final_char );
				}
				break;

			case TC_LONG_AH :
				z++;
				if ( *z == TC_WAW ) {
					z++;
					vowel = "AO";
				}
				else if ( *z == TC_YAW_YAHK ) {
					z++;
					vowel = "AI";
				}
				else {
					vowel = "AH";
					final_consonant ( &final , &final_char );
				}
				break;

			case TC_AHM :
				z++;
				vowel = "AH!M";
				break;

			case TC_IH :
				z++;
				vowel = "IH!";
				final_consonant ( &final , &final_char );
				break;

			case TC_EE :
				z++;
				vowel = "EE";
				final_consonant ( &final , &final_char );
				break;

			case TC_SHORT_EU :
				z++;
				vowel = "EU!";
				final_consonant ( &final , &final_char );
				break;

			case TC_LONG_EU :
				z++;
				vowel = "EU";
				final_consonant ( &final , &final_char );
				break;

			case TC_SHORT_OO :
				z++;
				vowel = "OO!";
				final_consonant ( &final , &final_char );
				break;

			case TC_LONG_OO :
				z++;
				vowel = "OO";
				final_consonant ( &final , &final_char );
				break;

			case TC_AW :
				z++;
				vowel = "AW";
				final_consonant ( &final , &final_char );
				break;

			default :
				if ( isconsonant(*z)  &&  ! isaftervowel( *(z+1) ) ) {
					vowel = "OH!";
					final_consonant ( &final , &final_char );
				}
				else {
					vowel = "AH!";
				}
				break;
			}
		}
	}
	tone = calc_tone ( initial , initial_char , tone_mark , vowel ,
		final , final_char );

	strcpy ( buf , "(x)" );
	buf[1] = tone;

	if ( initial != NULL )
		strcat ( buf , initial );
	if ( vowel != NULL )
		strcat ( buf , vowel );
	if ( final != NULL )
		strcat ( buf , final );
	return ( buf );
}


static
initial_consonant ( phoneme , c , tone_mark )
char **phoneme;
char *c;
char *tone_mark;
{
	char dummy;

	*phoneme = NULL;
	*c = *z;

	switch ( *z++ ) {

	case TC_GAW :
		if ( *z == TC_LAW_LEENG ) {
			z++;
			*phoneme = "GL";
		}
		else if ( *z == TC_RAW_REUA ) {
			z++;
			*phoneme = "GR";
		}
		else
			*phoneme = "G";
		break;

	case TC_KAW_KAI :
	case TC_KAW_KUAT :
	case TC_KAW_KWAI :
	case TC_KAW_KOHN :
	case TC_KAW_RAH_KAHNG :
		if ( *z == TC_LAW_LEENG ) {
			z++;
			*phoneme = "KL";
		}
		else if ( *z == TC_RAW_REUA ) {
			z++;
			*phoneme = "KR";
		}
		else
			*phoneme = "K";
		break;

	case TC_NGAW :
		*phoneme = "NG";
		break;

	case TC_JAW :
		*phoneme = "J";
		break;

	case TC_CHAW :
	case TC_CHAW_CHANG :
	case TC_CHAW_CHUH :
		*phoneme = "CH";
		break;

	case TC_SAW :
	case TC_SAW_SAH_LAH :
	case TC_SAW_REU_SEE :
	case TC_SAW_SEUA :
		*phoneme = "S";
		break;

	case TC_YAW_YEENG :
	case TC_YAW_YAHK :
		*phoneme = "Y";
		break;

	case TC_DAW_CHAH_DAH :
	case TC_DAW_DEHK :
		*phoneme = "D";
		break;

	case TC_DTAW_BPAH_DTAHK :
	case TC_DTAW_DTAO :
		*phoneme = "DT";
		break;

	case TC_TAW_TAHN :
	case TC_TAW_MOHN_TOH :
	case TC_TAW_POO_TAO :
	case TC_TAW_TOONG :
	case TC_TAW_TAH_HAHN :
	case TC_TAW_TOHNG :
		*phoneme = "T";
		break;

	case TC_NAW_NEHN :
	case TC_NAW_NOO :
		*phoneme = "N";
		break;

	case TC_BAW :
		*phoneme = "B";
		break;

	case TC_BPAW :
		*phoneme = "BP";
		break;

	case TC_PAW :
	case TC_PAW_PAHN :
	case TC_PAW_SAHM_PAO :
		*phoneme = "P";
		break;

	case TC_FAW_HIGH :
	case TC_FAW :
		*phoneme = "F";
		break;

	case TC_MAW :
		*phoneme = "M";
		break;

	case TC_RAW_REUA :
		*phoneme = "R";
		break;

	case TC_LAW_LEENG :
	case TC_LAW_JOOH_LAH :
		*phoneme = "L";
		break;

	case TC_WAW :
		*phoneme = "W";
		break;

	case TC_AW :
		*phoneme = "AW";
		break;

	case TC_HAW :
		if ( isconsonant ( *z )  &&  ! isaftervowel ( *(z+1) ) )
			initial_consonant ( phoneme , &dummy , tone_mark );
		else
			*phoneme = "H";
		break;

	case TC_HAH :
		*phoneme = "H";
		break;
	}

	switch ( *z ) {

	case TC_MAI_EHK :
	case TC_MAI_TOH :
	case TC_MAI_DTREE :
	case TC_MAI_JATTAWA :
		*tone_mark = *z++;
		break;

	default :
		*tone_mark = '\0';
	}
}


static
final_consonant ( phoneme , c , tone_mark )
char **phoneme;
char *c;
char *tone_mark;
{
	/* check if user put tone mark in wrong spot */

	switch ( *z ) {

	case TC_MAI_EHK :
	case TC_MAI_TOH :
	case TC_MAI_DTREE :
	case TC_MAI_JATTAWA :
		*tone_mark = *z++;
		break;

	default :
		break;	/* dont overide the old value then */
	}

	*c = *z;

	if ( isconsonant( z[0] )  &&  ! isaftervowel( z[1] ) ) {
		switch ( *z++ ) {

		case TC_GAW :
		case TC_KAW_KAI :
		case TC_KAW_KUAT :
		case TC_KAW_KWAI :
		case TC_KAW_KOHN :
		case TC_KAW_RAH_KAHNG :
			*phoneme = "K";
			break;

		case TC_NGAW :
			*phoneme = "NG";
			break;

		case TC_JAW :
		case TC_CHAW :
		case TC_CHAW_CHANG :
		case TC_SAW :
		case TC_CHAW_CHUH :
		case TC_DAW_CHAH_DAH :
		case TC_DTAW_BPAH_DTAHK :
		case TC_TAW_TAHN :
		case TC_TAW_MOHN_TOH :
		case TC_TAW_POO_TAO :
		case TC_DAW_DEHK :
		case TC_DTAW_DTAO :
		case TC_TAW_TOONG :
		case TC_TAW_TAH_HAHN :
		case TC_TAW_TOHNG :
		case TC_SAW_SAH_LAH :
		case TC_SAW_REU_SEE :
		case TC_SAW_SEUA :
			*phoneme = "T";
			break;

		case TC_NAW_NEHN :
		case TC_YAW_YEENG :
		case TC_NAW_NOO :
		case TC_RAW_REUA :
		case TC_LAW_LEENG :
		case TC_LAW_JOOH_LAH :
			*phoneme = "N";
			break;

		case TC_BAW :
		case TC_BPAW :
		case TC_PAW :
		case TC_PAW_PAHN :
		case TC_PAW_SAHM_PAO :
			*phoneme = "P";
			break;

		case TC_FAW :
			*phoneme = "F";
			break;

		case TC_MAW :
			*phoneme = "M";
			break;

		case TC_YAW_YAHK :
		case TC_WAW :
			*phoneme = NULL;
			break;

		case TC_FAW_HIGH :
		case TC_HAW :
		case TC_HAH :
		case TC_AW :
			*phoneme = "";		/* silent */
			break;

		default :
			*phoneme = NULL;
			break;
		}
	}
	else
		*phoneme = NULL;
}


static char
calc_tone ( initial , initial_char , tone_mark , vowel , final , final_char )
char *initial;
char initial_char;
char tone_mark;
char *vowel;
char *final;
char final_char;
{
	char tone;
	int long_vowel;

	tone = 'c';
	if ( initial == NULL  ||  initial[0] == '\0' )
		return ( tone );
	if ( vowel == NULL  ||  vowel[0] == '\0' )
		return ( tone );

	long_vowel = ( vowel[ strlen ( vowel ) - 1 ] != '!' );

	if ( tone_mark == TC_MAI_DTREE )
		tone = 'r';
	else if ( ishigh( initial_char ) ) {
		if ( tone_mark == TC_MAI_TOH ) {
			tone = 'f';
		}
		else if ( final == NULL  ||  final[0] == '\0' ) {
			if ( long_vowel ) {
				if ( tone_mark == '\0' ) {
					tone = 'r';
				}
				else if ( tone_mark == TC_MAI_EHK ) {
					tone = 'l';
				}
			}
			else {
				if ( tone_mark == '\0' ) {
					tone = 'l';
				}
			}
		}
		else {
			switch ( final[0] ) {

			case 'A' :
				if ( final[1] != 'I'  ||  final[1] == 'O' )
					tone = 'r';
				break;

			case 'M' :
			case 'N' :
			case 'W' :
			case 'Y' :
				tone = 'r';
				break;

			case 'K' :
			case 'P' :
			case 'T' :
				tone = 'l';
				break;
			}
		}
	}
	else if ( ismiddle( initial_char ) ) {
		if ( tone_mark == TC_MAI_EHK ) {
			tone = 'l';
		}
		else if ( tone_mark == TC_MAI_TOH ) {
			tone = 'f';
		}
		else {
			if ( final == NULL  ||  final[0] == '\0' ) {
				if ( long_vowel ) {
					if ( tone_mark == '\0' ) {
						tone = 'c';
					}
					else {
					}
				}
				else {
					if ( tone_mark == '\0' ) {
						tone = 'l';
					}
					else {
					}
				}
			}
			else {
				switch ( final[0] ) {

				case 'A' :
					if ( final[1] == 'O'  ||  final[1] == 'I' ) {
						if ( islow( final_char ) ) {
							tone = 'c';
						}
					}
					break;

				case 'M' :
				case 'N' :
				case 'W' :
				case 'Y' :
					if ( islow( final_char ) ) {
						tone = 'c';
					}
					break;

				case 'K' :
				case 'P' :
				case 'T' :
					tone = 'l';
					break;
				}
			}
		}
	}
	else if ( islow( initial_char ) ) {
		if ( tone_mark == TC_MAI_EHK ) {
			tone = 'f';
		}
		else if ( tone_mark == TC_MAI_TOH ) {
			tone = 'h';
		}
		else if ( tone_mark == '\0' ) {
			if ( long_vowel ) {
				if ( final == NULL  ||  final[0] == '\0' ) {
					tone = 'c';
				}
				else {
					switch ( final[0] ) {

					case 'K' :
					case 'P' :
					case 'T' :
						tone = 'f';
						break;
					}
				}
			}
			else {
				if ( final == NULL  ||  final[0] == '\0' ) {
					tone = 'h';
				}
				else {
					switch ( final[0] ) {

					case 'K' :
					case 'P' :
					case 'T' :
						tone = 'h';
						break;

					case 'A' :
						if ( final[1] == 'O'  ||  final[1] == 'I' ) {
							if ( islow( final_char ) ) {
								tone = 'c';
							}
						}
						break;

					case 'M' :
					case 'N' :
					case 'W' :
					case 'Y' :
						if ( islow( final_char ) ) {
							tone = 'c';
						}
						break;
					}
				}
			}
		}
	}
	return ( tone );
}
