/*
 *
 *  $Id: icommand.cpp $
 *  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
 *
 */
#include <string>
#include <list>
#include <api/iexception.h>
#include <api/controllers/iprogresscontroller.h>
#include "iproxynotificadorprogreso.h"
#include "icommand.h"

//---------------------------------------------------------------------------------------
//region Forward declarations
namespace GNC {
	class LanzadorComandos;
	class INotificadorProgreso;
	class ControladorComandos;

	namespace GCS {
		class IComando;

	}
}
//endregion

namespace GNC {
	namespace GCS {

		//---------------------------------------------------------------------------------------
		IComandoParams::IComandoParams() {}
		IComandoParams::~IComandoParams() {}

		//---------------------------------------------------------------------------------------
		IComandoResult::IComandoResult() { }
		IComandoResult::~IComandoResult() { }

		//---------------------------------------------------------------------------------------
		IComando::IComando(IComandoParams* pParams, const std::string& name , void* pOwner) {
				m_pParams = pParams;
				m_pResult = NULL;
				m_pNotificadorProgreso = NULL;
				m_Abortado = false;
				m_Nombre = name;
				m_pOwner = pOwner;
				if (m_Nombre.size() == 0)
				{
						m_Nombre = "Comando";
				}
				NotificarProgreso(0.0f, m_Nombre);
			}

		IComando::~IComando() {
				if (m_pResult != 0) {
						delete m_pResult;
						m_pResult = 0;
				}
				if (m_pParams != 0) {
						delete m_pParams;
						m_pParams = 0;
				}
				OnDestroy();
			}

			//endregion

			//---------------------------------------------------------------------------------------
			//region Interfaz especifica
		

			/** Notifica el progreso. Si devuelve true, el ejecutor dejara de procesarse **/
			bool IComando::NotificarProgreso(float progresoNormalizado, const std::string& texto)
			{
				if (m_Abortado) {
						return false;
				}

				if (m_pNotificadorProgreso != NULL) {
						return m_pNotificadorProgreso->NotificarProgreso(progresoNormalizado, texto);
				}

				return true;
			}

			/** Callback que puede ser sobrecargado por el sujeto para incluir acciones especificas cuando se aborta el comando **/
			void IComando::OnAbort() {}

			/** Callback que puede ser sobrecargado por el sujeto para incluir acciones especificas cuando se destruye el comando **/
			void IComando::OnDestroy() {}

			//endregion

			//---------------------------------------------------------------------------------------
			//region Getters y helpers
			int IComando::GetId() const {
				return m_Id;
			}

			void IComando::SetId(int id) {
				m_Id = id;
			}

			void IComando::SetOwner(void* pOwner)
			{
				m_pOwner = pOwner;
			}

			void* IComando::GetOwner() const
			{
				return m_pOwner;
			}

			const std::string& IComando::GetName() const
			{
				return m_Nombre;
			}

			IComandoParams* IComando::GetParams()
			{
				return m_pParams;
			}

			void IComando::Abort() {
				m_Abortado = true;
				OnAbort();
			}

			bool IComando::EstaAbortado() const {
				return m_Abortado;
			}

			//endregion

			//---------------------------------------------------------------------------------------
			//region Notificacion
			// Este metodo debe ser invocado solo por el lanzador de comandos.
			void IComando::SetNotificadorProgreso(GNC::INotificadorProgreso* pNotificador)
			{
				m_pNotificadorProgreso = pNotificador;
			}
			//endregion

			//---------------------------------------------------------------------------------------
			//region "Gestion de Dependencias"


			void IComando::EsperaA(int idDep)
			{
				m_Dependencias.push_back(idDep);
			}

			void IComando::AbortaSi(int idConflicto)
			{
				m_Conflictos.push_back(idConflicto);
			}

			void IComando::CancelaA(int idReemplazo) {
				m_Reemplazos.push_back(idReemplazo);
			}

			///////////////IPersistentCommand////////////////
			IPersistentCommand::IPersistentCommand(const std::list<long> seriesId, const std::string description):
				IComando(NULL),
				m_seriesId(seriesId),
				m_idBBDD(-1),
				m_status(IPersistentCommand::Pending),
				m_description(description)
			{
				
			}

			IPersistentCommand::IPersistentCommand(long idBBDD, const std::list<long> seriesId, const std::string description):
				IComando(NULL),
				m_seriesId(seriesId),
				m_idBBDD(idBBDD),
				m_status(IPersistentCommand::Pending),
				m_description(description)
			{
			}

			IPersistentCommand::~IPersistentCommand()
			{
			}

			std::string IPersistentCommand::getClassUID()
			{
				throw new GNC::GCS::IException("Method has to be overriden");
			}

			long IPersistentCommand::getIdBBDD()
			{
				return m_idBBDD;
			}

			void IPersistentCommand::setIdBBDD(long id)
			{
				m_idBBDD = id;
			}

			const std::list<long>& IPersistentCommand::getSeriesId()
			{
				return m_seriesId;
			}

			const std::string& IPersistentCommand::getErrorDescription()
			{
				return m_errorDescription;
			}

			IPersistentCommand::TStatus IPersistentCommand::getStatus()
			{
				return m_status;
			}

			const std::string& IPersistentCommand::getDescription()
			{
				return m_description;
			}

			void IPersistentCommand::setStatus(IPersistentCommand::TStatus status)
			{
				m_status = status;
			}
	}
}
