/*
 * Copyright 2010, Intel Corporation
 *
 * This file is part of PowerTOP
 *
 * This program file is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; version 2 of the License.
 *
 * 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 General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program in a file named COPYING; if not, write to the
 * Free Software Foundation, Inc,
 * 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 * or just google for it.
 *
 * Authors:
 *	Arjan van de Ven <arjan@linux.intel.com>
 */
#include "parameters.h"
#include "../measurement/measurement.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <vector>
#include <unistd.h>


struct parameter_bundle all_parameters;
struct result_bundle all_results;

vector <struct result_bundle *> past_results;

map <string, int> param_index;
static int maxindex = 1;
map <string, int> result_index;
static int maxresindex = 1;

int get_param_index(const char *name)
{
	int index;
	index = param_index[name];
	if (index == 0) {
		index = param_index[name] = ++maxindex;
	}

	if (index == 0)
		printf("OH BLA\n");
	return index;
}

int get_result_index(const char *name)
{
	int index;
	index = result_index[name];
	if (index == 0) {
		index = result_index[name] = ++maxresindex;
	}

	return index;
}


void register_parameter(const char *name, double default_value, double weight)
{
	int index;

	index = get_param_index(name);

	if (index >= (int)all_parameters.parameters.size()) {
		all_parameters.parameters.resize(index+1, 0.0);
		all_parameters.weights.resize(index+1, 1.0);
	}

	if (all_parameters.parameters[index] <= 0.0001)
		all_parameters.parameters[index] = default_value;

	all_parameters.weights[index] = weight;
}

void set_parameter_value(const char *name, double value, struct parameter_bundle *bundle)
{
	int index;

	index = get_param_index(name);

	if (index >= (int)bundle->parameters.size()) {
		bundle->parameters.resize(index+1, 0.0);
		bundle->weights.resize(index+1, 1.0);
	}

	bundle->parameters[index] = value;
}

double get_parameter_value(const char *name, struct parameter_bundle *the_bundle)
{
	unsigned int index;

	index = get_param_index(name);
	if (index >= the_bundle->parameters.size()) {
		fprintf(stderr, "BUG: requesting unregistered parameter %s\n", name);
	}
	return the_bundle->parameters[index];
}

double get_parameter_value(int index, struct parameter_bundle *the_bundle)
{
	return the_bundle->parameters[index];
}

double get_parameter_weight(int index, struct parameter_bundle *the_bundle)
{
	return the_bundle->weights[index];
}

double get_result_value(const char *name, struct result_bundle *the_bundle)
{
	return get_result_value(get_result_index(name), the_bundle);
}

void set_result_value(const char *name, double value, struct result_bundle *the_bundle)
{
	unsigned int index = get_result_index(name);
	if (index >= the_bundle->utilization.size())
		the_bundle->utilization.resize(index+1);
	the_bundle->utilization[index] = value;
}

void set_result_value(unsigned int index, double value, struct result_bundle *the_bundle)
{
	if (index >= the_bundle->utilization.size())
		the_bundle->utilization.resize(index+1);
	the_bundle->utilization[index] = value;
}

double get_result_value(int index, struct result_bundle *the_bundle)
{
	if (!the_bundle)
		return 0;
	if (index >= (int) the_bundle->utilization.size())
		return 0;
	return the_bundle->utilization[index];
}


int result_device_exists(const char *name)
{
	unsigned int i;
	for (i = 0; i < all_devices.size(); i++) {
		if (strcmp(all_devices[i]->device_name(), name) == 0)
			return 1;
	}
	return 0;
}

void report_utilization(const char *name, double value, struct result_bundle *bundle)
{
	set_result_value(name, value, bundle);
}
void report_utilization(int index, double value, struct result_bundle *bundle)
{
	set_result_value(index, value, bundle);
}



double compute_bundle(struct parameter_bundle *parameters, struct result_bundle *results)
{
	double power = 0;
	unsigned int i;

	static int bpi = 0;

	if (!bpi)
		bpi = get_param_index("base power");

	power = parameters->parameters[bpi];

	for (i = 0; i < all_devices.size(); i++) {

		power += all_devices[i]->power_usage(results, parameters);
	}
//	printf("result power is %6.2f  guessed is %6.2f\n", results->power, power);
	parameters->actual_power = results->power;
	parameters->guessed_power = power;
	/* scale the squared error by the actual power so that non-idle data points weigh heavier */
	parameters->score += results->power * (power - results->power) * (power - results->power);

	return power;
}

static int precomputed_valid = 0;
void precompute_valid(void)
{
	unsigned int i;


	for (i = 0; i < all_devices.size(); i++) {
		all_devices[i]->cached_valid = all_devices[i]->power_valid();
	}
	precomputed_valid = 1;
}

double bundle_power(struct parameter_bundle *parameters, struct result_bundle *results)
{
	double power = 0;
	unsigned int i;
	static int bpi = 0;

	if (!bpi)
		bpi = get_param_index("base power");

	if (!precomputed_valid)
		precompute_valid();


	power = parameters->parameters[bpi];

	for (i = 0; i < all_devices.size(); i++) {

		if (all_devices[i]->cached_valid)
			power += all_devices[i]->power_usage(results, parameters);
	}

	return power;
}


