text: #include "p2Defs.h"
  #include "p2Log.h"
  
  #include "j1Window.h"
  #include "j1Input.h"
  #include "j1Render.h"
  #include "j1Textures.h"
  #include "j1Audio.h"
  #include "j1Scene.h"
  #include "j1App.h"
  
  // Constructor
  j1App::j1App(int argc, char* args[]) : argc(argc), args(args)
  {
  	frames = 0;
  
  	input = new j1Input();
  	win = new j1Window();
  	render = new j1Render();
  	tex = new j1Textures();
  	audio = new j1Audio();
  	scene = new j1Scene();
  
  	// Ordered for awake / Start / Update
  	// Reverse order of CleanUp
  	AddModule(input);
  	AddModule(win);
  	AddModule(tex);
  	AddModule(audio);
  	AddModule(scene);
  
  	// render last to swap buffer
  	AddModule(render);
  }
  
  // Destructor
  j1App::~j1App()
  {
  	// release modules
  	p2List_item<j1Module*>* item = modules.end;
  
  	while(item != NULL)
  	{
  		RELEASE(item->data);
  		item = item->prev;
  	}
  
  	modules.clear();
  }
  
  void j1App::AddModule(j1Module* module)
  {
  	module->Init();
  	modules.add(module);
  }
  
  // Called before render is available
  bool j1App::Awake()
  {
  	// TODO 3: Load config.xml file using load_file() method from the xml_document class.
  	// If everything goes well, load the top tag inside the xml_node property
  	// created in the last TODO
  	pugi::xml_document config_file;
  	pugi::xml_node node;
  
  	config_file.load_file("Config.xml");
  	node = config_file.child("config");
  
  	bool ret = true;
  
  	p2List_item<j1Module*>* item;
  	item = modules.start;
  
  	while(item != NULL && ret == true)
  	{
  		// TODO 6: Add a new argument to the Awake method to receive a pointer to an xml node.
  		// If the section with the module name exists in config.xml, fill the pointer with the valid xml_node
  		// that can be used to read all variables for that module.
  		// Send nullptr if the node does not exist in config.xml
  
  		ret = item->data->Awake();
  		item = item->next; 
  	}
  	 
  	// TODO 4: Read the title from the config file
  	// and set the window title using win->SetTitle()
  	title = node.child("app").child("title").child_value();
  	
  
  	win->SetTitle(title);
  
  	return ret;
  }
  
  // Called before the first frame
  bool j1App::Start()
  {
  	bool ret = true;
  	p2List_item<j1Module*>* item;
  	item = modules.start;
  
  	while(item != NULL && ret == true)
  	{
  		ret = item->data->Start();
  		item = item->next;
  	}
  
  	return ret;
  }
  
  // Called each loop iteration
  bool j1App::Update()
  {
  	bool ret = true;
  	PrepareUpdate();
  
  	if(input->GetWindowEvent(WE_QUIT) == true)
  		ret = false;
  
  	if(ret == true)
  		ret = PreUpdate();
  
  	if(ret == true)
  		ret = DoUpdate();
  
  	if(ret == true)
  		ret = PostUpdate();
  
  	FinishUpdate();
  	return ret;
  }
  
  // ---------------------------------------------
  void j1App::PrepareUpdate()
  {
  }
  
  // ---------------------------------------------
  void j1App::FinishUpdate()
  {
  }
  
  // Call modules before each loop iteration
  bool j1App::PreUpdate()
  {
  	bool ret = true;
  	p2List_item<j1Module*>* item;
  	item = modules.start;
  	j1Module* pModule = NULL;
  
  	for(item = modules.start; item != NULL && ret == true; item = item->next)
  	{
  		pModule = item->data;
  
  		if(pModule->active == false) {
  			continue;
  		}
  
  		ret = item->data->PreUpdate();
  	}
  
  	return ret;
  }
  
  // Call modules on each loop iteration
  bool j1App::DoUpdate()
  {
  	bool ret = true;
  	p2List_item<j1Module*>* item;
  	item = modules.start;
  	j1Module* pModule = NULL;
  
  	for(item = modules.start; item != NULL && ret == true; item = item->next)
  	{
  		pModule = item->data;
  
  		if(pModule->active == false) {
  			continue;
  		}
  
  		ret = item->data->Update(dt);
  	}
  
  	return ret;
  }
  
  // Call modules after each loop iteration
  bool j1App::PostUpdate()
  {
  	bool ret = true;
  	p2List_item<j1Module*>* item;
  	j1Module* pModule = NULL;
  
  	for(item = modules.start; item != NULL && ret == true; item = item->next)
  	{
  		pModule = item->data;
  
  		if(pModule->active == false) {
  			continue;
  		}
  
  		ret = item->data->PostUpdate();
  	}
  
  	return ret;
  }
  
  // Called before quitting
  bool j1App::CleanUp()
  {
  	bool ret = true;
  	p2List_item<j1Module*>* item;
  	item = modules.end;
  
  	while(item != NULL && ret == true)
  	{
  		ret = item->data->CleanUp();
  		item = item->prev;
  	}
  
  	return ret;
  }
  
  // ---------------------------------------
  int j1App::GetArgc() const
  {
  	return argc;
  }
  
  // ---------------------------------------
  const char* j1App::GetArgv(int index) const
  {
  	if(index < argc)
  		return args[index];
  	else
  		return NULL;
  }
  