/*
 * 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.
 */

#ifndef LATINIME_DIC_NODE_STATE_INPUT_H
#define LATINIME_DIC_NODE_STATE_INPUT_H

#include "defines.h"

namespace latinime {

// TODO: Have a .cpp for this class
class DicNodeStateInput {
 public:
    DicNodeStateInput() {}
    virtual ~DicNodeStateInput() {}

    // TODO: Merge into DicNodeStatePrevWord::truncate
    void truncate(const int commitPoint) {
        mInputIndex[0] -= commitPoint;
    }

    void init() {
        for (int i = 0; i < MAX_POINTER_COUNT_G; i++) {
            // TODO: The initial value for mInputIndex should be -1?
            //mInputIndex[i] = i == 0 ? 0 : -1;
            mInputIndex[i] = 0;
            mPrevCodePoint[i] = NOT_A_CODE_POINT;
            mTerminalDiffCost[i] = static_cast<float>(MAX_VALUE_FOR_WEIGHTING);
        }
    }

    void init(const DicNodeStateInput *const src, const bool resetTerminalDiffCost) {
        for (int i = 0; i < MAX_POINTER_COUNT_G; i++) {
             mInputIndex[i] = src->mInputIndex[i];
             mPrevCodePoint[i] = src->mPrevCodePoint[i];
             mTerminalDiffCost[i] = resetTerminalDiffCost ?
                     static_cast<float>(MAX_VALUE_FOR_WEIGHTING) : src->mTerminalDiffCost[i];
         }
    }

    void updateInputIndexG(const int pointerId, const int inputIndex,
            const int prevCodePoint, const float terminalDiffCost, const float rawLength) {
        mInputIndex[pointerId] = inputIndex;
        mPrevCodePoint[pointerId] = prevCodePoint;
        mTerminalDiffCost[pointerId] = terminalDiffCost;
    }

    void init(const DicNodeStateInput *const src) {
        init(src, false);
    }

    // For transposition
    void setPrevCodePoint(const int pointerId, const int c) {
        mPrevCodePoint[pointerId] = c;
    }

    void forwardInputIndex(const int pointerId, const int val) {
        if (mInputIndex[pointerId] < 0) {
            mInputIndex[pointerId] = val;
        } else {
            mInputIndex[pointerId] = mInputIndex[pointerId] + val;
        }
    }

    int getInputIndex(const int pointerId) const {
        // when "inputIndex" exceeds "inputSize", auto-completion needs to be done
        return mInputIndex[pointerId];
    }

    int getPrevCodePoint(const int pointerId) const {
        return mPrevCodePoint[pointerId];
    }

    float getTerminalDiffCost(const int pointerId) const {
        return mTerminalDiffCost[pointerId];
    }

 private:
    // Caution!!!
    // Use a default copy constructor and an assign operator because shallow copies are ok
    // for this class
    int mInputIndex[MAX_POINTER_COUNT_G];
    int mPrevCodePoint[MAX_POINTER_COUNT_G];
    float mTerminalDiffCost[MAX_POINTER_COUNT_G];
};
} // namespace latinime
#endif // LATINIME_DIC_NODE_STATE_INPUT_H
