/*
 * Copyright (C) 2015 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.systemui.classifier;

import android.os.Build;
import android.os.SystemProperties;
import android.view.MotionEvent;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * A classifier which for each point from a stroke, it creates a point on plane with coordinates
 * (timeOffsetNano, distanceCoveredUpToThisPoint) (scaled by DURATION_SCALE and LENGTH_SCALE)
 * and then it calculates the angle variance of these points like the class
 * {@link AnglesClassifier} (without splitting it into two parts). The classifier ignores
 * the last point of a stroke because the UP event comes in with some delay and this ruins the
 * smoothness of this curve. Additionally, the classifier classifies calculates the percentage of
 * angles which value is in [PI - ANGLE_DEVIATION, 2* PI) interval. The reason why the classifier
 * does that is because the speed of a good stroke is most often increases, so most of these angels
 * should be in this interval.
 */
public class SpeedAnglesClassifier extends StrokeClassifier {
    public static final boolean VERBOSE = SystemProperties.getBoolean("debug.falsing_log.spd_ang",
            Build.IS_DEBUGGABLE);
    public static final String TAG = "SPD_ANG";

    private HashMap<Stroke, Data> mStrokeMap = new HashMap<>();

    public SpeedAnglesClassifier(ClassifierData classifierData) {
        mClassifierData = classifierData;
    }

    @Override
    public String getTag() {
        return TAG;
    }

    @Override
    public void onTouchEvent(MotionEvent event) {
        int action = event.getActionMasked();

        if (action == MotionEvent.ACTION_DOWN) {
            mStrokeMap.clear();
        }

        for (int i = 0; i < event.getPointerCount(); i++) {
            Stroke stroke = mClassifierData.getStroke(event.getPointerId(i));

            if (mStrokeMap.get(stroke) == null) {
                mStrokeMap.put(stroke, new Data());
            }

            if (action != MotionEvent.ACTION_UP && action != MotionEvent.ACTION_CANCEL
                    && !(action == MotionEvent.ACTION_POINTER_UP && i == event.getActionIndex())) {
                mStrokeMap.get(stroke).addPoint(
                        stroke.getPoints().get(stroke.getPoints().size() - 1));
            }
        }
    }

    @Override
    public float getFalseTouchEvaluation(int type, Stroke stroke) {
        Data data = mStrokeMap.get(stroke);
        return SpeedVarianceEvaluator.evaluate(data.getAnglesVariance())
                + SpeedAnglesPercentageEvaluator.evaluate(data.getAnglesPercentage());
    }

    private static class Data {
        private final float DURATION_SCALE = 1e8f;
        private final float LENGTH_SCALE = 1.0f;
        private final float ANGLE_DEVIATION = (float) Math.PI / 10.0f;

        private List<Point> mLastThreePoints = new ArrayList<>();
        private Point mPreviousPoint;
        private float mPreviousAngle;
        private float mSumSquares;
        private float mSum;
        private float mCount;
        private float mDist;
        private float mAnglesCount;
        private float mAcceleratingAngles;

        public Data() {
            mPreviousPoint = null;
            mPreviousAngle = (float) Math.PI;
            mSumSquares = 0.0f;
            mSum = 0.0f;
            mCount = 1.0f;
            mDist = 0.0f;
            mAnglesCount = mAcceleratingAngles = 0.0f;
        }

        public void addPoint(Point point) {
            if (mPreviousPoint != null) {
                mDist += mPreviousPoint.dist(point);
            }

            mPreviousPoint = point;
            Point speedPoint = new Point((float) point.timeOffsetNano / DURATION_SCALE,
                    mDist / LENGTH_SCALE);

            // Checking if the added point is different than the previously added point
            // Repetitions are being ignored so that proper angles are calculated.
            if (mLastThreePoints.isEmpty()
                    || !mLastThreePoints.get(mLastThreePoints.size() - 1).equals(speedPoint)) {
                mLastThreePoints.add(speedPoint);
                if (mLastThreePoints.size() == 4) {
                    mLastThreePoints.remove(0);

                    float angle = mLastThreePoints.get(1).getAngle(mLastThreePoints.get(0),
                            mLastThreePoints.get(2));

                    mAnglesCount++;
                    if (angle >= (float) Math.PI - ANGLE_DEVIATION) {
                        mAcceleratingAngles++;
                    }

                    float difference = angle - mPreviousAngle;
                    mSum += difference;
                    mSumSquares += difference * difference;
                    mCount += 1.0;
                    mPreviousAngle = angle;
                }
            }
        }

        public float getAnglesVariance() {
            final float v = mSumSquares / mCount - (mSum / mCount) * (mSum / mCount);
            if (VERBOSE) {
                FalsingLog.i(TAG, "getAnglesVariance: sum^2=" + mSumSquares
                        + " count=" + mCount + " result=" + v);
            }
            return v;
        }

        public float getAnglesPercentage() {
            if (mAnglesCount == 0.0f) {
                return 1.0f;
            }
            final float v = (mAcceleratingAngles) / mAnglesCount;
            if (VERBOSE) {
                FalsingLog.i(TAG, "getAnglesPercentage: angles=" + mAcceleratingAngles
                        + " count=" + mAnglesCount + " result=" + v);
            }
            return v;
        }
    }
}