/*
 * Powerdebug : power debugging tool
 *
 * Copyright (C) 2016, Linaro Limited.
 *
 * Author:
 * Thara Gopinath <thara.gopinath@linaro.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 */
#define DEBUGFS_GENPD "/sys/kernel/debug/pm_genpd"
#define NAME_MAX	16
#define DEVICE_NAME_MAX	256

#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 "display.h"
#include "powerdebug.h"
#include "tree.h"
#include "utils.h"

struct genpd_idle_state {
	char name[NAME_MAX];
	long long idle_time;
};

struct genpd_info {
	long long active_time;
	long long total_idle_time;
	char current_state[NAME_MAX];
	struct genpd_idle_state *idle_states;
	char (*devices)[DEVICE_NAME_MAX];
	char (*sub_domains)[NAME_MAX];
	int nr_devices;
	int nr_subdomains;
	int nr_states;
};

static struct tree *genpd_tree;

static struct genpd_info *genpd_alloc(void)
{
	struct genpd_info *genpd;

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

	return genpd;
}

static int genpd_filter_cb(const char *name)
{
	/* Ignore the summary directory */
	if (!strcmp(name, "pm_genpd_summary"))
		return -1;
	if (!strcmp(name, "pm_genpd"))
		return -1;

	return 0;
}

static int genpd_dump_cb(struct tree *t, void *data)
{
	struct genpd_info *genpd = t->private;
	int i;

	if (!t->parent)
		return 0;

	printf("\n%s:\n", t->name);
	printf("current_state: %s\n", genpd->current_state);
	printf("active_time: %lld ms\n", genpd->active_time);
	printf("total_idle_time: %lld ms\n", genpd->total_idle_time);
	printf("Idle States:\n");
	for (i = 0; i < genpd->nr_states; i++) {
		struct genpd_idle_state state = genpd->idle_states[i];

		if (!i)
			printf("%*s State %*s Time\n", 12, "", 10, "");
		printf("%*s %-16s %lld\n", 12, "", state.name,
							state.idle_time);
	}
	printf("Devices:\n");
	for (i = 0; i < genpd->nr_devices; i++)
		printf("%*s %s\n", 8, "", genpd->devices[i]);
	printf("Subdomains:\n");
	for (i = 0; i < genpd->nr_subdomains; i++)
		printf("%*s %s\n", 11, "", genpd->sub_domains[i]);

	return 0;
}

static int genpd_display_cb(struct tree *t, void *data)
{
	struct genpd_info *genpd = t->private;
	int *line = data;
	int nr_states = 0, nr_devices = 0, nr_domains = 0, i = 0;
	char *buf;

	if (!t->parent)
		return 0;

	while (1) {
		char *state_buf, *device_buf, *domain_buf;

		if ((i) && (nr_states == genpd->nr_states) &&
			(nr_devices == genpd->nr_devices) &&
			(nr_domains == genpd->nr_subdomains)) {
			display_print_line(GENPD, *line, " ", 1, t);
			(*line)++;
			break;
		}

		if (nr_states < genpd->nr_states) {
			if (asprintf(&state_buf, "%-10s %lld",
				genpd->idle_states[nr_states].name,
				genpd->idle_states[nr_states].idle_time) < 0)
				return -1;
			nr_states++;
		} else {
			if (asprintf(&state_buf, "%s", "") < 0)
				return -1;
		}

		if (nr_devices < genpd->nr_devices) {
			if (asprintf(&device_buf, "%s",
				genpd->devices[nr_devices]) < 0)
				return -1;
			nr_devices++;
		} else {
			if (asprintf(&device_buf, "%s", "") < 0)
				return -1;
		}

		if (nr_domains < genpd->nr_subdomains) {
			if (asprintf(&domain_buf, "%s",
				genpd->sub_domains[nr_domains]) < 0)
				return -1;
			nr_domains++;
		} else {
			if (asprintf(&domain_buf, "%s", "") < 0)
				return -1;
		}

		if (!i) {
			if (asprintf(&buf, "%-9s %-18s %-20lld %-24lld %-34s "
				"%-50s %-15s", t->name, genpd->current_state,
				genpd->active_time, genpd->total_idle_time,
				state_buf, device_buf, domain_buf) < 0)
				return -1;
		} else {
			if (asprintf(&buf, "%-74s %-34s %-50s %-15s",
				"", state_buf, device_buf, domain_buf) < 0)
				return -1;
		}

		display_print_line(GENPD, *line, buf, 1, t);
		(*line)++;
		free(buf);
		free(state_buf);
		free(device_buf);
		free(domain_buf);
		i++;
	}

	return 0;
}

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

	if (asprintf(&buf, "%-9s %-18s %-20s %-24s %-34s %-50s %-15s", "Name",
		"Current State", "Active Time(ms)", "Total Idle Time(ms)",
		"Idle States(State,Time ms)", "Devices", "Subdomains") < 0)
		return -1;

	ret = display_column_name(buf);
	free(buf);

	return ret;
}

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

	display_reset_cursor(GENPD);

	genpd_print_header();

	ret = tree_for_each(t, genpd_display_cb, &line);

	display_refresh_pad(GENPD);

	return ret;
}

