/*
 * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
 *
 * 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 "gesture_predictor.hpp"

#include "constants.hpp"

namespace {
	/* State for the averaging algorithm we're using. */
	float prediction_history[kGestureCount][kPredictionHistoryLength] = {};
	int prediction_history_index = 0;
	int prediction_suppression_count = 0;
} /* namespace */

/* Return the result of the last prediction
 * 0: wing("W"), 1: ring("O"), 2: slope("angle"), 3: unknown
 */
int PredictGesture(float *output)
{
	/* Record the latest predictions in our rolling history buffer. */
	for (int i = 0; i < kGestureCount; ++i) {
		prediction_history[i][prediction_history_index] = output[i];
	}
	/* Figure out which slot to put the next predictions into. */
	++prediction_history_index;
	if (prediction_history_index >= kPredictionHistoryLength) {
		prediction_history_index = 0;
	}

	/* Average the last n predictions for each gesture, and find which has the
	 * highest score.
	 */
	int max_predict_index = -1;
	float max_predict_score = 0.0f;
	for (int i = 0; i < kGestureCount; i++) {
		float prediction_sum = 0.0f;
		for (int j = 0; j < kPredictionHistoryLength; ++j) {
			prediction_sum += prediction_history[i][j];
		}
		const float prediction_average = prediction_sum / kPredictionHistoryLength;
		if ((max_predict_index == -1) || (prediction_average > max_predict_score)) {
			max_predict_index = i;
			max_predict_score = prediction_average;
		}
	}

	/* If there's been a recent prediction, don't trigger a new one too soon. */
	if (prediction_suppression_count > 0) {
		--prediction_suppression_count;
	}
	/* If we're predicting no gesture, or the average score is too low, or there's
	 * been a gesture recognised too recently, return no gesture.
	 */
	if ((max_predict_index == kNoGesture) ||
	    (max_predict_score < kDetectionThreshold) ||
	    (prediction_suppression_count > 0)) {
		return kNoGesture;
	} else {
		/* Reset the suppression counter so we don't come up with another prediction
		 * too soon.
		 */
		prediction_suppression_count = kPredictionSuppressionDuration;
		return max_predict_index;
	}
}
