
/**
@author d金魚
@since 2005/12/28
*/
#ifndef DKUTIL_RANKING_TIMER_HPP
#define DKUTIL_RANKING_TIMER_HPP

#include <dkutil/timer.hpp>

namespace dkutil{

template<class ClockPolicy = policy::ranking_timer_type,class OutputPolicy = policy::DebugReport>
class ranking_timer2_base : public boost::noncopyable{
public:

	typedef typename ClockPolicy timer_type;
	typedef typename ranking_timer2_base<ClockPolicy,OutputPolicy> self_type;
	typedef typename boost::noncopyable base_type;
	typedef typename self_type self_ranking_timer_type;
	typedef typename LONGLONG time_type;

	typedef typename std::multimap<time_type,std::string> container_type;
	typedef typename container_type::value_type data_type;
	
private:
	timer_type mT;
	container_type mC;
	///ファイル名
	std::string mFName;

public:

	virtual void sort_output()const{
#	if defined(DEBUG) || defined(_DEBUG)
		const char *cmode = "DEBUG";
#	else
		const char *cmode = "RELEASE";
#	endif

		OutputPolicy::Output(0,mFName.c_str(),"ranking_tiemr / clock type : %s / compile mode : %s"
			,mT.GetOutputSignature(false),cmode);

		{
			size_t i = 1;
			std::string ts;
			LONGLONG t;
			std::string rt = "%d\t/ %s\t/ ";
			rt += timer_type::getFormat();//"%d\t/ %s\t/ %lf";
			for(container_type::const_iterator it=mC.begin();
			it != mC.end();it++,i++)
			{
				
				ts = boost::io::str(boost::format(rt)
					% i % (*it).second.c_str() % (*it).first);
				OutputPolicy::Output((double)(*it).first,mFName.c_str(),ts.c_str());
			}
		}
	}
	ranking_timer2_base(){	}
	~ranking_timer2_base(){
		sort_output();
	}
	///ranking_timer2_baseクラスが使うタイマー
	template<class RTT>
	struct scoped_timer_base{
		timer_type mT;
		RTT *mPtr;
		std::string mName;
		/*!
		@param name[in] 出力する時に一緒に出力する文字列（いわいる識別子）
		@param ptr[in] ranking_timer2_baseクラスへのポインタ
		@todo
		このranking_timer2_baseクラスへのポインタを渡すところが
		ダサくて嫌いなのですが、これしか思いつきません＾＾；
		どちら様か、奨励できる実装がありましたら、どうか教えてください。m(_ _)m
		*/
		scoped_timer_base(const char *name,RTT *ptr){
			dkcmFORCE_NOT_ASSERT(NULL==ptr);
			mPtr = ptr;
			mName = name;
			mT.restart();
		}
		~scoped_timer_base(){
			RTT::time_type t = mT.getTime();
			if(false==mPtr->insert(mName.c_str(),t))
			{
				dkcmFORCE_NOT_ASSERT("ranking_timer2_base::scoped_timer insert error");
			}
		}
		void restart(){
			mT.restart();
		}
	};
	typedef typename scoped_timer_base<self_type> scoped_timer;
	
	bool insert(const char *name,time_type time){
		data_type d(time,name);

		

		container_type::iterator it = mC.insert(d);
		return mC.end() != it;
	}
	void clear(){
		mC.clear();
	}
	void setFilename(parm_string str){
		mFName = str.c_str();
	}
	void print(parm_string str){
		OutputPolicy::Output(0,mFName.c_str(),str.c_str());
	}
	void print_arg(const char *pb,...){
		char s[512];
		SET_VA_LIST(s,sizeof(s),pb);
		print(s);
	}
};

typedef ranking_timer2_base<> ranking_timer2;
#ifdef WIN32
typedef ranking_timer2_base<MilliSecondClock> msec_ranking_timer2;
typedef ranking_timer2_base<QueryPerformanceClock> qp_ranking_timer2;
#endif




}//end of dkutil namespace


#endif //end of include once