/* Measurement Report Processing */

/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
 *
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <errno.h>

#include <osmocom/bsc/gsm_data.h>
#include <osmocom/bsc/meas_rep.h>

static int get_field(const struct gsm_meas_rep *rep,
		     enum meas_rep_field field)
{
	switch (field) {
	case MEAS_REP_DL_RXLEV_FULL:
		if (!(rep->flags & MEAS_REP_F_DL_VALID))
			return -EINVAL;
		return rep->dl.full.rx_lev;
	case MEAS_REP_DL_RXLEV_SUB:
		if (!(rep->flags & MEAS_REP_F_DL_VALID))
			return -EINVAL;
		return rep->dl.sub.rx_lev;
	case MEAS_REP_DL_RXQUAL_FULL:
		if (!(rep->flags & MEAS_REP_F_DL_VALID))
			return -EINVAL;
		return rep->dl.full.rx_qual;
	case MEAS_REP_DL_RXQUAL_SUB:
		if (!(rep->flags & MEAS_REP_F_DL_VALID))
			return -EINVAL;
		return rep->dl.sub.rx_qual;
	case MEAS_REP_UL_RXLEV_FULL:
		return rep->ul.full.rx_lev;
	case MEAS_REP_UL_RXLEV_SUB:
		return rep->ul.sub.rx_lev;
	case MEAS_REP_UL_RXQUAL_FULL:
		return rep->ul.full.rx_qual;
	case MEAS_REP_UL_RXQUAL_SUB:
		return rep->ul.sub.rx_qual;
	}

	return 0;
}


unsigned int calc_initial_idx(unsigned int array_size,
			      unsigned int meas_rep_idx,
			      unsigned int num_values)
{
	int offs, idx;

	/* from which element do we need to start if we're interested
	 * in an average of 'num' elements */
	offs = meas_rep_idx - num_values;

	if (offs < 0)
		idx = array_size + offs;
	else
		idx = offs;

	return idx;
}

/* obtain an average over the last 'num' fields in the meas reps */
int get_meas_rep_avg(const struct gsm_lchan *lchan,
		     enum meas_rep_field field, unsigned int num)
{
	unsigned int i, idx;
	int avg = 0, valid_num = 0;

	if (num < 1)
		return -EINVAL;

	if (num > lchan->meas_rep_count)
		return -EINVAL;

	idx = calc_initial_idx(ARRAY_SIZE(lchan->meas_rep),
				lchan->meas_rep_idx, num);

	for (i = 0; i < num; i++) {
		int j = (idx+i) % ARRAY_SIZE(lchan->meas_rep);
		int val = get_field(&lchan->meas_rep[j], field);

		if (val >= 0) {
			avg += val;
			valid_num++;
		}
	}

	if (valid_num == 0)
		return -EINVAL;

	return avg / valid_num;
}

/* Check if N out of M last values for FIELD are >= bd */
int meas_rep_n_out_of_m_be(const struct gsm_lchan *lchan,
			enum meas_rep_field field,
			unsigned int n, unsigned int m, int be)
{
	unsigned int i, idx;
	int count = 0;

	idx = calc_initial_idx(ARRAY_SIZE(lchan->meas_rep),
				lchan->meas_rep_idx, m);

	for (i = 0; i < m; i++) {
		int j = (idx + i) % ARRAY_SIZE(lchan->meas_rep);
		int val = get_field(&lchan->meas_rep[j], field);

		if (val >= be) /* implies that val < 0 will not count */
			count++;

		if (count >= n)
			return 1;
	}

	return 0;
}
