/**
 * @file opreport.cpp
 * Implement opreport utility
 *
 * @remark Copyright 2003 OProfile authors
 * @remark Read the file COPYING
 *
 * @author John Levon
 * @author Philippe Elie
 */

#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <sstream>
#include <numeric>

#include "op_exception.h"
#include "stream_util.h"
#include "string_manip.h"
#include "file_manip.h"
#include "opreport_options.h"
#include "op_header.h"
#include "profile.h"
#include "populate.h"
#include "arrange_profiles.h"
#include "profile_container.h"
#include "callgraph_container.h"
#include "diff_container.h"
#include "symbol_sort.h"
#include "format_output.h"
#include "xml_utils.h"
#include "image_errors.h"

using namespace std;

namespace {

static size_t nr_classes;

/// storage for a merged file summary
struct summary {
	count_array_t counts;
	string lib_image;

	bool operator<(summary const & rhs) const {
		return options::reverse_sort
		    ? counts[0] < rhs.counts[0] : rhs.counts[0] < counts[0];
	}

	/// add a set of files to a summary
	count_type add_files(list<profile_sample_files> const & files,
	                     size_t pclass);
};


count_type summary::
add_files(list<profile_sample_files> const & files, size_t pclass)
{
	count_type subtotal = 0;

	list<profile_sample_files>::const_iterator it = files.begin();
	list<profile_sample_files>::const_iterator const end = files.end();

	for (; it != end; ++it) {
		count_type count = profile_t::sample_count(it->sample_filename);
		counts[pclass] += count;
		subtotal += count;

		if (!it->cg_files.empty()) {
			throw op_runtime_error("opreport.cpp::add_files(): "
			       "unxpected non empty cg file set");
		}
	}

	return subtotal;
}


/**
 * Summary of an application: a set of image summaries
 * for one application, i.e. an application image and all
 * dependent images such as libraries.
 */
struct app_summary {
	/// total count of us and all dependents
	count_array_t counts;
	/// the main image
	string image;
	/// our dependent images
	vector<summary> deps;

	/// construct and fill in the data
	count_type add_profile(profile_set const & profile, size_t pclass);

	bool operator<(app_summary const & rhs) const {
		return options::reverse_sort 
		    ? counts[0] < rhs.counts[0] : rhs.counts[0] < counts[0];
	}

private:
	/// find a matching summary (including main app summary)
	summary & find_summary(string const & image);
};


summary & app_summary::find_summary(string const & image)
{
	vector<summary>::iterator sit = deps.begin();
	vector<summary>::iterator const send = deps.end();
	for (; sit != send; ++sit) {
		if (sit->lib_image == image)
			return *sit;
	}

	summary summ;
	summ.lib_image = image;
	deps.push_back(summ);
	return deps.back();
}


count_type app_summary::add_profile(profile_set const & profile,
                                size_t pclass)
{
	count_type group_total = 0;

	// first the main image
	summary & summ = find_summary(profile.image);
	count_type app_count = summ.add_files(profile.files, pclass);
	counts[pclass] += app_count;
	group_total += app_count;

	// now all dependent images if any
	list<profile_dep_set>::const_iterator it = profile.deps.begin();
	list<profile_dep_set>::const_iterator const end = profile.deps.end();

	for (; it != end; ++it) {
		summary & summ = find_summary(it->lib_image);
		count_type lib_count = summ.add_files(it->files, pclass);
		counts[pclass] += lib_count;
		group_total += lib_count;
	}

	return group_total;
}


/// all the summaries
struct summary_container {
	summary_container(vector<profile_class> const & pclasses);

