/*
 *  
 *  $Id: controladorcomandos.h $
 *  Ginkgo CADx Project
 *
 *  Copyright 2008-12 MetaEmotion S.L. All rights reserved.
 *  http://ginkgo-cadx.com
 *
 *  This file is licensed under LGPL v3 license.
 *  See License.txt for details
 *
 *
 */
#pragma once

#include <list>
#include <map>

#include <api/internal.h>
#include <api/controllers/icommandscontroller.h>
#include <api/icommand.h>
#include <api/controllers/iprogresscontroller.h>
#include <api/ilock.h>
#include <api/iwaitqueue.h>

// TODO: Refactor this
#include <wx/thread.h>

//----------------------------------------------------------------------------------------------------
//region forward declarations
namespace GNC {
	class ControladorComandos;
}

class wxWindow;
//endregion

namespace GNC {

	//----------------------------------------------------------------------------------------------------
	//----------------------------------------------------------------------------------------------------
	class EXTAPI LanzadorComandos : public wxThread, public GNC::GCS::WaitQueueTask, public GNC::INotificadorProgreso {
	public:
		//id Ginkgo
		unsigned long m_idThreadGinkgo;

		GNC::GCS::IComando* GetComando(){
			return m_pComando;
		}

		virtual void* Entry();

		virtual void OnExit();

		bool RecalcularDependencias();

		void IniciarUnlocker();

	protected:

		virtual void DoTerminar();

	private:

		LanzadorComandos(GNC::GCS::IComando* pComando);

		~LanzadorComandos();

		virtual bool NotificarProgreso(float progresoNormalizado, const std::string& texto);


	private:

		GNC::GCS::IComando*    m_pComando;

		GNC::GCS::WaitQueue m_Dependencias;

		// Esta variable controla si el hilo debe enviar el mensaje de finalizacion o no
		bool                m_Abortar;

		#if defined(_WINDOWS)
		//HANDLE              m_hEventoCancelacion;
		#else

		#endif

		friend class GNC::ControladorComandos;
	};



	//----------------------------------------------------------------------------------------------------
	//----------------------------------------------------------------------------------------------------
	class EXTAPI ControladorComandos : public GNC::GCS::IControladorComandos, public GNC::GCS::ILockable {
	public:

		typedef std::map<long, LanzadorComandos*> MapaComandos;
		typedef std::map<long, GNC::GCS::IComando*> MapaComandosTerminados;
		typedef std::list<long> ListaHilos;
		typedef std::map<void*, ListaHilos > MapaOwners;
		typedef std::list<std::string> ListaNombreComandos;

		static ControladorComandos *Instance();
		static void FreeInstance();

		~ControladorComandos();
		virtual void Process(GNC::GCS::IComando* cmd);
		virtual void ProcessSync(GNC::GCS::IComando* cmd, bool autodelete);
		virtual void ProcessAsync(std::string str, GNC::GCS::IComando* cmd, void* owner);
		virtual void AbortarComando(GNC::GCS::IComando* pComando, bool sincrono = true);
		virtual void AbortarComando(long threadId, bool sincrono = true);
		virtual void AbortarComandosDeOwner(void* owner);
		virtual void AbortarComandosDeOwnerAsincrono(void* owner);
		virtual void WaitToOwnerCommands(void* owner);

		virtual unsigned int GetNumActiveCommands();

		void RegistrarProgreso(GNC::IControladorProgreso* pProgreso)
		{
			m_pProgreso = pProgreso;
		}

		GNC::IControladorProgreso* GetProgresoRegistrado()
		{
			return m_pProgreso;
		}

		void OnComandoLanzado(long threadId);
		void OnComandoProgreso(long threadId);
		void OnComandoFinalizado(long threadId, bool lock=true);

		ListaNombreComandos GetComandosActivos();

	protected:

		ControladorComandos();

		static ControladorComandos* m_psInstancia;
		bool m_Destroying;

		MapaComandos m_ComandosLanzados;
		MapaComandosTerminados m_ComandosTerminados;
		MapaOwners m_MapaOwners;
		bool m_EsperarComandos;

		GNC::IControladorProgreso* m_pProgreso;

		unsigned long m_idThreads;

		friend class GNC::LanzadorComandos;
	};

}
