/*
 * 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 <iostream>
#include <malloc.h>
#include <algorithm>
#include <string.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#include "perf_bundle.h"
#include "perf_event.h"
#include "perf.h"

#include "../cpu/cpu.h"

#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
# define USE_DECLTYPE
#endif

class perf_bundle_event: public perf_event
{
public:
	perf_bundle_event(void);
	virtual void handle_event(struct perf_event_header *header, void *cookie);
};

perf_bundle_event::perf_bundle_event(void) : perf_event()
{
}


void perf_bundle_event::handle_event(struct perf_event_header *header, void *cookie)
{
	unsigned char *buffer;
	vector<void *> *vector;

	buffer = (unsigned char *)malloc(header->size);
	memcpy(buffer, header, header->size);

#ifdef USE_DECLTYPE
	vector = (decltype(vector))cookie;
#else
	vector = (typeof(vector))cookie;
#endif
	vector->push_back(buffer);
}


void perf_bundle::release(void)
{
	class perf_event *ev;
	unsigned int i = 0;

	for (i = 0; i < events.size(); i++) {
		ev = events[i];
		if (!ev)
			continue;
		ev->clear();
		delete ev;
	}
	events.clear();

	for (i = 0; i < event_names.size(); i++) {
		free((void*)event_names[i]);
	}
	event_names.clear();

	for(i = 0; i < records.size(); i++) {
		free(records[i]);
	}
	records.clear();
}

static char * read_file(const char *file)
{
	char *buffer = NULL; /* quient gcc */
	char buf[4096];
	int len = 0;
	int fd;
	int r;

	fd = open(file, O_RDONLY);
	if (fd < 0)
		exit(-1);

	while((r = read(fd, buf, 4096)) > 0) {
		if (len) {
			char *tmp = (char *)realloc(buffer, len + r + 1);
			if (!tmp)
				free(buffer);
			buffer = tmp;
		} else
			buffer = (char *)malloc(r + 1);
		if (!buffer)
			goto out;
		memcpy(buffer + len, buf, r);
		len += r;
		buffer[len] = '\0';
	}
out:
	return buffer;
}

static void parse_event_format(const char *event_name)
{
	char *tptr;
	char *name = strdup(event_name);
	char *sys = strtok_r(name, ":", &tptr);
	char *event = strtok_r(NULL, ":", &tptr);
	char *file;
	char *buf;

	file = (char *)malloc(strlen(sys) + strlen(event) +
		      strlen("/sys/kernel/debug/tracing/events////format") + 2);
	sprintf(file, "/sys/kernel/debug/tracing/events/%s/%s/format", sys, event);

	buf = read_file(file);
	free(file);
	if (!buf)
		return;

	pevent_parse_event(perf_event::pevent, buf, strlen(buf), sys);
	free(name);
	free(buf);
}

bool perf_bundle::add_event(const char *event_name)
{
	unsigned int i;
	int event_added = false;
	class perf_event *ev;


	for (i = 0; i < all_cpus.size(); i++) {

		if (!all_cpus[i])
			continue;

		ev = new class perf_bundle_event();

		ev->set_event_name(event_name);
		ev->set_cpu(i);

		if ((int)ev->trace_type >= 0) {
			if (event_names.find(ev->trace_type) == event_names.end()) {
				event_names[ev->trace_type] = strdup(event_name);
				parse_event_format(event_name);
			}
			events.push_back(ev);
			event_added = true;
		} else {
			delete ev;
		}
	}
	return event_added;
}

void perf_bundle::start(void)
{
	unsigned int i;
	class perf_event *ev;

	for (i = 0; i < events.size(); i++) {
		ev = events[i];
		if (!ev)
			continue;
		ev->start();
	}
}
void perf_bundle::stop(void)
{
	unsigned int i;
	class perf_event *ev;

	for (i = 0; i < events.size(); i++) {
		ev = events[i];
		if (!ev)
			continue;
		ev->stop();
	}
}
void perf_bundle::clear(void)
{
	unsigned int i;

	class perf_event *ev;

	for (i = 0; i < events.size(); i++) {
		ev = events[i];
		if (!ev)
			continue;
		ev->clear();
	}

	for (i = 0; i < records.size(); i++) {
		free(records[i]);
	}
	records.resize(0);
}


struct trace_entry {
	uint64_t		time;
	uint32_t		cpu;
	uint32_t		res;
	__u32			size;
} __attribute__((packed));;


struct perf_sample {
	struct perf_event_header        header;
	struct trace_entry		trace;
	unsigned char			data[0];
} __attribute__((packed));

static uint64_t timestamp(perf_event_header *event)
{
	struct perf_sample *sample;

	if (event->type != PERF_RECORD_SAMPLE)
		return 0;

	sample = (struct perf_sample *)event;

#if 0
	int i;
	unsigned char *x;

	printf("header:\n");
	printf("	type  is %x \n", sample->header.type);
	printf("	misc  is %x \n", sample->header.misc);
	printf("	size  is %i \n", sample->header.size);
	printf("sample:\n");
	printf("	time  is %llx \n", sample->trace.time);
	printf("	cpu   is %i / %x \n", sample->trace.cpu, sample->trace.cpu);
	printf("	res   is %i / %x \n", sample->trace.res, sample->trace.res);
	printf("	size  is %i / %x \n", sample->trace.size, sample->trace.size);
	printf("	type  is %i / %x \n", sample->trace.type, sample->trace.type);
	printf("	flags is %i / %x \n", sample->trace.flags, sample->trace.flags);
	printf("	p/c   is %i / %x \n", sample->trace.preempt_count, sample->trace.preempt_count);
	printf("	pid   is %i / %x \n", sample->trace.pid, sample->trace.pid);
	printf("	lock dept  is %i / %x \n", sample->trace.lock_depth, sample->trace.lock_depth);

	x = (unsigned char *)sample;
	for (i = 0; i < sample->header.size; i++)
		printf("%02x ", *(x+i));
	printf("\n");
#endif
	return sample->trace.time;

}

static bool event_sort_function (void *i, void *j)
{
	struct perf_event_header *I, *J;

	I = (struct perf_event_header *) i;
	J = (struct perf_event_header *) j;
	return (timestamp(I)<timestamp(J));
}

void perf_bundle::process(void)
{
	unsigned int i;
	class perf_event *ev;

	/* fixme: reserve enough space in the array in one go */
	for (i = 0; i < events.size(); i++) {
		ev = events[i];
		if (!ev)
			continue;
		ev->process(&records);
	}
	sort(records.begin(), records.end(), event_sort_function);

	for (i = 0; i < records.size(); i++) {
		struct perf_sample *sample;

		sample = (struct perf_sample *)records[i];
		if (!sample)
			continue;

		if (sample->header.type != PERF_RECORD_SAMPLE)
			continue;

		handle_trace_point(&sample->data, sample->trace.cpu, sample->trace.time);
	}
}

void perf_bundle::handle_trace_point(void *trace, int cpu, uint64_t time)
{
	printf("UH OH... abstract handle_trace_point called\n");
}
