//Written by Kilian Singer 18.1.2007
#ifndef __Log_H
#define __Log_H
#include <TApplication.h>
#include <TString.h>
#include <TSystem.h>
#include <iostream>
#include <fstream>

#ifdef WIN32
#include <Windows4Root.h>//is needed otherwise TCanvas.h creates an error at CreateWindow, because this is a macro in MFC
#endif

//#include <TWinNTSystem.h>
#include <TCanvas.h>
#include <TGraph.h>
#include <map>
#include <string>
#include <complex>
typedef std::complex<double> cdouble;


using namespace std;


typedef pair <TString, int> TStringintPair;

//Comments on doxygen: /// are put in comments. If single line then no brief description is supplied.
// ///< comments after memberfunction. If no empty line with ///< or multiple ///< lines are supplied then no brief description is supplied.

///Logging class.
///Creates html log files if Logging(true) is set.
///Different Sections are generated by calling ExpLog.Section. Nesting of logs is possible. 
///Then ExpLog classes have to be nested in brackets as as {ExpLog mainlog(...){ExpLog sublog(...)...}}
class ExpLog{
protected:
	int stdoutnum;
	int stderrnum;
	FILE *fpout;
	FILE *fperr;
	//TString fullpath; ///<path with filename of executable
	TString filename; ///<filename of the Log without html extension. This is the filename part of the fullpath 
	TString directory; ///<directory of Log 
	TString outputdir; ///<directory+filename
	TString logfilename; ///<directory+filename+"html"
	TString readpath;///< Path for all ReadCSV commands.
	TString sectionname;


	bool logging;
	bool StartRedirection();
	bool StopRedirection();
	bool overwrite;
	bool append;
public:
	


	void Append(bool doappend);
	//static bool firsttime;
   map<TString,int> TitelCounter;
   map<TString,int> SessionCounter;
   map<TString,TCanvas*> canvas;
   map<TString,TGraph*> graph;

	/// Constructor for Logging Class.
	/// Create subsections by nesting ExpLogs as {ExpLog mainlog(...){ExpLog sublog(...)...}} 
	/// \param LogFileName The absolute Path and Filename of the logfile
	/// If only stdout logging is needed, then calling with default constructor: ExpLog Log; is enough
	/// If default constructor is used and Logging(true) is called, then the current directory together with the
	/// \param doLogging defaults to false. If set to true then Logging(true) is called in the constructor
	/// and the SetWritePath(path) is called with path derived from LogFileName
	ExpLog(TString LogFileName="",bool doLogging=false); 

	/// Destructor. It also erases all opened Graphs.
	~ExpLog();

	/// Switches between overwriting and appending mode.
	/// First call of Logging(true) overwrites Logfile.
	/// This behaviour can be changed by calling OverwriteLog(false) before the first call of Logging(true).
	/// Subsequent calls to Logging(true) after intermediate Logging(false) appends only to logfile.
	/// If Overwrite(true) is called then it is then also overwritten.
	void Overwrite(bool overwrite);

	/// Sets Path to which all WriteCSV and Print functions write data.
	/// Default the WritePath is the path derived from the expression given in the constructor.
	/// \param LogFileName the path relative to which data is written.
	/// \returns true if path exists
	void SetLogFileName(TString LogFileName="");

	/// Sets Path from which all ReadCSV functions read data.
	/// \param path the path relative to which data is read.
	/// \returns true if path exists
	void SetReadPath(TString path);
	
	/// Writes to log file if Logging2 is true otherwise writes to stdout.
	/// \param Logging2 
	bool Logging(bool Logging2);
	
	/// Reads CSV data.
	/// \param filename is relative Filename to the one set at SetReadPath.
	/// If starting with c:/ or ./ ../ </" absolute filename is taken as in function AbsoluteFileName.
	/// \param y[] array of values. X axis is starting from 1 to num.
	/// \param num size of data array. 
	/// \returns amount of read data or -1 in case of error
	int ReadCSV(TString filename,double y[],int n,int skiplines=0,int skipchars=0);   
	
	/// Reads CSV data.
	/// \param filename is relative Filename to the one set at SetReadPath.
	/// if starting with c:/ or ./ ../ </ absolute filename is taken as in function AbsoluteFileName.
	/// \param x[] array of x values.\param y[] array of y values.\param num size of data array.
	/// \returns amount of read data or -1 in case of error
	int ReadCSV(TString filename,double x[],double y[],int num,int skiplines=0,int skipchars=0);  
	
	/// Writes CSV data.
	/// \param filename is truncated with logfilename and additional Section names.
	/// if starting with c:/ or ./ ../ </ absolute filename is taken as in function AbsoluteFileName.
	/// \param y[] array of values. X axis is starting from 1 to num.
	/// \param num amount of values. 
	bool WriteCSV(TString filename,double y[],int n); 
	