void dump_parameter_bundle(struct parameter_bundle *para)
{
	map<string, int>::iterator it;
	int index;

	printf("\n\n");
	printf("Parameter state \n");
	printf("----------------------------------\n");
	printf("Value\t\tName\n");
	for (it = param_index.begin(); it != param_index.end(); it++) {
		index = it->second;
		printf("%5.2f\t\t%s (%i)\n", para->parameters[index], it->first.c_str(), index);
	}

	printf("\n");
	printf("Score:  %5.1f  (%5.1f)\n", sqrt(para->score / (0.001 + past_results.size()) / average_power()), para->score);
	printf("Guess:  %5.1f\n", para->guessed_power);
	printf("Actual: %5.1f\n", para->actual_power);

	printf("----------------------------------\n");
}

void dump_result_bundle(struct result_bundle *res)
{
	map<string, int>::iterator it;
	unsigned int index;

	printf("\n\n");
	printf("Utilisation state \n");
	printf("----------------------------------\n");
	printf("Value\t\tName\n");
	for (it = result_index.begin(); it != result_index.end(); it++) {
		index = get_result_index(it->first.c_str());
		printf("%5.2f%%\t\t%s(%i)\n", res->utilization[index], it->first.c_str(), index);
	}

	printf("\n");
	printf("Power: %5.1f\n", res->power);

	printf("----------------------------------\n");
}

struct result_bundle * clone_results(struct result_bundle *bundle)
{
	struct result_bundle *b2;
	map<string, double>::iterator it;
	unsigned int i;

	b2 = new struct result_bundle;

	if (!b2)
		return NULL;

	b2->power = bundle->power;
	b2->utilization.resize(bundle->utilization.size());

	for (i = 0; i < bundle->utilization.size(); i++) {
		b2->utilization[i] = bundle->utilization[i];
	}

	return b2;
}


struct parameter_bundle * clone_parameters(struct parameter_bundle *bundle)
{
	struct parameter_bundle *b2;
	unsigned int i;

	b2 = new struct parameter_bundle;

	if (!b2)
		return NULL;

	b2->score = 0;
	b2->guessed_power = 0;
	b2->actual_power = bundle->actual_power;
	b2->parameters.resize(bundle->parameters.size());
	for (i = 0; i < bundle->parameters.size(); i++) {
		b2->parameters[i] = bundle->parameters[i];
	}

	return b2;
}


void store_results(double duration)
{
	if (duration < 5)
		return;
	global_joules_consumed();
	if (all_results.power > 0.01) {
		unsigned int overflow_index;
		overflow_index = 50 + (rand() % MAX_KEEP);
		if (past_results.size() >= MAX_PARAM) {
			/* memory leak, must free old one first */
			past_results[overflow_index] = clone_results(&all_results);
		} else {
			past_results.push_back(clone_results(&all_results));
		}
		if ((past_results.size() % 10) == 0)
			save_all_results("saved_results.powertop");
	}

}



void dump_past_results(void)
{
	unsigned int j;
	unsigned int i;
	struct result_bundle *result;

	for (j = 0; j < past_results.size(); j+=10) {
		printf("Est    ");
		for (i = j; i < past_results.size() && i < j + 10; i++) {
			result = past_results[i];
			printf("%6.2f  ", bundle_power(&all_parameters, result));
		}
		printf("\n");
		printf("Actual ");
		for (i = j; i < past_results.size() && i < j + 10; i++) {
			result = past_results[i];
			printf("%6.2f  ", result->power);
		}
		printf("\n\n");
	}
}

double average_power(void)
{
	double sum = 0.0;
	unsigned int i;
	for (i = 0; i < past_results.size(); i++)
		sum += past_results[i]->power;

	if (past_results.size())
		sum = sum / past_results.size() + 0.0001;
	else
		sum = 0.0001;
	return sum;
}

int utilization_power_valid(const char *u)
{
	unsigned int i;
	unsigned int index;
	double first_value;

	index = get_result_index(u);
	if (index <= 0)
		return 0;

	first_value = past_results[0]->utilization[index];
	for (i = 1; i < past_results.size(); i++) {
		if (get_result_value(index, past_results[i]) < first_value - 0.0001)
			return 1;
		if (get_result_value(index, past_results[i]) > first_value + 0.0001)
			return 1;
	}

	return 0;
}

int utilization_power_valid(int index)
{
	unsigned int i;
	double first_value;

	if (index <= 0)
		return 0;

	if (past_results.size() == 0)
		return 0;

	if (index >= (int)past_results[0]->utilization.size())
		return 0;
	first_value = past_results[0]->utilization[index];
	for (i = 1; i < past_results.size(); i++) {
		if (get_result_value(index, past_results[i]) < first_value - 0.0001)
			return 1;
		if (get_result_value(index, past_results[i]) > first_value + 0.0001)
			return 1;
	}

	return 0;
}


/* force power data to be valid to the rest of the system  */
int global_power_override = 0;

/* force no calculations to be done on parameters and trust the current ones */
int global_fixed_parameters = 0;

/*
 * only report power numbers once we have 3* more measurements than
 * we have parameters; anything less and our model fit is highly suspect
 */
int global_power_valid(void)
{
	if (past_results.size() > 3 * all_parameters.parameters.size())
		return 1;


	return global_power_override;
}

/* find the directory to store powertop results/parameters based on distribution*/
char* get_param_directory(const char *filename)
{
	static char tempfilename[4096];

	if (access("/var/cache/powertop", W_OK ) == 0)
		sprintf(tempfilename, "/var/cache/powertop/%s", filename);
	if (access("/data/local/powertop", W_OK ) == 0)
		sprintf(tempfilename, "/data/local/powertop/%s", filename);

	return tempfilename;
};
