#pragma once
#include<iostream>
#include<string>
#include<time.h>
#include<map>
#include<stdarg.h>
#include<assert.h>
#include<Windows.h>
using namespace std;
typedef long long LongType;
//性能剖析器PerformanceProtiler
template<class T>
class Singleton
{
public:
	static T* GetInstance()
	{
		return _instance;
	}
protected:
	static T* _instance;
	Singleton()
	{};
	Singleton(const Singleton& s);
	Singleton& operator=(const Singleton& s);
};
template<class T>
T* Singleton<T>::_instance = new T;
class SaveAdapter
{
public:
	virtual void Save(const char* fmt, ...)=0;
};
class ConsoleSaveAdapter :public SaveAdapter
{
public:
	void Save(const char* fmt, ...)
	{
		va_list args;
		va_start(args, fmt);
		vfprintf(stdout, fmt, args);
		va_end(args);
	}
};
class FileSaveAdapter :public ConsoleSaveAdapter
{
public:
	FileSaveAdapter(const char* filename = "PerformanceProfiler.txt")
	{
		_fout = fopen(filename, "w");
		assert(_fout);
	}
	~FileSaveAdapter()
	{
		fclose(_fout);
	}
	void Save(const char* fmt,...)
	{
		va_list args;
		va_start(args, fmt);
		vfprintf(_fout, fmt, args);
		va_end(args);
	}
private:
	FILE* _fout;
};


struct PPNode
{
	string _filename;   //文件名
	string _function;   //函数名
	size_t _line;       //行号
	string _desc;       //描述description
	PPNode(const char* filename = "", const char* function = "", \
		size_t line = 0, const char* desc = "")
		:_filename(filename)
		, _function(function)
		, _line(line)
		, _desc(desc)
	{}
	bool operator<(const PPNode& node)const
	{
		return _line < node._line || _filename < node._filename || _function < node._function || \
			_desc < node._desc;
	}
};

struct PPSection
{
	LongType _startTime;
	LongType _costTime;
	LongType _callCount;
	struct PPSection()
		:_startTime(0)
		, _costTime(0)
		, _callCount(0)
	{}
	void Begin()
	{
		_startTime = clock();
		++_callCount;
	}
	void End()
	{
		_costTime += (clock() - _startTime);
		cout << _callCount << endl;
	}
};
class PerformanceProfiler :public Singleton<PerformanceProfiler>
{
public:
	friend class  Singleton<PerformanceProfiler>;
	PerformanceProfiler()
	{}
	PPSection* CreateSection(const char* filename, const char* function, size_t line, \
		const char* desc)
	{
		PPNode node(filename, function, line, desc);
		PPSection* &section = _ppMap[node];
		if (section == NULL)
		{
			section = new PPSection;
		}
		return section;
	}
	void OutPut()
	{
		ConsoleSaveAdapter css;
		_OutPut(css);
		FileSaveAdapter  fss;
		_OutPut(fss);
	}
	
protected:
	void _OutPut(SaveAdapter& sa)
	{
		map<PPNode, PPSection*>::iterator it = _ppMap.begin();
		while (it != _ppMap.end())
		{
			const PPNode& node = it->first;
			const PPSection* section = it->second;
			sa.Save("Filename:%s , Function:%s , Line:%u , Desc:%s\n", \
				node._filename.c_str(), node._function.c_str(), node._line, node._desc.c_str());
			sa.Save("CostTime:%u,CallCount:%d\n", section->_costTime,section->_callCount);
			++it;
		}
	}
	map<PPNode, PPSection*> _ppMap;
};

struct Realease
{
	~Realease()
	{
		PerformanceProfiler::GetInstance()->OutPut();
	}
};

#define PERFORMANCE_PROFILER_EE_BEGIN(sign,desc)\
	PPSection* sign##section = PerformanceProfiler::GetInstance()\
	->CreateSection(__FILE__, __FUNCTION__, __LINE__, desc); \
	sign##section->Begin();

#define PERFORMANCE_PROFILER_EE_END(sign)\
	sign##section->End();
Realease r;
void TestSleep()
{
	PERFORMANCE_PROFILER_EE_BEGIN(Sleep, "休眠");

	//...
	Sleep(2000);

	PERFORMANCE_PROFILER_EE_END(Sleep);
}
void TestDataBase()
{
	PERFORMANCE_PROFILER_EE_BEGIN(sql, "数据库");
	//...数据库
	Sleep(100);

	PERFORMANCE_PROFILER_EE_END(sql);

	PERFORMANCE_PROFILER_EE_BEGIN(network, "网络");
	//...
	Sleep(200);

	PERFORMANCE_PROFILER_EE_END(network);
}

void Test1()
{
	//TestSleep();
	TestDataBase();
	PerformanceProfiler::GetInstance()->OutPut();

}