	/// all map summaries
	vector<app_summary> apps;
	/// total count of samples for all summaries
	count_array_t total_counts;
};


summary_container::
summary_container(vector<profile_class> const & pclasses)
{
	typedef map<string, app_summary> app_map_t;
	app_map_t app_map;

	for (size_t i = 0; i < pclasses.size(); ++i) {
		list<profile_set>::const_iterator it
			= pclasses[i].profiles.begin();
		list<profile_set>::const_iterator const end
			= pclasses[i].profiles.end();

		for (; it != end; ++it) {
			app_map_t::iterator ait = app_map.find(it->image);
			if (ait == app_map.end()) {
				app_summary app;
				app.image = it->image;
				total_counts[i] += app.add_profile(*it, i);
				app_map[app.image] = app;
			} else {
				total_counts[i]
					+= ait->second.add_profile(*it, i);
			}
		}
	}

	app_map_t::const_iterator it = app_map.begin();
	app_map_t::const_iterator const end = app_map.end();

	for (; it != end; ++it)
		apps.push_back(it->second);

	// sort by count
	stable_sort(apps.begin(), apps.end());
	vector<app_summary>::iterator ait = apps.begin();
	vector<app_summary>::iterator const aend = apps.end();
	for (; ait != aend; ++ait)
		stable_sort(ait->deps.begin(), ait->deps.end());
}


void output_header()
{
	if (!options::show_header)
		return;

	cout << classes.cpuinfo << endl;
	if (!classes.event.empty())
		cout << classes.event << endl;

	for (vector<profile_class>::size_type i = 0;
	     i < classes.v.size(); ++i) {
		cout << classes.v[i].longname << endl;
	}
}


string get_filename(string const & filename)
{
	return options::long_filenames ? filename : op_basename(filename);
}


/// Output a count and a percentage
void output_count(count_type total_count, count_type count)
{
	cout << setw(9) << count << ' ';
	double ratio = op_ratio(count, total_count);
	cout << format_percent(ratio * 100, percent_int_width,
			      percent_fract_width) << ' ';
}


void output_col_headers(bool indent)
{
	if (!options::show_header)
		return;

	if (indent)
		cout << '\t';

	size_t colwidth = 9 + 1 + percent_width;

	for (size_t i = 0; i < classes.v.size(); ++i) {
		string name = classes.v[i].name;
		if (name.length() > colwidth)
			name = name.substr(0, colwidth - 3)
				+ "...";
		io_state state(cout);
		// gcc 2.95 doesn't know right io manipulator
		cout.setf(ios::right, ios::adjustfield);
		// gcc 2.95 doesn't honor setw() for std::string
		cout << setw(colwidth) << name.c_str();
		cout << '|';
	}
	cout << '\n';

	if (indent)
		cout << '\t';

	for (size_t i = 0; i < classes.v.size(); ++i) {
		cout << "  samples| ";
		io_state state(cout);
		// gcc 2.95 doesn't know right io manipulator
		cout.setf(ios::right, ios::adjustfield);
		cout << setw(percent_width) << "%|";
	}

	cout << '\n';

	if (indent)
		cout << '\t';

	for (size_t i = 0; i < classes.v.size(); ++i) {
		cout << "-----------";
		string str(percent_width, '-');
		cout << str;
	}

	cout << '\n';
}


void
output_deps(summary_container const & summaries,
	    app_summary const & app)
{
	// the app summary itself is *always* present
	// (perhaps with zero counts) so this test
	// is correct
	if (app.deps.size() == 1)
		return;

	output_col_headers(true);

	for (size_t j = 0 ; j < app.deps.size(); ++j) {
		summary const & summ = app.deps[j];

		if (summ.counts.zero())
			continue;

		cout << '\t';

		for (size_t i = 0; i < nr_classes; ++i) {
			count_type tot_count = options::global_percent
				? summaries.total_counts[i] : app.counts[i];

			output_count(tot_count, summ.counts[i]);
		}

		cout << get_filename(summ.lib_image);
		cout << '\n';
	}
}


/**
 * Display all the given summary information
 */
void output_summaries(summary_container const & summaries)
{
	output_col_headers(false);

	for (size_t i = 0; i < summaries.apps.size(); ++i) {
		app_summary const & app = summaries.apps[i];
		double ratio = (!summaries.total_counts[0]) ? 0
		                                            : (app.counts[0] * 100.0)/
		                                              summaries.total_counts[0];
		if (ratio < options::threshold) {
			continue;
		}

		for (size_t j = 0; j < nr_classes; ++j)
			output_count(summaries.total_counts[j], app.counts[j]);

		cout << get_filename(app.image) << '\n';

		output_deps(summaries, app);
	}
}


format_flags get_format_flags(column_flags const & cf)
{
	format_flags flags(ff_none);
	flags = format_flags(flags | ff_nr_samples);
	flags = format_flags(flags | ff_percent | ff_symb_name);

	if (options::show_address)
		flags = format_flags(flags | ff_vma);

	if (options::debug_info)
		flags = format_flags(flags | ff_linenr_info);

	if (options::accumulated) {
		flags = format_flags(flags | ff_nr_samples_cumulated);
		flags = format_flags(flags | ff_percent_cumulated);
	}

	if (classes2.v.size())
		flags = format_flags(flags | ff_diff);

	if (cf & cf_image_name)
		flags = format_flags(flags | ff_image_name);

	return flags;
}


void output_symbols(profile_container const & pc, bool multiple_apps)
{
	profile_container::symbol_choice choice;
	choice.threshold = options::threshold;
	symbol_collection symbols = pc.select_symbols(choice);
	options::sort_by.sort(symbols, options::reverse_sort,
	                      options::long_filenames);
	format_output::formatter * out;
	format_output::xml_formatter * xml_out = 0;
	format_output::opreport_formatter * text_out = 0;

	if (options::xml) {
		xml_out = new format_output::xml_formatter(&pc, symbols,
			pc.extra_found_images, options::symbol_filter);
		xml_out->show_details(options::details);
		out = xml_out;
		// for XML always output long filenames
		out->show_long_filenames(true);
	} else {
		text_out = new format_output::opreport_formatter(pc);
		text_out->show_details(options::details);
		out = text_out;
		out->show_long_filenames(options::long_filenames);
	}

	out->set_nr_classes(nr_classes);
	out->show_header(options::show_header);
	out->vma_format_64bit(choice.hints & cf_64bit_vma);
	out->show_global_percent(options::global_percent);

	format_flags flags = get_format_flags(choice.hints);
	if (multiple_apps)
		flags = format_flags(flags | ff_app_name);

	out->add_format(flags);

	if (options::xml) {
		xml_support = new xml_utils(xml_out, symbols, nr_classes,
			pc.extra_found_images);
		xml_out->output(cout);
	} else {
		text_out->output(cout, symbols);
	}
}


void output_diff_symbols(profile_container const & pc1,
                         profile_container const & pc2, bool multiple_apps)
{
	diff_container dc(pc1, pc2);

	profile_container::symbol_choice choice;
	choice.threshold = options::threshold;

	diff_collection symbols = dc.get_symbols(choice);

	format_flags flags = get_format_flags(choice.hints);
	if (multiple_apps)
		flags = format_flags(flags | ff_app_name);

	// With diff profile we output only filename coming from the first
	// profile session, internally we use only name derived from the sample
	// filename so image name can match.
	format_output::diff_formatter out(dc, pc1.extra_found_images);

	out.set_nr_classes(nr_classes);
	out.show_long_filenames(options::long_filenames);
	out.show_header(options::show_header);
	out.show_global_percent(options::global_percent);
	out.vma_format_64bit(choice.hints & cf_64bit_vma);
	out.add_format(flags);

	options::sort_by.sort(symbols, options::reverse_sort,
	                      options::long_filenames);

	out.output(cout, symbols);
}


void output_cg_symbols(callgraph_container const & cg, bool multiple_apps)
{
	column_flags output_hints = cg.output_hint();

	symbol_collection symbols = cg.get_symbols();

	options::sort_by.sort(symbols, options::reverse_sort,
	                      options::long_filenames);

	format_output::formatter * out;
	format_output::xml_cg_formatter * xml_out = 0;
	format_output::cg_formatter * text_out = 0;

	if (options::xml) {
		xml_out = new format_output::xml_cg_formatter(cg, symbols,
			options::symbol_filter);
		xml_out->show_details(options::details);
		out = xml_out;
		// for XML always output long filenames
		out->show_long_filenames(true);
	} else {
		text_out = new format_output::cg_formatter(cg);
		out = text_out;
		out->show_long_filenames(options::long_filenames);
	}

	out->set_nr_classes(nr_classes);
	out->show_header(options::show_header);
	out->vma_format_64bit(output_hints & cf_64bit_vma);
	out->show_global_percent(options::global_percent);

	format_flags flags = get_format_flags(output_hints);
	if (multiple_apps)
		flags = format_flags(flags | ff_app_name);

	out->add_format(flags);

	if (options::xml) {
		xml_support = new xml_utils(xml_out, symbols, nr_classes,
			cg.extra_found_images);
		xml_out->output(cout);
	} else {
		text_out->output(cout, symbols);
	}

}


int opreport(options::spec const & spec)
{
	want_xml = options::xml;

	handle_options(spec);

	nr_classes = classes.v.size();

	if (!options::symbols && !options::xml) {
		summary_container summaries(classes.v);
		output_header();
		output_summaries(summaries);
		return 0;
	}

	bool multiple_apps = false;

	for (size_t i = 0; i < classes.v.size(); ++i) {
		if (classes.v[i].profiles.size() > 1)
			multiple_apps = true;
	}

	list<inverted_profile> iprofiles = invert_profiles(classes);

	report_image_errors(iprofiles, classes.extra_found_images);

	if (options::xml) {
		xml_utils::output_xml_header(options::command_options,
		                             classes.cpuinfo, classes.event);
	} else {
		output_header();
	}

	if (classes2.v.size()) {
		for (size_t i = 0; i < classes2.v.size(); ++i) {
			if (classes2.v[i].profiles.size() > 1)
				multiple_apps |= true;
		}

		profile_container pc1(options::debug_info, options::details,
				      classes.extra_found_images);

		list<inverted_profile>::iterator it = iprofiles.begin();
		list<inverted_profile>::iterator const end = iprofiles.end();

		for (; it != end; ++it)
			populate_for_image(pc1, *it,
					   options::symbol_filter, 0);

		list<inverted_profile> iprofiles2 = invert_profiles(classes2);

		report_image_errors(iprofiles2, classes2.extra_found_images);

		profile_container pc2(options::debug_info, options::details,
				      classes2.extra_found_images);

		list<inverted_profile>::iterator it2 = iprofiles2.begin();
		list<inverted_profile>::iterator const end2 = iprofiles2.end();

		for (; it2 != end2; ++it2)
			populate_for_image(pc2, *it2,
					   options::symbol_filter, 0);

		output_diff_symbols(pc1, pc2, multiple_apps);
	} else if (options::callgraph) {
		callgraph_container cg_container;
		cg_container.populate(iprofiles, classes.extra_found_images,
			options::debug_info, options::threshold,
			options::merge_by.lib, options::symbol_filter);

		output_cg_symbols(cg_container, multiple_apps);
	} else {
		profile_container samples(options::debug_info,
			options::details, classes.extra_found_images);

		list<inverted_profile>::iterator it = iprofiles.begin();
		list<inverted_profile>::iterator const end = iprofiles.end();

		for (; it != end; ++it)
			populate_for_image(samples, *it,
					   options::symbol_filter, 0);

		output_symbols(samples, multiple_apps);
	}

	return 0;
}

}  // anonymous namespace


int main(int argc, char const * argv[])
{
	cout.tie(0);
	return run_pp_tool(argc, argv, opreport);
}
