/*
 * Power debug tool (powerdebug)
 *
 * Copyright (C) 2016, Linaro Limited.
 *
 * This program 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; either version 2
 * 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 */

#define _GNU_SOURCE
#include <stdio.h>
#undef _GNU_SOURCE
#include <sys/types.h>
#include <stdbool.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#include "powerdebug.h"
#include "display.h"
#include "tree.h"
#include "utils.h"

#define SYSFS_SENSOR "/sys/class/hwmon"

static struct tree *sensor_tree;

struct temp_info {
	char name[NAME_MAX];
	int temp;
};

struct fan_info {
	char name[NAME_MAX];
	int rpms;
};

struct sensor_info {
	char name[NAME_MAX];
	struct temp_info *temperatures;
	struct fan_info *fans;
	short nrtemps;
	short nrfans;
};

static int sensor_dump_cb(struct tree *tree, void *data)
{
	int i;
	struct sensor_info *sensor = tree->private;

	if (!strlen(sensor->name))
		return 0;

	printf("%s\n", sensor->name);

	for (i = 0; i < sensor->nrtemps; i++)
		printf(" %s %.1f °C/V\n", sensor->temperatures[i].name,
		       (float)sensor->temperatures[i].temp / 1000);

	for (i = 0; i < sensor->nrfans; i++)
		printf(" %s %d rpm\n", sensor->fans[i].name,
		       sensor->fans[i].rpms);

	return 0;
}

static struct sensor_info *sensor_alloc(void)
{
	struct sensor_info *sensor;

	sensor = malloc(sizeof(*sensor));
	if (sensor)
		memset(sensor, 0, sizeof(*sensor));

	return sensor;
}

static int read_sensor_cb(struct tree *tree, void *data)
{
	DIR *dir;
	int value;
        struct dirent dirent, *direntp;
	struct sensor_info *sensor = tree->private;

	int nrtemps = 0;
	int nrfans = 0;

	dir = opendir(tree->path);
	if (!dir)
		return -1;

	file_read_value(tree->path, "name", "%s", sensor->name);

	while (!readdir_r(dir, &dirent, &direntp)) {

                if (!direntp)
                        break;

		if (direntp->d_type != DT_REG)
			continue;

		if (!strncmp(direntp->d_name, "temp", 4)) {

			if (file_read_value(tree->path, direntp->d_name, "%d",
					    &value))
				continue;

			sensor->temperatures =
				realloc(sensor->temperatures,
					sizeof(struct temp_info) * (nrtemps + 1));
			if (!sensor->temperatures)
				continue;

			strcpy(sensor->temperatures[nrtemps].name,
			       direntp->d_name);
			sensor->temperatures[nrtemps].temp = value;

			nrtemps++;
		}

		if (!strncmp(direntp->d_name, "fan", 3)) {

			if (file_read_value(tree->path, direntp->d_name, "%d",
					    &value))
				continue;

			sensor->fans =
				realloc(sensor->fans,
					sizeof(struct temp_info) * (nrfans + 1));
			if (!sensor->fans)
				continue;

			strcpy(sensor->fans[nrfans].name,
			       direntp->d_name);
			sensor->fans[nrfans].rpms = value;

			nrfans++;
		}
	}

	sensor->nrtemps = nrtemps;
	sensor->nrfans = nrfans;

	closedir(dir);

	return 0;
}

static int read_sensor_info(struct tree *tree)
{
	return tree_for_each(tree, read_sensor_cb, NULL);
}

static int fill_sensor_cb(struct tree *t, void *data)
{
	struct sensor_info *sensor;

	sensor = sensor_alloc();
	if (!sensor)
		return -1;

	t->private = sensor;

	if (!t->parent)
		return 0;

	return read_sensor_cb(t, data);
}

static int fill_sensor_tree(void)
{
	return tree_for_each(sensor_tree, fill_sensor_cb, NULL);
}

static int sensor_filter_cb(const char *name)
{
	/* let's ignore some directories in order to avoid to be
	 * pulled inside the sysfs circular symlinks mess/hell
	 * (choose the word which fit better)
	 */
	if (!strcmp(name, "subsystem"))
		return 1;

	if (!strcmp(name, "driver"))
		return 1;

	if (!strcmp(name, "hwmon"))
		return 1;

	if (!strcmp(name, "power"))
		return 1;

	return 0;
}

static int sensor_display_cb(struct tree *t, void *data)
{
	struct sensor_info *sensor = t->private;
	int *line = data;
	char buf[1024];
	int i;

	if (!strlen(sensor->name))
		return 0;

	sprintf(buf, "%s", sensor->name);
	display_print_line(SENSOR, *line, buf, 1, t);

	(*line)++;

	for (i = 0; i < sensor->nrtemps; i++) {
		sprintf(buf, " %-35s%.1f", sensor->temperatures[i].name,
		       (float)sensor->temperatures[i].temp / 1000);
		display_print_line(SENSOR, *line, buf, 0, t);
		(*line)++;
	}

	for (i = 0; i < sensor->nrfans; i++) {
		sprintf(buf, " %-35s%d rpm", sensor->fans[i].name,
			sensor->fans[i].rpms);
		display_print_line(SENSOR, *line, buf, 0, t);
		(*line)++;
	}

	return 0;
}

static int sensor_print_header(void)
{
	char *buf;
	int ret;

	if (asprintf(&buf, "%-36s%s", "Name", "Value") < 0)
		return -1;

	ret = display_column_name(buf);

	free(buf);

	return ret;
}

static int sensor_print_info(struct tree *tree)
{
	int ret, line = 0;

	display_reset_cursor(SENSOR);

	sensor_print_header();

	ret = tree_for_each(tree, sensor_display_cb, &line);

	display_refresh_pad(SENSOR);

	return ret;
}

static int sensor_load_info(void)
{
        if (sensor_tree)
		return 0;

	sensor_tree = tree_load(SYSFS_SENSOR, sensor_filter_cb, false);
        if (!sensor_tree)
		return -1;

	if (fill_sensor_tree())
		return -1;

	return 0;
}

int sensor_dump(void)
{
	if (sensor_load_info())
		return -1;

	printf("\nSensor Information:\n");
	printf("*******************\n\n");

	return tree_for_each(sensor_tree, sensor_dump_cb, NULL);
}

static int sensor_display(bool refresh)
{
	if (sensor_load_info()) {
		display_print_error(SENSOR, 0, "Failed to read sensor info");
		return 0;
	}

	if (refresh && read_sensor_info(sensor_tree)) 
		return -1;

	return sensor_print_info(sensor_tree);
}

static struct display_ops sensor_ops = {
	.display = sensor_display,
};

int sensor_init(struct powerdebug_options *options)
{
	if (!(options->flags & SENSOR_OPTION))
		return 0;

	return display_register(SENSOR, &sensor_ops);
}
