/**
 * Copyright (C) 2009 Samsung Electronics Co., Ltd. All rights reserved.
 *
 * Mobile Communication Division,
 * Digital Media & Communications Business, Samsung Electronics Co., Ltd.
 *
 * This software and its documentation are confidential and proprietary
 * information of Samsung Electronics Co., Ltd.  No part of the software and
 * documents may be copied, reproduced, transmitted, translated, or reduced to
 * any electronic medium or machine-readable form without the prior written
 * consent of Samsung Electronics.
 *
 * Samsung Electronics makes no representations with respect to the contents,
 * and assumes no responsibility for any errors that might appear in the
 * software and documents. This publication and the contents hereof are subject
 * to change without notice.
 */

#include <string.h>
#include <memory.h>


#include "et9JapaneseUtil.h"
#include "core/Wnn/src/WnnConvEng.h"
#include "ConvEng.h"

#ifdef ET9_JAPANESE_MODULE
/*----------------------------------------------------------------------------
 * External Variables
 *----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------
 * Global Variables
 *----------------------------------------------------------------------------*/
ET9JWLingCmnInfo g_JLingCmnInfo;

ConvEng *g_pEngineInfo;

#ifdef __cplusplus
extern "C" {
#endif

void* getConvEng() {
    if (g_pEngineInfo == NULL) {
        g_pEngineInfo = new ConvEng;
	    g_pEngineInfo->Init();
    }

    return (void *)g_pEngineInfo;

}

short ET9JUtil_getRangeConvertedPhrase(const int index, unsigned int *outReadingDivInfo, unsigned short *word, unsigned int* outPhraseDivInfo, const int nOutLen) {

	return ((WnnConvEng *)((ConvEng *)getConvEng())->getOpenWnnEng())->GetRangeConvertedPhrase(index, outReadingDivInfo, word, outPhraseDivInfo, nOutLen);
}

short ET9JUtil_startRangeConversion(unsigned short *wordToConv, int wordLen)
{
    if (wordToConv == NULL || wordLen <= 0) {
        return 0;
    }
    //clean up passed in wordToConv.
    ET9U16 *tempWord = new ET9U16[wordLen+1];
    memcpy(tempWord,wordToConv,wordLen*2);
    tempWord[wordLen]=0;
    //bool bRet= ((WnnConvEng *)((ConvEng *)getConvEng())->getOpenWnnEng())->DoRangeConversion(type, tempWord, wordLen);
	bool bRet= ((ConvEng *)getConvEng())->StartYomiConversion(tempWord, 0);
    delete[] tempWord;
    return 0;

}

short ET9JUtil_DoRangeConversion(unsigned short *wordToConv, int wordLen)
{
    if (wordToConv == NULL || wordLen <= 0) {
        return 0;
    }
    //clean up passed in wordToConv.
    ET9U16 *tempWord = new ET9U16[wordLen+1];
    memcpy(tempWord,wordToConv,wordLen*2);
    tempWord[wordLen]=0;
    bool bRet= ((WnnConvEng *)((ConvEng *)getConvEng())->getOpenWnnEng())->DoRangeConversion(1, tempWord, wordLen);
	//bool bRet= ((ConvEng *)getConvEng())->StartYomiConversion(tempWord, 0);
    delete[] tempWord;
    return 0;

}


int ET9JUtil_getRangeConvCandidateWord(const int index, unsigned short* pWordBuf, int *wordLen)
{
    //return ((WnnConvEng *)getConvEng())->GetRangeConvCandidateWord(index, pWordBuf);
    unsigned const short* pMidashigo = ((ConvEng *)getConvEng())->GetMidashigoCandidate(index, 0);


	if (pMidashigo) {
		ET9U16 nLen = 0;
		for (; nLen < ET9MAXWORDSIZE; nLen++) {
			pWordBuf[nLen] = pMidashigo[nLen];
			if (pMidashigo[nLen] == 0) {
			   break;
			}
		}
		*wordLen = nLen;
	}

	
    return 0;
}

short ET9JUtil_getRangeConvCandidateWordCount()
{
    //return ((WnnConvEng *)getConvEng())->GetRangeConvCandidateWordCount();
    return ((ConvEng *)getConvEng())->GetMidashigoCandidateCount();
}

int ET9JUtil_confirmRangeConvWord(int nIndex, const unsigned short* pwSpell, int nSpellLen)
{
    return ((WnnConvEng *)getConvEng())->ConfirmRangeConvWord(nIndex, pwSpell, nSpellLen);

}




/*----------------------------------------------------------------------------
 * Callback Functions
 *----------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------
 *
 *   Function: ET9JHandle_Midashigo_Request
 *
 *   Synopsis: This function handles Midashigo Conversion Engine requests.
 *
 *      Input: pLingInfo = pointer to Japanese information structure
 *             pRequest  = pointer to Midashigo Engine request structure
 *
 *     Return: ET9STATUS_NONE on success, otherwise return  error code.
 *
 *---------------------------------------------------------------------------*/

ET9STATUS ET9FARCALL ET9JHandle_Midashigo_Request(ET9JLingPriv* pLingInfo, ET9JMidashigo_Request * pRequest, void * const pEngineInfo)
{
    ET9STATUS wStatus;
    ConvEng *_pEngineInfo = (ConvEng *)pEngineInfo;

    ET9U8  abRomaji[ET9MAXWORDSIZE + 1] = {0,};
    ET9U8  abYomi  [ET9MAXWORDSIZE] = {0,};

    ET9SYMB sMidashigo[ET9MAXWORDSIZE + 1] = {0,};
    ET9U16  wMidashigoSize = 0;

    const ET9SYMB* psMidashigo = 0;

    int iScore = 0;

    if (pLingInfo == NULL || pRequest == NULL || pEngineInfo == NULL) {

        return ET9STATUS_ERROR;
    }

    wStatus = ET9STATUS_NONE;

    switch(pRequest->eType) {

    case ET9_MIDASHIGO_REQ_NONE : /* nop */
        break;

    case ET9_MIDASHIGO_REQ_START_YOMI_CONVERT:

        if (_pEngineInfo->StartYomiConversion((const unsigned short*)(pRequest->data.sConvYomi.pYomi), pRequest->data.sConvYomi.bIsExact)) {
            pRequest->data.wReturn = _pEngineInfo->GetMidashigoCandidateCount();
        }
        else {
            pRequest->data.wReturn = 0;
            wStatus = ET9STATUS_ERROR;
        }
        break;

    case ET9_MIDASHIGO_REQ_RETRIEVE_MIDASHIGO:

        psMidashigo = (const ET9SYMB*)_pEngineInfo->GetMidashigoCandidate((int)pRequest->data.sRetrieveMid.wMidashigoIndex, &iScore);

        if (psMidashigo) {
            ET9U16 nLen = 0;
            for (; nLen < ET9MAXWORDSIZE; nLen++) {
                pRequest->data.sRetrieveMid.pMidashigo[nLen] = psMidashigo[nLen];
                if (psMidashigo[nLen] == 0) {
                   break;
                }
            }
            pRequest->data.sRetrieveMid.wScore   = (ET9U16)iScore;
            pRequest->data.sRetrieveMid.wWordLen = nLen;
        }
        else {
            pRequest->data.sRetrieveMid.wWordLen = 0;
            wStatus = ET9STATUS_ERROR;
        }

        break;

    case ET9_MIDASHIGO_REQ_START_PREDICTIONS:

        pRequest->data.wReturn = 0;
        if (_pEngineInfo->StartPrediction(0)) {
            pRequest->data.wReturn = _pEngineInfo->GetPredictionCandidateCount();
        }
        break;

    case ET9_MIDASHIGO_REQ_RETRIEVE_PREDICTIONS:

        psMidashigo = (const ET9SYMB*)_pEngineInfo->GetPredictionCandidate((int)pRequest->data.sRetrieveMid.wMidashigoIndex, &iScore);

        if (psMidashigo) {
            ET9U16 nLen = 0;
            for (; nLen < ET9MAXWORDSIZE; nLen++) {
                pRequest->data.sRetrieveMid.pMidashigo[nLen] = psMidashigo[nLen];
                if (psMidashigo[nLen] == 0) {
                   break;
                }
            }
            pRequest->data.sRetrieveMid.wScore   = (ET9U16)iScore;
            pRequest->data.sRetrieveMid.wWordLen = nLen;
        }
        else {
            pRequest->data.sRetrieveMid.wWordLen = 0;
            wStatus = ET9STATUS_ERROR;
        }

        break;

    case ET9_MIDASHIGO_REQ_MIN_SCORE:
        {
            pRequest->data.sMinScore.wScore = 0;
        }
        break;

    case ET9_MIDASHIGO_REQ_ASSIGN_SCORES:
        {
            ET9JYomiInfo *pYomi = pRequest->data.sAssignScores.pYomi;
            ET9JWordInfo *pWord = pRequest->data.sAssignScores.pWord;
            ET9U16 wWordIndex = pRequest->data.sAssignScores.wWordIndex;
            ET9U8 i;
            for (i = 0; i < pYomi->bMidashigoCount; i++) {
                pYomi->sMidashigo[i].nFinalScore = (1 + pYomi->sMidashigo[i].nConvScore) * wWordIndex;
            }
        }
        break;

    case ET9_MIDASHIGO_REQ_UPDATE_PAIR:

        _pEngineInfo->ConfirmCandidate((const unsigned short*)(pRequest->data.sUpdatePair.psYomi), (const unsigned short*)(pRequest->data.sUpdatePair.psMidashigo));
        wStatus = ET9STATUS_NONE;

        break;

    case ET9_MIDASHIGO_REQ_UPDATE_PREDICTION:

        _pEngineInfo->UpdatePrediction((const unsigned short* )(pRequest->data.sUpdatePair.psMidashigo));
        wStatus = ET9STATUS_NONE;

        break;

    case ET9_MIDASHIGO_REQ_BREAK_CONTEXT:

        _pEngineInfo->BreakContext();
        wStatus = ET9STATUS_NONE;

        break;

    default:

        wStatus = ET9STATUS_NO_OPERATION;
        break;

    } /* end switch */
    return(wStatus);
}


#ifdef __cplusplus
}
#endif


/*----------------------------------------------------------------------------
 * Get Functions
 *----------------------------------------------------------------------------*/


/*----------------------------------------------------------------------------
 * Set Functions
 *----------------------------------------------------------------------------*/


#endif // ET9_JAPANESE_MODULE