static int read_genpd_cb(struct tree *t, void *data)
{
	struct genpd_info *genpd = t->private;
	FILE *fp;
	char line[256];
	int nr_states = 0, nr_devices = 0, nr_sub_domains = 0;

	file_read_value(t->path, "active_time", "%lld", &genpd->active_time);
	file_read_value(t->path, "total_idle_time", "%lld",
						&genpd->total_idle_time);
	file_read_value(t->path, "current_state", "%s", &genpd->current_state);
	file_open(&fp, t->path, "idle_states", "r");
	while (!(file_read_line(&fp, line, sizeof(line)))) {
		if (!strncmp(line, "State", 5))
			continue;

		genpd->idle_states = realloc(genpd->idle_states,
			sizeof(struct genpd_idle_state) * (nr_states + 1));
		if (!genpd->idle_states)
			continue;
		sscanf(line, "%s %lld", genpd->idle_states[nr_states].name,
				&(genpd->idle_states[nr_states].idle_time));

		nr_states++;
	}
	file_close(&fp);

	file_open(&fp, t->path, "devices", "r");
	while (!(file_read_line(&fp, line, sizeof(line)))) {
		int len;

		genpd->devices = realloc(genpd->devices,
			sizeof(*(genpd->devices)) * (nr_devices + 1));
		if (!genpd->devices)
			continue;

		len = strlen(line);
		line[len - 1] = '\0';
		strcpy(genpd->devices[nr_devices], line);
		nr_devices++;
	}
	file_close(&fp);

	file_open(&fp, t->path, "sub_domains", "r");
	while (!(file_read_line(&fp, line, sizeof(line)))) {
		int len;

		genpd->sub_domains = realloc(genpd->sub_domains,
			sizeof(*(genpd->sub_domains)) * (nr_sub_domains + 1));
		if (!genpd->sub_domains)
			continue;

		len = strlen(line);
		line[len - 1] = '\0';
		strcpy(genpd->sub_domains[nr_sub_domains], line);
		nr_sub_domains++;
	}

	genpd->nr_states = nr_states;
	genpd->nr_devices = nr_devices;
	genpd->nr_subdomains = nr_sub_domains;

	return 0;
}

static int read_genpd_info(struct tree *t)
{
	return tree_for_each(t, read_genpd_cb, NULL);
}

static int fill_genpd_cb(struct tree *t, void *data)
{
	struct genpd_info *genpd;

	genpd = genpd_alloc();
	if (!genpd) {
		printf("error: unable to allocate memory for genpd\n");
		return -1;
	}

	t->private = genpd;

	return read_genpd_cb(t, data);
}

static int fill_genpd_tree(void)
{
	return tree_for_each(genpd_tree, fill_genpd_cb, NULL);
}

static int genpd_info_load(void)
{
	if (genpd_tree)
		return 0;

	genpd_tree = tree_load(DEBUGFS_GENPD, genpd_filter_cb, false);
	if (!genpd_tree)
		return -1;

	if (fill_genpd_tree())
		return -1;

	return 0;
}

int genpd_dump(void)
{
	if (!genpd_tree)
		genpd_info_load();
	else
		read_genpd_info(genpd_tree);

	return tree_for_each(genpd_tree, genpd_dump_cb, NULL);

	return 0;
}

static int genpd_display(bool refresh)
{
	if (genpd_info_load()) {
		display_print_error(GENPD, 0, "Failed to read genpd info");
		return 0;
	}

	if (refresh && read_genpd_info(genpd_tree))
		return -1;

	return genpd_print_info(genpd_tree);
}

static struct display_ops genpd_ops = {
	.display = genpd_display,
};

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

	return display_register(GENPD, &genpd_ops);
}

