/**
 * 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 "ConvEng.h"



#ifdef ET9_JAPANESE_MODULE
/*----------------------------------------------------------------------------
 * External Variables
 *----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------
 * Global Variables
 *----------------------------------------------------------------------------*/
ET9JLingInfo    g_JLingInfo;
ET9JLingCmnInfo 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;

}



int ET9JUtil_getRangeConvertedPhrase(unsigned int index, unsigned int *outReadingDivInfo, unsigned short *word, unsigned int* outPhraseDivInfo) {

	return ((ConvEng *)getConvEng())->getRangeConvertedPhrase(index, outReadingDivInfo, word, outPhraseDivInfo);
}

int ET9JUtil_startRangeConversion(unsigned int type, 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= ((ConvEng *)getConvEng())->startRangeConversion(type, tempWord, wordLen);
    delete[] tempWord;
    return bRet;

}

int ET9JUtil_getRangeConvCandidateWord(const int index, unsigned short *word, int *wordLen)
{
    return ((ConvEng *)getConvEng())->getRangeConvCandidateWord(index, word, wordLen);
}

int ET9JUtil_getRangeConvCandidateWordCount()
{
    return ((ConvEng *)getConvEng())->getRangeConvCandidateWordCount();
}

int ET9JUtil_confirmRangeConvWord(int nIndex)
{
    return ((ConvEng *)getConvEng())->confirmRangeConvWord(nIndex);

}




/*----------------------------------------------------------------------------
 * 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(ET9JLingInfo * pLingInfo, ET9JMidashigo_Request * pRequest, void * const pEngineInfo)
{
    ET9STATUS wStatus;
    ConvEng *_pEngineInfo = (ConvEng *)pEngineInfo;

    ET9U8  abRomaji[ET9MAXWORDSIZE + 1] = {0,};
    ET9U8  abYomi  [ET9MAXSJISWORDSIZE] = {0,};
    ET9U8 *pbMidashigo;
    ET9UINT nSize;
    ET9J_CONVTYPE eConvType;

    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_ROMAJI_CONVERT:

        wStatus = ET9JUtil_SymbToU8(pRequest->data.sConvRomaji.pRomaji, abRomaji, pRequest->data.sConvRomaji.wRomajiLen);

        if (wStatus == ET9STATUS_NONE) {

            abRomaji[pRequest->data.sConvRomaji.wRomajiLen] = 0;

            // Using core's own Romaji-to-kana conversion to obtain yomi
            wStatus = ET9JUtil_RomajiToKana(abRomaji, pRequest->data.sConvRomaji.wRomajiLen, abYomi, ET9MAXSJISWORDSIZE, &nSize, &eConvType, 1);
            
            if (wStatus == ET9STATUS_NONE && ET9J_CONVTYPE_INVALID != eConvType && ET9J_CONVTYPE_BOTH != eConvType) {

                pRequest->data.wReturn = 0;

                if (_pEngineInfo->StartYomiConversion((const unsigned char *)abYomi, pRequest->data.sConvRomaji.bIsExact)) {
                    pRequest->data.wReturn = _pEngineInfo->GetMidashigoCandidateCount();
                }
                else {
                    pRequest->data.wReturn = 0;
                    wStatus = ET9STATUS_ERROR;
                }
            }
            else {
                pRequest->data.wReturn = 0;
                wStatus = ET9STATUS_ERROR;
            }
        }
        else {
            pRequest->data.wReturn = 0;
            wStatus = ET9STATUS_ERROR;
        }
        break;

    case ET9_MIDASHIGO_REQ_RETRIEVE_MIDASHIGO:

        pbMidashigo = (ET9U8 *)_pEngineInfo->GetMidashigoCandidate((int)pRequest->data.sRetrieveMid.wMidashigoIndex, &iScore);
        
        if (pbMidashigo) {
            int nMidaLen = strlen((const char*)pbMidashigo);
            strncpy((char *)pRequest->data.sRetrieveMid.pMidashigo, (const char *)pbMidashigo, nMidaLen);
            pRequest->data.sRetrieveMid.wScore = (ET9U16)iScore;
            pRequest->data.sRetrieveMid.wWordLen = nMidaLen;
        }
        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:

        pbMidashigo = (ET9U8 *)_pEngineInfo->GetPredictionCandidate((int)pRequest->data.sRetrieveMid.wMidashigoIndex, &iScore);
        
        if (pbMidashigo) {
            int nMidaLen = strlen((const char*)pbMidashigo);
            strncpy((char *)pRequest->data.sRetrieveMid.pMidashigo, (const char *)pbMidashigo, nMidaLen);
            pRequest->data.sRetrieveMid.wScore = (ET9U16)iScore;
            pRequest->data.sRetrieveMid.wWordLen = nMidaLen;
        }
        else {
            pRequest->data.sRetrieveMid.wWordLen = 0;
            wStatus = ET9STATUS_ERROR;
        }
        break;

    case ET9_MIDASHIGO_REQ_MIN_SCORE:
        {
            pRequest->data.sMinScore.wScore = pRequest->data.sMinScore.wWordIndex;
        }
        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;
            int i;

            for (i = 0; i < pYomi->bMidashigoCount; i++) {
                pYomi->sMidashigo[i].wFinalScore = (1 + pYomi->sMidashigo[i].wConvScore) * wWordIndex;
            }
        }
        break;

    case ET9_MIDASHIGO_REQ_UPDATE_PAIR:

        wStatus = ET9JUtil_SymbToU8(pRequest->data.sUpdatePair.pRomaji, abRomaji, pRequest->data.sUpdatePair.wRomajiLen);

        if (ET9STATUS_NONE == wStatus) {

            abRomaji[pRequest->data.sConvRomaji.wRomajiLen] = 0;

            wStatus = ET9JUtil_RomajiToKana(abRomaji, pRequest->data.sConvRomaji.wRomajiLen, abYomi, ET9MAXSJISWORDSIZE, &nSize, &eConvType, 1);

            if (wStatus == ET9STATUS_NONE && ET9J_CONVTYPE_INVALID != eConvType && ET9J_CONVTYPE_BOTH != eConvType) {

                _pEngineInfo->LearnCandidate((const unsigned char*)abYomi, (const unsigned char*)pRequest->data.sUpdatePair.pMidashigo);
            }
        }
        break;

    case ET9_MIDASHIGO_REQ_UPDATE_PREDICTION:

        _pEngineInfo->UpdatePrediction((const ET9U8)pRequest->data.wPredictionIndex);
        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
