/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "suggest/core/session/dic_traverse_session.h"

#include "binary_format.h"
#include "defines.h"
#include "dictionary.h"
#include "dic_traverse_wrapper.h"
#include "jni.h"
#include "suggest/core/dicnode/dic_node_utils.h"

namespace latinime {

const int DicTraverseSession::CACHE_START_INPUT_LENGTH_THRESHOLD = 20;

// A factory method for DicTraverseSession
static void *getSessionInstance(JNIEnv *env, jstring localeStr) {
    return new DicTraverseSession(env, localeStr);
}

// TODO: Pass "DicTraverseSession *traverseSession" when the source code structure settles down.
static void initSessionInstance(void *traverseSession, const Dictionary *const dictionary,
        const int *prevWord, const int prevWordLength) {
    if (traverseSession) {
        DicTraverseSession *tSession = static_cast<DicTraverseSession *>(traverseSession);
        tSession->init(dictionary, prevWord, prevWordLength);
    }
}

// TODO: Pass "DicTraverseSession *traverseSession" when the source code structure settles down.
static void releaseSessionInstance(void *traverseSession) {
    delete static_cast<DicTraverseSession *>(traverseSession);
}

// An ad-hoc internal class to register the factory method defined above
class TraverseSessionFactoryRegisterer {
 public:
    TraverseSessionFactoryRegisterer() {
        DicTraverseWrapper::setTraverseSessionFactoryMethod(getSessionInstance);
        DicTraverseWrapper::setTraverseSessionInitMethod(initSessionInstance);
        DicTraverseWrapper::setTraverseSessionReleaseMethod(releaseSessionInstance);
    }
 private:
    DISALLOW_COPY_AND_ASSIGN(TraverseSessionFactoryRegisterer);
};

// To invoke the TraverseSessionFactoryRegisterer constructor in the global constructor.
static TraverseSessionFactoryRegisterer traverseSessionFactoryRegisterer;

void DicTraverseSession::init(const Dictionary *const dictionary, const int *prevWord,
        int prevWordLength) {
    mDictionary = dictionary;
    mMultiWordCostMultiplier = BinaryFormat::getMultiWordCostMultiplier(mDictionary->getDict());
    if (!prevWord) {
        mPrevWordPos = NOT_VALID_WORD;
        return;
    }
    mPrevWordPos = DicNodeUtils::getWordPos(dictionary->getOffsetDict(), prevWord, prevWordLength);
}

void DicTraverseSession::setupForGetSuggestions(const ProximityInfo *pInfo,
        const int *inputCodePoints, const int inputSize, const int *const inputXs,
        const int *const inputYs, const int *const times, const int *const pointerIds,
        const float maxSpatialDistance, const int maxPointerCount) {
    mProximityInfo = pInfo;
    mMaxPointerCount = maxPointerCount;
    initializeProximityInfoStates(inputCodePoints, inputXs, inputYs, times, pointerIds, inputSize,
            maxSpatialDistance, maxPointerCount);
}

const uint8_t *DicTraverseSession::getOffsetDict() const {
    return mDictionary->getOffsetDict();
}

int DicTraverseSession::getDictFlags() const {
    return mDictionary->getDictFlags();
}

void DicTraverseSession::resetCache(const int nextActiveCacheSize, const int maxWords) {
    mDicNodesCache.reset(nextActiveCacheSize, maxWords);
    mBigramCacheMap.clear();
    mPartiallyCommited = false;
}

void DicTraverseSession::initializeProximityInfoStates(const int *const inputCodePoints,
        const int *const inputXs, const int *const inputYs, const int *const times,
        const int *const pointerIds, const int inputSize, const float maxSpatialDistance,
        const int maxPointerCount) {
    ASSERT(1 <= maxPointerCount && maxPointerCount <= MAX_POINTER_COUNT_G);
    mInputSize = 0;
    for (int i = 0; i < maxPointerCount; ++i) {
        mProximityInfoStates[i].initInputParams(i, maxSpatialDistance, getProximityInfo(),
                inputCodePoints, inputSize, inputXs, inputYs, times, pointerIds,
                maxPointerCount == MAX_POINTER_COUNT_G
                /* TODO: this is a hack. fix proximity info state */);
        mInputSize += mProximityInfoStates[i].size();
    }
}
} // namespace latinime
