/* You may find the license in the LICENSE file */

const EXPORTED_SYMBOLS = ['SpeedStats'];

/**
 * Speed Statistics
 * @param maxSpeeds (unsigned) Maximum number of speeds to count
 */
function SpeedStats(maxSpeeds) {
	this._maxSpeeds = maxSpeeds;
	this.clear();
}

SpeedStats.prototype = {
	/**
	 * Maximum number of speeds to store
	 * Oldest will be dropped if buffer runs full
	 */
	get maxSpeeds() {
		return this._maxSpeeds;
	},
	/**
	 * Average speed (at the moment)
	 */
	get avg() {
		return this._avg;
	},
	/**
	 * First (oldest) speed recorded
	 */
	get first() {
		return this._speeds[0];
	},
	/**
	 * Last (most recent) speed recorded
	 */
	get last() {
		return this._speeds[this._speeds.length - 1];
	},
	/**
	 * Number of speed statistics currently recorded
	 */
	get length() {
		return this._speeds.length;
	},
	/**
	 * Generator over all recorded speeds
	 */
	get all() {
		for each (let x in this._speeds) {
			yield x;
		}
	},
	/**
	 * Time of last update
	 */
	get lastUpdate() {
		return this._lastTime;
	},
	/**
	 * Bytes in last period
	 */
	get lastBytes() {
		return this._lastBytes;
	},
	_lastTime: 0,
	_lastBytes: 0,
	/**
	 * Adds a new data point based on given downloaded bytes and time
	 * @param bytes (int) Bytes in the period
	 * @param time (int) Time bytes was recorded
	 */
	add: function DSS_add(bytes, time) {
		let received = 0;
		if (this._lastTime) {
			let elapsed = (time - this._lastTime) / 1000;
			received = bytes - this._lastBytes;
			let last = Math.max(0, Math.round(received / elapsed));
			this._speeds.push(last);
			if (this._speeds.length > this._maxSpeeds) {
				this._speeds.shift();
			}
			
			this._avg = this._speeds.slice(-10).reduce(function(p, c) (0.8 * p) + (0.2 * c));
		}
		this._lastTime = time;
		this._lastBytes = bytes;
		return received;
	},
	/**
	 * Clears all statistics
	 */
	clear: function DSS_clear() {
		this._speeds = [];
		this._lastTime = this._lastBytes = this._avg = 0;
	}
};
