/*
 * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
 *
 * Parts came from builtin-{top,stat,record}.c, see those files for further
 * copyright notes.
 *
 * Released under the GPL v2. (and only v2, not any later version)
 */
#include "../browser.h"
#include "../helpline.h"
#include "../libslang.h"
#include "../../evlist.h"
#include "../../hist.h"
#include "../../sort.h"
#include "../../symbol.h"
#include "../../top.h"

struct perf_top_browser {
	struct ui_browser b;
	struct rb_root	  root;
	float		  sum_ksamples;
	int		  dso_width;
	int		  dso_short_width;
	int		  sym_width;
};

static void perf_top_browser__write(struct ui_browser *browser, void *entry, int row)
{
	struct perf_top_browser *top_browser = container_of(browser, struct perf_top_browser, b);
	struct sym_entry *syme = rb_entry(entry, struct sym_entry, rb_node);
	bool current_entry = ui_browser__is_current_entry(browser, row);
	struct symbol *symbol = sym_entry__symbol(syme);
	struct perf_top *top = browser->priv;
	int width = browser->width;
	double pcnt;

	pcnt = 100.0 - (100.0 * ((top_browser->sum_ksamples - syme->snap_count) /
				 top_browser->sum_ksamples));
	ui_browser__set_percent_color(browser, pcnt, current_entry);

	if (top->evlist->nr_entries == 1 || !top->display_weighted) {
		slsmg_printf("%20.2f ", syme->weight);
		width -= 24;
	} else {
		slsmg_printf("%9.1f %10ld ", syme->weight, syme->snap_count);
		width -= 23;
	}

	slsmg_printf("%4.1f%%", pcnt);
	width -= 7;

	if (verbose) {
		slsmg_printf(" %016" PRIx64, symbol->start);
		width -= 17;
	}

	slsmg_printf(" %-*.*s ", top_browser->sym_width, top_browser->sym_width,
		     symbol->name);
	width -= top_browser->sym_width;
	slsmg_write_nstring(width >= syme->map->dso->long_name_len ?
				syme->map->dso->long_name :
				syme->map->dso->short_name, width);
}

static void perf_top_browser__update_rb_tree(struct perf_top_browser *browser)
{
	struct perf_top *top = browser->b.priv;

	browser->root = RB_ROOT;
	browser->b.top = NULL;
	browser->sum_ksamples = perf_top__decay_samples(top, &browser->root);
	perf_top__find_widths(top, &browser->root, &browser->dso_width,
			      &browser->dso_short_width,
                              &browser->sym_width);
	if (browser->sym_width + browser->dso_width > browser->b.width - 29) {
		browser->dso_width = browser->dso_short_width;
		if (browser->sym_width + browser->dso_width > browser->b.width - 29)
			browser->sym_width = browser->b.width - browser->dso_width - 29;
	}
	browser->b.nr_entries = top->rb_entries;
}

static int perf_top_browser__run(struct perf_top_browser *browser)
{
	int key;
	char title[160];
	struct perf_top *top = browser->b.priv;
	int delay_msecs = top->delay_secs * 1000;

	perf_top_browser__update_rb_tree(browser);
        perf_top__header_snprintf(top, title, sizeof(title));
        perf_top__reset_sample_counters(top);

	if (ui_browser__show(&browser->b, title, "ESC: exit") < 0)
		return -1;

	newtFormSetTimer(browser->b.form, delay_msecs);

	while (1) {
		key = ui_browser__run(&browser->b);

		switch (key) {
		case -1:
			/* FIXME we need to check if it was es.reason == NEWT_EXIT_TIMER */
			perf_top_browser__update_rb_tree(browser);
			perf_top__header_snprintf(top, title, sizeof(title));
			perf_top__reset_sample_counters(top);
			ui_browser__set_color(&browser->b, NEWT_COLORSET_ROOT);
			SLsmg_gotorc(0, 0);
			slsmg_write_nstring(title, browser->b.width);
			break;
		case NEWT_KEY_TAB:
		default:
			goto out;
		}
	}
out:
	ui_browser__hide(&browser->b);
	return key;
}

int perf_top__tui_browser(struct perf_top *top)
{
	struct perf_top_browser browser = {
		.b = {
			.entries = &browser.root,
			.refresh = ui_browser__rb_tree_refresh,
			.seek	 = ui_browser__rb_tree_seek,
			.write	 = perf_top_browser__write,
			.priv	 = top,
		},
	};

	ui_helpline__push("Press <- or ESC to exit");
	return perf_top_browser__run(&browser);
}
