/*
 *  Copyright (c) 2015, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */

package com.facebook.network.connectionclass;

/**
 * Moving average calculation for ConnectionClass.
 */
class ExponentialGeometricAverage {

  private final double mDecayConstant;
  private final int mCutover;

  private double mValue = -1;
  private int mCount;

  public ExponentialGeometricAverage(double decayConstant) {
    mDecayConstant = decayConstant;
    mCutover = decayConstant == 0.0
        ? Integer.MAX_VALUE
        : (int) Math.ceil(1 / decayConstant);
  }

  /**
   * Adds a new measurement to the moving average.
   * @param measurement - Bandwidth measurement in bits/ms to add to the moving average.
   */
  public void addMeasurement(double measurement) {
    double keepConstant = 1 - mDecayConstant;
    if (mCount > mCutover) {
      mValue = Math.exp(keepConstant * Math.log(mValue) + mDecayConstant * Math.log(measurement));
    } else if (mCount > 0) {
      double retained = keepConstant * mCount / (mCount + 1.0);
      double newcomer = 1.0 - retained;
      mValue = Math.exp(retained * Math.log(mValue) + newcomer * Math.log(measurement));
    } else {
      mValue = measurement;
    }
    mCount++;
  }

  public double getAverage() {
    return mValue;
  }

  /**
   * Reset the moving average.
   */
  public void reset() {
    mValue = -1.0;
    mCount = 0;
  }
}
