
#pragma once
#ifndef AI_LOG_HPP
#define AI_LOG_HPP

#pragma warning(push)
#include <stlport\string>
#include <stlport\vector>
#pragma warning(pop)
#include "AI_UserConstants.hpp"
#include "AI_TacticInterface.hpp"
#include "AI_FireData.hpp"
#include <Stuff\Auto_Ptr.hpp>


namespace MechWarrior4
{
	class MWObject;
};

namespace MW4AI
{
	class LogNode
	{
	  public:
		enum Type
		{
			TYPE_PARAMETER,		// change TYPE_FIRST if you change this
			TYPE_RETURN_VALUE,
			TYPE_FUNCTION		// change TYPE_LAST if you change this
		};

		LogNode(Type type, const std::string& text, const std::string& label = "");
		LogNode(Type type, const std::string& text, const std::string& label, const std::string& filename, int line_number);
		~LogNode();

		LogNode* AddChild(Type type, const std::string& text, const std::string& label = "");
		LogNode* AddChild(Type type, const std::string& text, const std::string& label, const std::string& filename, int line_number);
		LogNode* Find(const std::string& text);

		std::string GetText() const;
		std::string GetLabel() const;
		Type GetType() const;
		std::string GetFile() const;
		int GetLine() const;

		void SpewToString(std::string& output, unsigned int level = 0, bool first_in_row = false) const;

	  private:
		const std::string m_Text;
		const std::string m_Label;
		std::vector<LogNode*> m_Children;
		const Type m_Type;
		const std::string m_File;
		const int m_Line;

		enum
		{
			TYPE_FIRST = TYPE_PARAMETER,
			TYPE_LAST = TYPE_FUNCTION
		};
	};

	class DiagnosticsInterface
	{
	  public:
		DiagnosticsInterface();
		~DiagnosticsInterface();

		static DiagnosticsInterface& GetInstance();

		void Log(LogNode::Type type, const std::string& value, const std::string& label = "");
		void Log(LogNode::Type type, const Stuff::Scalar& value, const std::string& label = "");
		void Log(LogNode::Type type, const Stuff::Point3D& value, const std::string& label = "");
		void Log(LogNode::Type type, const int& value, const std::string& label = "");
		void Log(LogNode::Type type, const bool& value, const std::string& label = "");
		void Log(LogNode::Type type, const TacticInterface::WR_WHO& value, const std::string& label = "");
		void Log(LogNode::Type type, const TacticInterface::WR_QUALIFIER& value, const std::string& label = "");
		void Log(LogNode::Type type, const Stuff::Time& value, const std::string& label = "");
		void Log(LogNode::Type type, const UserConstants::ID& value, const std::string& label = "");
		void Log(LogNode::Type type, const FireStyles::FireStyleID& value, const std::string& label = "");
		void Log(LogNode::Type type, const FireData::HIT_RESULT& value, const std::string& label = "");

		void PushFunction(const std::string& funcname, const std::string& file, int line);
		void PopFunction(const std::string& funcname);

		void SetEnabled(bool enabled);
		bool GetEnabled() const;

		void SetFileAndLineEnabled(bool enabled);
		bool GetFileAndLineEnabled() const;

		void SetParameterNamesEnabled(bool enabled);
		bool GetParameterNamesEnabled() const;

		void SetFileSpewing(bool enabled);
		bool GetFileSpewing() const;

		void Reset();

		void GetSpew(std::string& output) const;

		void SetExecutingObject(MechWarrior4::MWObject* object);

	  private:
		static DiagnosticsInterface* m_Instance;
		Stuff::Auto_Ptr<LogNode> m_Root;
		std::vector<LogNode*> m_Stack;
		bool m_Enabled;
		bool m_FileAndLineEnabled;
		bool m_ParameterNamesEnabled;
		bool m_FileSpewing;
		MWObject* m_ExecutingObject;
		std::string m_BufferedSpew;

	  private:
		bool CanLog() const;
	};

	class LogFunction
	{
	  public:
		LogFunction(const std::string& name, const std::string& file, int line);
		~LogFunction();

	  private:
		const std::string m_Name;
	};

/*
	// disabled: AI logging is not currently used for anything, so no point wasting time on it, even in Debug

	#ifdef _ARMOR
		#define AILOGFUNC(funcname) MW4AI::LogFunction func(funcname,__FILE__,__LINE__);
		#define AILOGTEXT(value) MW4AI::DiagnosticsInterface::GetInstance().Log(LogNode::TYPE_PARAMETER,(std::string)value);
		#define AILOG(value) MW4AI::DiagnosticsInterface::GetInstance().Log(LogNode::TYPE_PARAMETER,value,#value);
		#define AILOG1(value1) AILOG(value1);
		#define AILOG2(value1,value2) AILOG(value1); AILOG(value2);
		#define AILOG3(value1,value2,value3) AILOG(value1); AILOG(value2); AILOG(value3);
		#define AILOG4(value1,value2,value3,value4) AILOG(value1); AILOG(value2); AILOG(value3); AILOG(value4);
		#define LOG_AND_RETURN(value) MW4AI::DiagnosticsInterface::GetInstance().Log(LogNode::TYPE_RETURN_VALUE,value,"RETURNED"); return (value);
	#else
*/
		#define AILOGFUNC(funcname) ;
		#define AILOGTEXT(value) ;
		#define AILOG(value) ;
		#define AILOG1(value1) ;
		#define AILOG2(value1,value2) ;
		#define AILOG3(value1,value2,value3) ;
		#define AILOG4(value1,value2,value3,value4) ;
		#define LOG_AND_RETURN(value) return (value);

//	#endif
};



#endif // AI_LOG_HPP