// __author__ = Juan Carlos De Abreu (jcabreur@gmail.com)

#include "LogManagement.h"
#include "../Util/Calendar.h"
#include "../Util/string.h"
#include "../Util/Funcs.h"
#include "../GUI/window_management.h"

BEGIN_TEG_NAMESPACE();

using namespace DebugApplication;

// Standard constructor of Debug Management
LogManagement::LogManagement() : nEvents(1) {
	// Initialize the pathName of the Debug Log
	m_lpszPathName = _T("Output/Log.xml");
	// Clear the DebugLog
	InitializeLog();
}

// Destructor of the Debug Managemet
LogManagement::~LogManagement() {
	// Open the output Log
	FILE *f = fopen(m_lpszPathName.c_str(), "a+");
	
	// Finish the Log Managemnet
	fprintf(f, "</RunTimeLog>\n");
	
	// Close the output Log
	fclose(f);
}

// Method to show the Log
void LogManagement::ShowLog() {
	// If is enable the file output of the log
	if(LOG_OUTPUT & LOG_FILE_OUTPUT) {
		// Construct the command line
		std::tstring CmdLine = std::tstring(_T("notepad.exe \'")) + m_lpszPathName + std::tstring(_T("\'"));
		// Show the Log
	//	WinExec(_T(CmdLine.c_str()), SW_SHOW);
	}
}

// Method to initialize the Log
void LogManagement::InitializeLog() {
	// Open the Log Debug
	FILE* f = fopen(_T(m_lpszPathName.c_str()), _T("w"));
	
	Calendar calendar;

	// Print a brief description of the log
	fprintf(f, "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n");
	//fprintf(f, "<?xml-stylesheet type=\"text/xsl\" href=\"Log.xsl\"?>\n");
	fprintf(f, "<!-- Written using LogManagement.cpp, written by Juan Carlos De Abreu -->\n");
	fprintf(f, "<!-- Generated from code compiled on %s at %s -->\n", __DATE__, __TIME__);
	
	// Print the header of the log
	fprintf(f, "<RunTimeLog>\n");
	fprintf(f, "  <LogHeader>\n");
	fprintf(f, "    <OutputLevel> (TODO) </OutputLevel>\n");
	fprintf(f, "    <Session>\n");
	fprintf(f, "      <Started>\n");
	fprintf(f, "        <Time>%s</Time>\n", calendar.GetCurrentTime_().c_str());
	fprintf(f, "        <Date>%s</Date>\n", calendar.GetCurrentDate().c_str());
	fprintf(f, "      </Started>\n");
	fprintf(f, "      <Configuration>\n");
	fprintf(f, "        <Environment>(TODO)</Environment>\n");
	fprintf(f, "        <Processor>\n");
	fprintf(f, "          <Family> (TODO) </Family>\n");
	fprintf(f, "          <Vendor> (TODO) </Vendor>\n");
	fprintf(f, "          <Features> (TODO) </Features>\n");
	fprintf(f, "          <ClockSpeed> (TODO) </ClockSpeed>\n");
	fprintf(f, "        </Processor>\n");
	fprintf(f, "        <Memory>\n");
	fprintf(f, "          <Total> (TODO) </Total>\n");
	fprintf(f, "          <Available> (TODO) </Available>\n");
	fprintf(f, "        </Memory>\n");
	fprintf(f, "      </Configuration>\n");
	fprintf(f, "    </Session>\n");
	fprintf(f, "  </LogHeader>\n");
	
	// Close the Log Debug
	fclose(f);
}

// Method to write a message in the Log
void LogManagement::WriteLog(const _TCHAR* message, ...) {
		
	// Obtain the pointer to the arguments
	va_list args; va_start(args, message);

	// TODO: add the time when occur the message ... 

	// If is enable the file output of the log
	if(LOG_OUTPUT & LOG_FILE_OUTPUT) {
		// Open the Log Debug
		FILE* f = fopen(m_lpszPathName.c_str(), "a+");
		// Print the log message in the file
		vfprintf(f, message, args);
		// Close the Log Debug
		fclose(f);
	}

	// If is enable the standard output of the log
	if(LOG_OUTPUT & LOG_STANDARD_OUTPUT) {
		// Print the log message in the console
		vprintf(message, args);	
	}
}

// Function to convert a line to compatible xml line.
// TODO: Agregar los otros valores que tienen que ser escritos en xml de manera especifica..
std::tstring toCompatibleXML(const std::tstring& str) {
	std::string res;
	const int size = static_cast<int> (str.size());
	for (int i = 0; i < size; ++i) {
		if (str[i] == '&') res += _T("&amp;");
		else if (str[i] == '<' || str[i] == '>')
			res += _T("<![CDATA[") + toString(str[i]) + _T("]]>");
		else res += toString(str[i]);
	}
	return res;
}

// Method to write a message int the log
void LogManagement::WriteLog2(std::tstring strEntryType, std::tstring strSourceFile,
		std::tstring strFunction, int iSourceLine, const _TCHAR* message, ...) {
	// Open the output Log
	FILE *f = fopen(m_lpszPathName.c_str(), "a+");
	
	// Obtain the pointer to the arguments
	va_list args; va_start(args, message);

	// TODO: Use the debug level to know what kind of message will be transfered to the console.
	const std::tstring msg = toString(message, args);
	if (strEntryType != TYPE_EVENT) gui::WindowManagement::GetInstance().console().addMessage(msg);
	// //

	// Print the info of the message
	fprintf(f, "  <LogEvent id=\"%d\">\n", nEvents++);
	fprintf(f, "    <Type>%s</Type>\n", strEntryType.c_str());
	//fprintf(f, "<TimeIndex>TODO</TimeIndex>\n");
	fprintf(f, "    <TimeIndex>%2.2f secs</TimeIndex>\n", (double)clock() / CLOCKS_PER_SEC);
	//fprintf(f, "<File>%s</File>\n", toCompatibleXML(strSourceFile).c_str());
	fprintf(f, "    <File>%s</File>\n", GetFileName(strSourceFile).c_str());
	fprintf(f, "    <Function>%s</Function>\n", strFunction.c_str());
	fprintf(f, "    <LineNumber>%d</LineNumber>\n",iSourceLine);
	fprintf(f, "    <Message>%s</Message>\n", toCompatibleXML(msg).c_str());
//	vfprintf(f, message, args);
//	fprintf(f, "</Message>\n");
	fprintf(f, "  </LogEvent>\n");

	// Close the output Log
	fclose(f);
}

// Method to set the Log pathName 
void LogManagement::SetLogPathName(const _TCHAR* lpszPathName) {
	// Update the Log pathName
	m_lpszPathName = lpszPathName;
}

END_TEG_NAMESPACE();
