// FILE:      BrailleTranslator.m
// AUTHOR:    Daniel Lee (unless stated)
// PURPOSE:   To translate text to braille or vice versa.
// REFERENCE: None. 
// COMMENTS:  
// REQUIRES:  BrailleTranslator.m
// Last Mod:  28-03-2006




#import "BrailleTranslator.h"

@implementation BrailleTranslator


// NAME: init
// PURPOSE: To initialise the data
// IMPORTS: nil
// EXPORTS: nil
// AUTHOR: Daniel Lee
// REMARKS: Used to ensure that the values are initialised properly.
// LAST MODIFIED: 24-03-2006

- (id) init
{

    // This should init the items
	return self;
}


// NAME: changeRules
// PURPOSE: To switch the rules of translation
// IMPORTS: BOOL direction, NSString language, int grade
// EXPORTS: nil
// AUTHOR: Daniel Lee
// REMARKS: 
// LAST MODIFIED: 23-03-2006

void changeRules( BOOL direction, NSString* language, int grade )
{
}


// NAME: translateLine
// PURPOSE: 
// IMPORTS: 
// EXPORTS: 
// AUTHOR: 
// REMARKS: 
// LAST MODIFIED: 28-03-2006

void translateLine( char print_Line[], char braille_Line[] )
{
}


// NAME: hashFunction
// PURPOSE: To return the hash value to which a rule will be applied.
// IMPORTS: char key
// EXPORTS: int index
// AUTHOR: Shannon Thrower
// REMARKS: This function determines the index of the hash table list_array[] to which a rule should be applied.
//          It compares the first letter of the rule's focus to the letter A and typecasts the result to an
//          integer thus defining the index.
// LAST MODIFIED: 28-03-2006

int hashFunction( char key )
{
    int index = (int) key - (int) 'A';

    if( (index < 0) || ( index > 25 ) )
    {
        index = 26;
    }

    return index;
}


/**************************************

   Methods for forward translation

***************************************/


// NAME: translateLineToBraille
// PURPOSE: 
// IMPORTS: 
// EXPORTS: 
// AUTHOR: 
// REMARKS: 
// LAST MODIFIED: 28-03-2006

