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

import android.util.Log;

import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.define.ProductionFlag;

public class Statistics {
    private static final String TAG = Statistics.class.getSimpleName();
    private static final boolean DEBUG = false
            && ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG;

    // TODO: Cleanup comments to only including those giving meaningful information.
    // Number of characters entered during a typing session
    int mCharCount;
    // Number of letter characters entered during a typing session
    int mLetterCount;
    // Number of number characters entered
    int mNumberCount;
    // Number of space characters entered
    int mSpaceCount;
    // Number of delete operations entered (taps on the backspace key)
    int mDeleteKeyCount;
    // Number of words entered during a session.
    int mWordCount;
    // Number of words found in the dictionary.
    int mDictionaryWordCount;
    // Number of words split and spaces automatically entered.
    int mSplitWordsCount;
    // Number of words entered during a session.
    int mCorrectedWordsCount;
    // Number of gestures that were input.
    int mGesturesInputCount;
    // Number of gestures that were deleted.
    int mGesturesDeletedCount;
    // Total number of characters in words entered by gesture.
    int mGesturesCharsCount;
    // Number of manual suggestions chosen.
    int mManualSuggestionsCount;
    // Number of times that autocorrection was invoked.
    int mAutoCorrectionsCount;
    // Number of times a commit was reverted in this session.
    int mRevertCommitsCount;
    // Whether the text field was empty upon editing
    boolean mIsEmptyUponStarting;
    boolean mIsEmptinessStateKnown;

    // Timers to count average time to enter a key, first press a delete key,
    // between delete keys, and then to return typing after a delete key.
    final AverageTimeCounter mKeyCounter = new AverageTimeCounter();
    final AverageTimeCounter mBeforeDeleteKeyCounter = new AverageTimeCounter();
    final AverageTimeCounter mDuringRepeatedDeleteKeysCounter = new AverageTimeCounter();
    final AverageTimeCounter mAfterDeleteKeyCounter = new AverageTimeCounter();

    static class AverageTimeCounter {
        int mCount;
        int mTotalTime;

        public void reset() {
            mCount = 0;
            mTotalTime = 0;
        }

        public void add(long deltaTime) {
            mCount++;
            mTotalTime += deltaTime;
        }

        public int getAverageTime() {
            if (mCount == 0) {
                return 0;
            }
            return mTotalTime / mCount;
        }
    }

    // To account for the interruptions when the user's attention is directed elsewhere, times
    // longer than MIN_TYPING_INTERMISSION are not counted when estimating this statistic.
    public static final int MIN_TYPING_INTERMISSION = 2 * 1000;  // in milliseconds
    public static final int MIN_DELETION_INTERMISSION = 10 * 1000;  // in milliseconds

    // The last time that a tap was performed
    private long mLastTapTime;
    // The type of the last keypress (delete key or not)
    boolean mIsLastKeyDeleteKey;

    private static final Statistics sInstance = new Statistics();

    public static Statistics getInstance() {
        return sInstance;
    }

    private Statistics() {
        reset();
    }

    public void reset() {
        mCharCount = 0;
        mLetterCount = 0;
        mNumberCount = 0;
        mSpaceCount = 0;
        mDeleteKeyCount = 0;
        mWordCount = 0;
        mDictionaryWordCount = 0;
        mSplitWordsCount = 0;
        mCorrectedWordsCount = 0;
        mGesturesInputCount = 0;
        mGesturesDeletedCount = 0;
        mManualSuggestionsCount = 0;
        mRevertCommitsCount = 0;
        mAutoCorrectionsCount = 0;
        mIsEmptyUponStarting = true;
        mIsEmptinessStateKnown = false;
        mKeyCounter.reset();
        mBeforeDeleteKeyCounter.reset();
        mDuringRepeatedDeleteKeysCounter.reset();
        mAfterDeleteKeyCounter.reset();
        mGesturesCharsCount = 0;
        mGesturesDeletedCount = 0;

        mLastTapTime = 0;
        mIsLastKeyDeleteKey = false;
    }

    public void recordChar(int codePoint, long time) {
        if (DEBUG) {
            Log.d(TAG, "recordChar() called");
        }
        if (codePoint == Constants.CODE_DELETE) {
            mDeleteKeyCount++;
            recordUserAction(time, true /* isDeletion */);
        } else {
            mCharCount++;
            if (Character.isDigit(codePoint)) {
                mNumberCount++;
            }
            if (Character.isLetter(codePoint)) {
                mLetterCount++;
            }
            if (Character.isSpaceChar(codePoint)) {
                mSpaceCount++;
            }
            recordUserAction(time, false /* isDeletion */);
        }
    }

    public void recordWordEntered(final boolean isDictionaryWord,
            final boolean containsCorrection) {
        mWordCount++;
        if (isDictionaryWord) {
            mDictionaryWordCount++;
        }
        if (containsCorrection) {
            mCorrectedWordsCount++;
        }
    }

    public void recordSplitWords() {
        mSplitWordsCount++;
    }

    public void recordGestureInput(final int numCharsEntered, final long time) {
        mGesturesInputCount++;
        mGesturesCharsCount += numCharsEntered;
        recordUserAction(time, false /* isDeletion */);
    }

    public void setIsEmptyUponStarting(final boolean isEmpty) {
        mIsEmptyUponStarting = isEmpty;
        mIsEmptinessStateKnown = true;
    }

    public void recordGestureDelete(final int length, final long time) {
        mGesturesDeletedCount++;
        recordUserAction(time, true /* isDeletion */);
    }

    public void recordManualSuggestion(final long time) {
        mManualSuggestionsCount++;
        recordUserAction(time, false /* isDeletion */);
    }

    public void recordAutoCorrection(final long time) {
        mAutoCorrectionsCount++;
        recordUserAction(time, false /* isDeletion */);
    }

    public void recordRevertCommit(final long time) {
        mRevertCommitsCount++;
        recordUserAction(time, true /* isDeletion */);
    }

    private void recordUserAction(final long time, final boolean isDeletion) {
        final long delta = time - mLastTapTime;
        if (isDeletion) {
            if (delta < MIN_DELETION_INTERMISSION) {
                if (mIsLastKeyDeleteKey) {
                    mDuringRepeatedDeleteKeysCounter.add(delta);
                } else {
                    mBeforeDeleteKeyCounter.add(delta);
                }
            } else {
                ResearchLogger.onUserPause(delta);
            }
        } else {
            if (mIsLastKeyDeleteKey && delta < MIN_DELETION_INTERMISSION) {
                mAfterDeleteKeyCounter.add(delta);
            } else if (!mIsLastKeyDeleteKey && delta < MIN_TYPING_INTERMISSION) {
                mKeyCounter.add(delta);
            } else {
                ResearchLogger.onUserPause(delta);
            }
        }
        mIsLastKeyDeleteKey = isDeletion;
        mLastTapTime = time;
    }
}