	/// Writes CSV data. 
	/// \param is truncated with logfilename and additional Section names.
	/// if starting with c:/ or ./ ../ </ absolute filename is taken as in function AbsoluteFileName.
	/// \param x[] array of x values.
	/// \param y[] array of y values.
	/// \param num amount of values. 
	bool WriteCSV(TString filename,double x[],double y[],int n); 
	
	/// Writes a graph.
	/// \param graphtitel the titel of the graph.
	bool WriteCSV(TString graphtitel); 



	/// Reads TSV data.
	/// \param filename is relative Filename to the one set at SetReadPath.
	/// If starting with c:/ or ./ ../ </" absolute filename is taken as in function AbsoluteFileName.
	/// \param y[] array of values. X axis is starting from 1 to num.
	/// \param num size of data array. 
	/// \returns amount of read data or -1 in case of error
	int ReadTSV(TString filename,double y[],int n,int skiplines=0,int skipchars=0);   
	
	/// Reads TSV data.
	/// \param filename is relative Filename to the one set at SetReadPath.
	/// if starting with c:/ or ./ ../ </ absolute filename is taken as in function AbsoluteFileName.
	/// \param x[] array of x values.\param y[] array of y values.\param num size of data array.
	/// \returns amount of read data or -1 in case of error
	int ReadTSV(TString filename,double x[],double y[],int num,int skiplines=0,int skipchars=0);  
	
	/// Writes TSV data.
	/// \param filename is truncated with logfilename and additional Section names.
	/// if starting with c:/ or ./ ../ </ absolute filename is taken as in function AbsoluteFileName.
	/// \param y[] array of values. X axis is starting from 1 to num.
	/// \param num amount of values. 
	bool WriteTSV(TString filename,double y[],int n); 
	
	/// Writes TSV data. 
	/// \param filename is truncated with logfilename and additional Section names.
	/// if starting with c:/ or ./ ../ </ absolute filename is taken as in function AbsoluteFileName.
	/// \param x[] array of x values.
	/// \param y[] array of y values.
	/// \param num amount of values. 
	bool WriteTSV(TString filename,double x[],double y[],int n); 
	
	/// Writes a graph.
	/// \param graphtitel the titel of the graph.
	bool WriteTSV(TString graphtitel); 





	void Graph(TString graphtitel,double x[],double y[],int num,TString xtitle="",TString ytitle="",TString style="A*",int color=1,int linewidth=1,int linestyle=1,double markersize=1,int markersyle=1,bool showtitel=true,double xstart=0,double xstop=0,double ystart=0,double ystop=0,cdouble *complx=0,bool plotnegated=false,double scale=30000,int xpos=100,int ypos=100,int width=800,int height=600); ///<Opens a new graph.
	void Graph(TString graphtitel,TString plotingraph,double x[],double y[],int num,TString style="*",int color=1,int linewidth=1,int linestyle=1,double markersize=1,int markersyle=1,bool showtitle=true,double ystart=0,double xstop=0,double xstart=0,double ystop=0,cdouble *complx=0,bool plotnegated=false,double scale=30000,int xpos=100,int ypos=100,int width=800,int height=600); ///<Opens a new graph.

	void CloseGraph(TString graphtitel); ///<Closes graph with name graphtitel. Called with no args calls CloseAllGraphs()
	void CloseAllGraphs();
	
	TCanvas *GetCanvas(TString graphtitel);  ///<Gets TCanvas of graph with name graphtitel. \returns Pointer to TCanvas object.
	
	TGraph *GetGraph(TString graphtitel); ///<Gets TGraph of graph with name graphtitel. \returns Pointer to TCanvas object.
    
	/// Writes Graph with name graphtitel to logfile.
	/// \param graphtitel the titel name of the graph.
	/// \param extension the extension name "root", "cxx", "eps" of the file created additionally as a link.
	void Print(TString graphtitel,TString extension="root"); 

	/// Writes Graph on TCanvas canvas to logfile.
	/// \param graphtitel the titel name of the graph.
	/// \param extension the extension name "root", "cxx", "eps" of the file created additionally as a link.
    void PrintCanvas(TCanvas *canvas, TString graphtitel,TString extension="root"); 
	
	void Section(TString sectionname);///<Sets the current section in a non hirarchical way.
	void AbsoluteFileName(TString fname,TString &absfile);///<Generates an absolute filename out of a relative one
	void AbsoluteFileName(TString fname,TString currentdirectory,TString &absfile);///<Generates an absolute filename out of a relative one
	void Reset();///<Resets the Logging. A new log is started.
	void CleanUpTitelCounter(TString outputdir2);
	void Finish();
	TString& GetLogFileName(){return filename;}
};

extern ExpLog logfile;
extern std::ostream &Cout;


#endif //__Log_H