void translateLineToBraille( char print_line[], char braille_line[] )
{
	int current_state = 1, array_index, match_flag=0, focus_length;
	int focus_match, state_match,
		lctxt_match, rctxt_match; 		// used as flags to represent a match occuring
	char right_of_focus[INPUT_SIZE],	// stores the braille input to the right of the current focus
		 left_of_focus[INPUT_SIZE]="\0"; 	// stores the braille input to the left of the current focus
	char current_character = braille_line[0];
	char focus[FOCUSSIZE], temp_focus[FOCUSSIZE], print_line_copy[INPUT_SIZE];
	rule_t *current_rule;
	int decision_table [5][6]={{1,1,0,0,0,0},	//row represents the current state
							   {1,0,0,0,0,0},	//column represents the current input class
							   {1,0,1,0,0,0},	//rule fires if there is a 1 corresponding to
							   {1,0,0,1,0,0},	//current state and input class
							   {0,0,0,0,1,0}};
	int new_word=1; //flag used to indicate the beginning of a new word


	//initialise variables
	strcpy(print_line_copy, print_line);
	strcpy(right_of_focus, "\0");
	strcpy(braille_line, "\0");

	//remove misc chars. tabs new lines etc
	for (int i=0; i<strlen(print_line);i++){ //for all char in the input string
		if ((int)print_line[i]<32){			 //delete the chars that are misc ie less than 32
			print_line[i]=' ';//note this line actually converts misc chars to space chars
		}
	}


	while(print_line[0] !='\0' && print_line[0] !='\n'){
		match_flag=0;

		//check if capital signs are needed.
		if(new_word && !isspace(print_line[0])){
			if(isalpha(print_line[0])){
				new_word = 0;
			}
			if(isupper(print_line[0])){
				braille_line = strcat(braille_line, ",");
				if(isupper(print_line[1])){
					braille_line = strcat(braille_line, ",");
				}
			}
		}

		//convert the char to upper case for comparison.
		current_character = toupper((int)print_line[0]);
		array_index = (int)current_character-(int)'A';
		if(array_index<0 || array_index>25){
			array_index = 26;
		}


		//search linked list corresponding to array_index for a match
		current_rule = list_array[array_index];

		while(!match_flag && current_rule != NULL){
			strcpy(focus, current_rule->focus); //ie 	focus = current_rule->focus
			focus_length = strlen(focus);

			//check the focus for a match irrelevant of case. Note that windows and linux use different
			//comands to do this.
			//returns 0 if the rule's focus matches the braille word (up to the lengh of the focus)
			//focus_match = strnicmp(focus, print_line, focus_length);		//windows function
			focus_match = strncasecmp(focus, print_line, focus_length);	//linux function

			if (focus_match == 0){
				// the focus has been matched. Now check the state
				// use the rule's state and current input class to check the decision table
				state_match = decision_table[current_state-1][current_rule->input_class-1];
				if (state_match){
					// the state has been matched. now check the left context
					//strncpy(left_of_focus,print_line, position_of_focus);
					lctxt_match = CheckLeftCtxt(current_rule->left_context, left_of_focus);
					if (lctxt_match){
						// the left context has been matched. now check the right context
						strcpy(right_of_focus, &print_line[strlen(current_rule->focus)]);
						// ie. right_of_focus = braille_line from the end of the current focus
						rctxt_match = CheckRightCtxt(current_rule->right_context, right_of_focus);
						if (rctxt_match){
							match_flag=1;
						}
					}
				}
			}
			if(!match_flag){
				//if a match has not been found move to the next rule in the linked list
				current_rule = current_rule->next;
			}
		}
		//a rule has been matched OR the end of the linked list has been reached

		if (match_flag){
			// a match has been found the rule should fire.
			// update the output, the new state and remove the focus from the input braille word

			//update new word flag
			if(!isalpha((int)current_rule->focus[0])){
				new_word=1;
			}

			//update the state
			if (current_rule->next_state != 99){
				current_state = current_rule->next_state;
			}

			//concatenate the output of the rule to the translated word
			//braille_line = strcat(braille_line, current_rule->output);
			strcpy(braille_line, strcat(braille_line, current_rule->output));

			//remove the focus from the input print line and attach it to the left of the focus
			strcpy(print_line, &print_line[focus_length]);
			strcat(left_of_focus, current_rule->focus);
		}else{
/**/		//commented text may be used for debugging new rules
			//printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
			//printf("!!!The translation has exited without a match being found!!!\n");
			//printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
			//printf("the print input was:%s.\n", print_line);
			//printf("The right of focus was:%s.\n", right_of_focus);

			// Print "ERROR" to the output file
			strcpy(braille_line, strcat(braille_line, "\n\n\nERRORe\n\n\n"));
			// remove character from the input
			for (int i=0; i<=strlen(print_line); i++){
				print_line[i]=print_line[i+1];
			}
		}
	}

}


// NAME: 
// PURPOSE: 
// IMPORTS: 
// EXPORTS: 
// AUTHOR: 
// REMARKS: 
// LAST MODIFIED: 28-03-2006

void constructRulesToBraille( char* location )
{
}


// NAME: 
// PURPOSE: 
// IMPORTS: 
// EXPORTS: 
// AUTHOR: 
// REMARKS: 
// LAST MODIFIED: 28-03-2006

int checkLeftCtxt( char left_CTxt[], char left_Of_Focus[] )
{
}


// NAME: 
// PURPOSE: 
// IMPORTS: 
// EXPORTS: 
// AUTHOR: 
// REMARKS: 
// LAST MODIFIED: 28-03-2006

int checkRightCtxt( char right_Ctxt[], char right_Of_Focus[] )
{
}


/**************************************

   Methods for backward translation

***************************************/


// NAME: 
// PURPOSE: 
// IMPORTS: 
// EXPORTS: 
// AUTHOR: 
// REMARKS: 
// LAST MODIFIED: 28-03-2006

void constructRulesFromBraille( char* location )
{
}


// NAME: 
// PURPOSE: 
// IMPORTS: 
// EXPORTS: 
// AUTHOR: 
// REMARKS: 
// LAST MODIFIED: 28-03-2006

void translateLineFromBraille( char print_Line[], char braille_Line[] )
{
}


@end
