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

package com.android.inputmethod.latin;

import android.text.format.DateUtils;
import android.util.Log;

public final class UserHistoryForgettingCurveUtils {
    private static final String TAG = UserHistoryForgettingCurveUtils.class.getSimpleName();
    private static final boolean DEBUG = false;
    private static final int FC_FREQ_MAX = 127;
    /* package */ static final int COUNT_MAX = 3;
    private static final int FC_LEVEL_MAX = 3;
    /* package */ static final int ELAPSED_TIME_MAX = 15;
    private static final int ELAPSED_TIME_INTERVAL_HOURS = 6;
    private static final long ELAPSED_TIME_INTERVAL_MILLIS = ELAPSED_TIME_INTERVAL_HOURS
            * DateUtils.HOUR_IN_MILLIS;
    private static final int HALF_LIFE_HOURS = 48;
    private static final int MAX_PUSH_ELAPSED = (FC_LEVEL_MAX + 1) * (ELAPSED_TIME_MAX + 1);

    private UserHistoryForgettingCurveUtils() {
        // This utility class is not publicly instantiable.
    }

    public static final class ForgettingCurveParams {
        private byte mFc;
        long mLastTouchedTime = 0;
        private final boolean mIsValid;

        private void updateLastTouchedTime() {
            mLastTouchedTime = System.currentTimeMillis();
        }

        public ForgettingCurveParams(boolean isValid) {
            this(System.currentTimeMillis(), isValid);
        }

        private ForgettingCurveParams(long now, boolean isValid) {
            this(pushCount((byte)0, isValid), now, now, isValid);
        }

        /** This constructor is called when the user history bigram dictionary is being restored. */
        public ForgettingCurveParams(int fc, long now, long last) {
            // All words with level >= 1 had been saved.
            // Invalid words with level == 0 had been saved.
            // Valid words words with level == 0 had *not* been saved.
            this(fc, now, last, fcToLevel((byte)fc) > 0);
        }

        private ForgettingCurveParams(int fc, long now, long last, boolean isValid) {
            mIsValid = isValid;
            mFc = (byte)fc;
            mLastTouchedTime = last;
            updateElapsedTime(now);
        }

        public boolean isValid() {
            return mIsValid;
        }

        public byte getFc() {
            updateElapsedTime(System.currentTimeMillis());
            return mFc;
        }

        public int getFrequency() {
            updateElapsedTime(System.currentTimeMillis());
            return UserHistoryForgettingCurveUtils.fcToFreq(mFc);
        }

        public int notifyTypedAgainAndGetFrequency() {
            updateLastTouchedTime();
            // TODO: Check whether this word is valid or not
            mFc = pushCount(mFc, false);
            return UserHistoryForgettingCurveUtils.fcToFreq(mFc);
        }

        private void updateElapsedTime(long now) {
            final int elapsedTimeCount =
                    (int)((now - mLastTouchedTime) / ELAPSED_TIME_INTERVAL_MILLIS);
            if (elapsedTimeCount <= 0) {
                return;
            }
            if (elapsedTimeCount >= MAX_PUSH_ELAPSED) {
                mLastTouchedTime = now;
                mFc = 0;
                return;
            }
            for (int i = 0; i < elapsedTimeCount; ++i) {
                mLastTouchedTime += ELAPSED_TIME_INTERVAL_MILLIS;
                mFc = pushElapsedTime(mFc);
            }
        }
    }

    /* package */ static  int fcToElapsedTime(byte fc) {
        return fc & 0x0F;
    }

    /* package */ static int fcToCount(byte fc) {
        return (fc >> 4) & 0x03;
    }

    /* package */ static int fcToLevel(byte fc) {
        return (fc >> 6) & 0x03;
    }

    private static int calcFreq(int elapsedTime, int count, int level) {
        if (level <= 0) {
            // Reserved words, just return -1
            return -1;
        }
        if (count == COUNT_MAX) {
            // Temporary promote because it's frequently typed recently
            ++level;
        }
        final int et = Math.min(FC_FREQ_MAX, Math.max(0, elapsedTime));
        final int l = Math.min(FC_LEVEL_MAX, Math.max(0, level));
        return MathUtils.SCORE_TABLE[l - 1][et];
    }

    /* pakcage */ static byte calcFc(int elapsedTime, int count, int level) {
        final int et = Math.min(FC_FREQ_MAX, Math.max(0, elapsedTime));
        final int c = Math.min(COUNT_MAX, Math.max(0, count));
        final int l = Math.min(FC_LEVEL_MAX, Math.max(0, level));
        return (byte)(et | (c << 4) | (l << 6));
    }

    public static int fcToFreq(byte fc) {
        final int elapsedTime = fcToElapsedTime(fc);
        final int count = fcToCount(fc);
        final int level = fcToLevel(fc);
        return calcFreq(elapsedTime, count, level);
    }

    public static byte pushElapsedTime(byte fc) {
        int elapsedTime = fcToElapsedTime(fc);
        int count = fcToCount(fc);
        int level = fcToLevel(fc);
        if (elapsedTime >= ELAPSED_TIME_MAX) {
            // Downgrade level
            elapsedTime = 0;
            count = COUNT_MAX;
            --level;
        } else {
            ++elapsedTime;
        }
        return calcFc(elapsedTime, count, level);
    }

    public static byte pushCount(byte fc, boolean isValid) {
        final int elapsedTime = fcToElapsedTime(fc);
        int count = fcToCount(fc);
        int level = fcToLevel(fc);
        if ((elapsedTime == 0 && count >= COUNT_MAX) || (isValid && level == 0)) {
            // Upgrade level
            ++level;
            count = 0;
            if (DEBUG) {
                Log.d(TAG, "Upgrade level.");
            }
        } else {
            ++count;
        }
        return calcFc(0, count, level);
    }

    // TODO: isValid should be false for a word whose frequency is 0,
    // or that is not in the dictionary.
    /**
     * Check wheather we should save the bigram to the SQL DB or not
     */
    public static boolean needsToSave(byte fc, boolean isValid, boolean addLevel0Bigram) {
        int level = fcToLevel(fc);
        if (level == 0) {
            if (isValid || !addLevel0Bigram) {
                return false;
            }
        }
        final int elapsedTime = fcToElapsedTime(fc);
        return (elapsedTime < ELAPSED_TIME_MAX - 1 || level > 0);
    }

    private static final class MathUtils {
        public static final int[][] SCORE_TABLE = new int[FC_LEVEL_MAX][ELAPSED_TIME_MAX + 1];
        static {
            for (int i = 0; i < FC_LEVEL_MAX; ++i) {
                final float initialFreq;
                if (i >= 2) {
                    initialFreq = FC_FREQ_MAX;
                } else if (i == 1) {
                    initialFreq = FC_FREQ_MAX / 2;
                } else if (i == 0) {
                    initialFreq = FC_FREQ_MAX / 4;
                } else {
                    continue;
                }
                for (int j = 0; j < ELAPSED_TIME_MAX; ++j) {
                    final float elapsedHours = j * ELAPSED_TIME_INTERVAL_HOURS;
                    final float freq = initialFreq
                            * (float)Math.pow(initialFreq, elapsedHours / HALF_LIFE_HOURS);
                    final int intFreq = Math.min(FC_FREQ_MAX, Math.max(0, (int)freq));
                    SCORE_TABLE[i][j] = intFreq;
                }
            }
        }
    }
}
