/*
 * 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 "measurement.h"
#include "acpi.h"
#include <iostream>
#include <fstream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "../lib.h"

using namespace std;

acpi_power_meter::acpi_power_meter(const char *acpi_name)
{
	rate = 0.0;
	capacity = 0.0;
	voltage = 0.0;
	pt_strcpy(battery_name, acpi_name);
}

/*
present:                 yes
capacity state:          ok
charging state:          discharging
present rate:            8580 mW
remaining capacity:      34110 mWh
present voltage:         12001 mV
*/

void acpi_power_meter::measure(void)
{
	char filename[PATH_MAX];
	char line[4096];
	ifstream file;

	double _rate = 0;
	double _capacity = 0;
	double _voltage = 0;

	char rate_units[16];
	char capacity_units[16];
	char voltage_units[16];

	rate_units[0] = 0;
	capacity_units[0] = 0;
	voltage_units[0] = 0;

	rate = 0;
	voltage = 0;
	capacity = 0;

	snprintf(filename, sizeof(filename), "/proc/acpi/battery/%s/state", battery_name);

	file.open(filename, ios::in);
	if (!file)
		return;

	while (file) {
		char *c;
		file.getline(line, sizeof(line));

		if (strstr(line, "present:") && (strstr(line, "yes") == NULL)) {
			return;
		}
		if (strstr(line, "charging state:") && (strstr(line, "discharging") == NULL)) {
			return; /* not discharging */
		}
		if (strstr(line, "present rate:")) {
			c = strchr(line, ':');
			c++;
			while (*c == ' ') c++;
			_rate = strtoull(c, NULL, 10);
			c = strchr(c, ' ');
			if (c) {
				c++;
				pt_strcpy(rate_units, c);
			} else {
				_rate = 0;
				strcpy(rate_units, "Unknown");
			}

		}
		if (strstr(line, "remaining capacity:")) {
			c = strchr(line, ':');
			c++;
			while (*c == ' ') c++;
			_capacity = strtoull(c, NULL, 10);
			c = strchr(c, ' ');
			if (c) {
				c++;
				pt_strcpy(capacity_units, c);
			} else {
				_capacity = 0;
				strcpy(capacity_units, "Unknown");
			}
		}
		if (strstr(line, "present voltage:")) {
			c = strchr(line, ':');
			c++;
			while (*c == ' ') c++;
			_voltage = strtoull(c, NULL, 10);
			c = strchr(c, ' ');
			if (c) {
				c++;
				pt_strcpy(voltage_units, c);
			} else {
				_voltage = 0;
				strcpy(voltage_units, "Unknown");
			}
		}
	}
	file.close();

	/* BIOS report random crack-inspired units. Lets try to get to the Si-system units */

	if (strcmp(voltage_units, "mV") == 0) {
		_voltage = _voltage / 1000.0;
		strcpy(voltage_units, "V");
	}

	if (strcmp(rate_units, "mW") == 0) {
		_rate = _rate / 1000.0;
		strcpy(rate_units, "W");
	}

	if (strcmp(rate_units, "mA") == 0) {
		_rate = _rate / 1000.0;
		strcpy(rate_units, "A");
	}

	if (strcmp(capacity_units, "mAh") == 0) {
		_capacity = _capacity / 1000.0;
		strcpy(capacity_units, "Ah");
	}
	if (strcmp(capacity_units, "mWh") == 0) {
		_capacity = _capacity / 1000.0;
		strcpy(capacity_units, "Wh");
	}
	if (strcmp(capacity_units, "Wh") == 0) {
		_capacity = _capacity * 3600.0;
		strcpy(capacity_units, "J");
	}


	if (strcmp(capacity_units, "Ah") == 0 && strcmp(voltage_units, "V") == 0) {
		_capacity = _capacity * 3600.0 * _voltage;
		strcpy(capacity_units, "J");
	}

	if (strcmp(rate_units, "A") == 0 && strcmp(voltage_units, "V")==0 ) {
		_rate = _rate * _voltage;
		strcpy(rate_units, "W");
	}




	if (strcmp(capacity_units, "J") == 0)
		capacity = _capacity;
	else
		capacity = 0.0;

	if (strcmp(rate_units, "W")==0)
		rate = _rate;
	else
		rate = 0.0;

	if (strcmp(voltage_units, "V")==0)
		voltage = _voltage;
	else
		voltage = 0.0;
}


void acpi_power_meter::end_measurement(void)
{
	measure();
}

void acpi_power_meter::start_measurement(void)
{
	/* ACPI battery state is a lagging indication, lets only measure at the end */
}


double acpi_power_meter::power(void)
{
	return rate;
}
