/**********************************************************************************
* AUTHOR		: Deepu V.
* DATE			: 22-AUG-2005
* NAME			: updateRecognitionResults
* DESCRIPTION	: This function tries to update the
*               : shape recognition choices with new shape recognition results
* ARGUMENTS		: results - new results for updating the results
* RETURNS		:
* NOTES			:
* CHANGE HISTROY
* Author			Date				Description of
*************************************************************************************/
int BoxedFieldRecognizer::updateRecognitionResults(const vector<LTKShapeRecoResult>& results, LTKRecognitionContext& rc)
{
	LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)
	    <<"Entering: BoxedFieldRecognizer::updateRecognitionResults"
	    <<endl;

	multimap< float, pair<int,int>, greater<float> >backTrace;
	                   //A multi map is used for finding best N paths
	multimap< float, pair<int,int>, greater<float> >::iterator iter, iterend;
	                   //Iterator for accessing elements of the map
	pair<int,int> combination;
	                   //Temporary variable that keeps a (int,int) pair
	int wordResultIndex, shapeResultIndex;
	                   //loop index variables
	float wordConfidence, shapeConfidence;
	                   //word level and shape level confidences
	unsigned short newSymbol;
	                   //temporary storage for shape recognizer id
	float newConf;     //temporary storage for shape recognizer confidence

	vector<LTKWordRecoResult> newResultVector;
	                   //new results after finding the best N paths

	int numWordRecoResults = rc.getNumResults();
	                   //number of word recognition results requested
	int numShapeRecoResults = results.size();
	                   //number of choices from the shape recognizer
        vector<unsigned short>initVec;
                           //for initializing the trellis



	//If there is no decoded results (First shape recognition in the word)
    if(m_decodedResults.empty())
	{
		//Initializing the results vector
		m_decodedResults.assign(numShapeRecoResults,LTKWordRecoResult());

		//iterating through different word recognition choices
 		for(wordResultIndex = 0; (wordResultIndex<numShapeRecoResults); ++wordResultIndex)
		{
				//Retrieving the shape recognition choices

				newSymbol = results.at(wordResultIndex).getShapeId();
				newConf   = results.at(wordResultIndex).getConfidence();

				//updating the results

				initVec.assign(1,newSymbol);
				m_decodedResults.at(wordResultIndex).setWordRecoResult(initVec,newConf);

		}
	}

    else
	{
		//initializing a temporary result vector
		//newResultVector.assign(smallerResultNumber,LTKWordRecoResult());

		//iterating through each word recognition result
		for(wordResultIndex=0; wordResultIndex<m_decodedResults.size(); ++wordResultIndex)
		{
			wordConfidence = (m_decodedResults.at(wordResultIndex)).getResultConfidence();

			//iterating through each shape recognition results
			for(shapeResultIndex =0; shapeResultIndex<numShapeRecoResults; ++shapeResultIndex )
			{
				//adding total confidence to the map. so that later they
				//can be retrieved in the sorted order
				shapeConfidence = (results.at(shapeResultIndex)).getConfidence();
				backTrace.insert( pair<float, pair<int,int> >( (shapeConfidence+wordConfidence),
					pair<int,int>(wordResultIndex,shapeResultIndex)));
			}
		}

		iterend = backTrace.end();

		//iterating through the map to retrieve the largest confidences.
		for(wordResultIndex = 0,iter = backTrace.begin(); (wordResultIndex<numWordRecoResults)&&(iter!= iterend); ++wordResultIndex,++iter)
		{

			//confidence
			wordConfidence = (*iter).first;

			//the combination that gave this
			//confidence
			combination = (*iter).second;

			//copying the word reco result corresponding to
			//the combination to new result vector
			//newResultVector.at(wordResultIndex) = m_decodedResults.at(combination.first);
			LTKWordRecoResult tempWordRecoResult = m_decodedResults.at(combination.first);

			//retrieving the shape recognition result id
			//and confidence corresponding to the combination
			newSymbol = results.at(combination.second).getShapeId();
			newConf   = results.at(combination.second).getConfidence();

			//updating the word reco result with new id and confidence
			//newResultVector.at(wordResultIndex).updateWordRecoResult(newSymbol, newConf);

				tempWordRecoResult.updateWordRecoResult(newSymbol,newConf);
				newResultVector.push_back(tempWordRecoResult);
		}

		//assigning the newly created result vector
		m_decodedResults = newResultVector;
	}


	LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)
		<<"Exiting: BoxedFieldRecognizer::updateRecognitionResults"
		<<endl;


	return SUCCESS;
}
/**********************************************************************************
* AUTHOR		: Deepu V.
* DATE			: 22-AUG-2005
* NAME			: recognize
* DESCRIPTION	: This is the recognize call
*               : The results of the recognition is set on the Recognition context
*               : object.  In case of BATCH_MODE recognition recognition of every
*               : character is performed.  otherwise the recognizer updates the outputs
*               : with the recognized results
* ARGUMENTS		: rc - The recognition context for the current recognition
* RETURNS		: SUCCESS/FAILURE
* NOTES			:
* CHANGE HISTROY
* Author			Date				Description of
*************************************************************************************/
int BoxedFieldRecognizer::recognize (LTKRecognitionContext& rc)
{
	LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)
	    <<"Entering: BoxedFieldRecognizer::recognize"
	    <<endl;

	string 	tempStr = REC_UNIT_INFO;  //temp string required to pass the arguments to set/get Flags

	int tempFlagValue = 0; //temp int to hold flag values

	int errorCode = 0;

	vector <LTKWordRecoResult>::iterator resultIter,resultEnd;  //iterates through decoded recognition results

	int numWordRecoResults ; //Number of results required by the application

	int resultIndex ; //index to iterate through the results

	vector<unsigned short> resultString; //result

	float normConf; //normalized confidence

	//Returning FAILURE if the recognition context
	//is not segmented into characters

	if((errorCode=rc.getFlag(tempStr,tempFlagValue))!=SUCCESS)
	{
		LOG(LTKLogger::LTK_LOGLEVEL_ERR)
            <<"Error: BoxedFieldRecognizer::recognize"<<endl;

		LTKReturnError(errorCode);
	}

	if( tempFlagValue != REC_UNIT_CHAR)
	{
		LOG(LTKLogger::LTK_LOGLEVEL_ERR)
		    <<"Error : "<< EINVALID_SEGMENT <<":"<< getErrorMessage(EINVALID_SEGMENT)
            <<" BoxedFieldRecognizer::recognize" <<endl;

		LTKReturnError(EINVALID_SEGMENT);
	}

	tempStr =REC_MODE;

	if((errorCode=rc.getFlag(tempStr,tempFlagValue))!=SUCCESS)
	{
		LOG(LTKLogger::LTK_LOGLEVEL_ERR)
            <<"Error: BoxedFieldRecognizer::recognize"<<endl;

		LTKReturnError(errorCode);
	}

	if(tempFlagValue == REC_MODE_BATCH)
	{
		//clear all the recognizer state
		clearRecognizerState();
		recognizeTraces(rc);
	}
	else if (tempFlagValue == REC_MODE_STREAMING)
	{
		recognizeTraces(rc);
	}
	else
	{
		LOG(LTKLogger::LTK_LOGLEVEL_ERR)
		    <<"Error : "<< EINVALID_REC_MODE <<":"<< getErrorMessage(EINVALID_REC_MODE)
            <<" BoxedFieldRecognizer::recognize" <<endl;

		LTKReturnError(EINVALID_REC_MODE);
	}

	/* Now all the recognized results are in
	 * m_decodedResults.
	 */

	resultEnd =	m_decodedResults.end();

	for(resultIter = m_decodedResults.begin(); resultIter != resultEnd ; ++resultIter)
	{
		normConf = (*resultIter).getResultConfidence();

		normConf /= ((*resultIter).getResultWord()).size();

		(*resultIter).setResultConfidence(normConf);

	}

	//number of requested results
	numWordRecoResults =  rc.getNumResults();

	//checking with existing recognition results' size
	if(numWordRecoResults > m_decodedResults.size())
	{
		LOG(LTKLogger::LTK_LOGLEVEL_INFO)
			<< "Don't have enough results to populate. Num of results available = "
			<< m_decodedResults.size() <<", however, results asked for ="
			<< numWordRecoResults <<endl;
	}

	resultEnd = m_decodedResults.end();
	for(resultIndex =0,resultIter = m_decodedResults.begin();(resultIndex <numWordRecoResults)&&(resultIter != resultEnd); ++resultIndex,++resultIter)
	{
		//map the shape ids to unicode IDs
		if((errorCode = LTKStrEncoding::shapeStrToUnicode(m_boxedShapeProject,(*resultIter).getResultWord(),resultString)) != SUCCESS)
		{
			LOG(LTKLogger::LTK_LOGLEVEL_ERR)
            	<<"Error: BoxedFieldRecognizer::recognize"<<endl;

			LTKReturnError(errorCode);
		}

		//adding the recognition result to recognition context
		 rc.addRecognitionResult(LTKWordRecoResult(resultString,
												   (*resultIter).getResultConfidence()));

		resultString.clear();

	}

	//clearing state of the recognizer
	clearRecognizerState();


	LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)
		<<"Exiting: BoxedFieldRecognizer::recognize"
	    <<endl;

	return SUCCESS;
}