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

/**
 * TODO(jcabreur): write a general comment here
 */

#ifndef SCENE_FILE_H__
#define SCENE_FILE_H__

#include "../Base/Singleton.h"
#include "../Scene/Scene.h"
#include "../Base/Functor/Functor1.h"

#include "DataTypes.h"
#include "DataStructures.h"

#include "DataSystemFunctions.h"

BEGIN_TEG_NAMESPACE();

class SceneFile {
public:
	// Attributes
	std::map<std::string, SmartPointer<IData>> variables;
	std::map<std::pair<std::string, int>, SmartPointer<Function>> functions;
	std::vector<SmartPointer<IData>> inst;	

	void apply();

	// Constructor
	SceneFile() { init(); }
	~SceneFile() { release(); }

	// TODO: add the functors ....
	// Add the pointer to functions ....
	void init() {}

	void release() { 
		inst.clear();
		variables.clear();
		functions.clear();
	}

	bool IsEmpty() {
		return !variables.size() && !functions.size() && !inst.size();
	}

	void resolve();
};

#define REGISTER_FUNCTION(name, func) \
	SceneFileManagement::GetInstance().DATAfunctions[name] = \
		FunctorGlobal1<SmartPointer<IData>, std::vector<SmartPointer<IData>>>(func)

#define GET_ID(name) SceneFileManagement::GetInstance().getId(name)

class SceneFileManagement : public Singleton<SceneFileManagement> {
public:
	// Attribues.
	std::vector<std::string> pathFiles;
	std::list<SceneFile> sceneFiles;

	std::map<std::string, FunctorGlobal1<SmartPointer<IData>, std::vector<SmartPointer<IData>>> > DATAfunctions;
	
	int proccessingFile; // Index of the file that is proccessing

	bool isReturning; // To know if the instruction was a return...

	// SceneFileManagement constructor.
	SceneFileManagement() {
		isReturning = false;
		reset_ = false;
	}

	void add(std::tstring s) {
		pathFiles.push_back(s);
		sceneFiles.push_back(SceneFile());
	}

	void init();

	// SceneFileManagement destructor.
	~SceneFileManagement() {
		release();
	}

	void release();

	void apply();

	SmartPointer<IData> getId(const std::tstring& name);

  inline void set_reset(bool reset) { reset_ = reset; }
  inline bool reset() const { return reset_; }

 private:
	 bool reset_;
};

#define ADD_VAR(v) VARS::GetInstance().datas.push_back(v)

class VARS : public Singleton<VARS> {
public:
	// Attributes
	std::vector<SmartPointer<IData>> datas;

	// Constructors
	VARS() {}
	~VARS() {}
};

template<typename _T> SmartPointer<IData> addData(const _T& t) {
	SmartPointer<IData> tmp = newData(t);
	ADD_VAR(tmp);
	return tmp;
}

SmartPointer<IData> addGlobalInst(IData* d);
SmartPointer<IData> addDataId(const std::string& s);
SmartPointer<IData> addOperation(IData* d1, std::string op);
SmartPointer<IData> addOperation(IData* d1, IData* d2, std::string op);
SmartPointer<IData> addVector(IData* d);
SmartPointer<IData> addVector(IData *d1, IData *d2);
SmartPointer<IData> addReturn(IData* d1);
SmartPointer<IData> addIf(IData* d1, IData* d2, IData* d3);
SmartPointer<IData> addWhile(IData* d1, IData* d2);
SmartPointer<IData> addFor(IData* d1, IData* d2, IData* d3, IData* d4);
SmartPointer<IData> addCallFunction(std::string name, IData* d);
SmartPointer<IData> addFunction(std::string name, IData* d1, IData *d2);

END_TEG_NAMESPACE();

#endif  // SCENE_FILE_H__
