/*
*
*  $Id: comandopacs.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
*
*/
//#define _GINKGO_TRACE

/*
#include <wx/filename.h>
#include <wx/dir.h>
#include <wx/progdlg.h>
#include <wx/log.h>
#include <wx/msgdlg.h>
*/
#include <api/api.h>
#include <api/globals.h>

#include <api/controllers/ieventscontroller.h>

#include <eventos/mensajes.h>

#include <main/entorno.h>
#include <main/controllers/controladoreventos.h>
#include <main/controllers/controladorcomandos.h>
#include <main/controllers/controladorpermisos.h>
#include <main/controllers/pacscontroller.h>
#include <main/controllers/controladorlog.h>
#include <main/controllers/dcmtk/dicomservers.h>
#include <main/controllers/controladorvistas.h>

#include "comandopacs.h"
#include "comandoincluirhistorial.h"

#include <sstream>
#include <map>


#define IDC_PACS_BUSCAR                  61
#define IDC_PACS_DESCARGAR               62
#define IDC_PACS_ABORTAR_TODOS           63
#define IDC_PACS_SUBIR			         64

#define ID_REFRESCO_PROGRESO 1

#define PARALLEL

// Singleton de persistencia
namespace GADAPI
{

	ComandoPACS::ComandoPACS(ComandoPACSParams* pParams) : IComando(pParams)
	{
		GTRACE(">> ComandoPACS::ComandoPACS(): " << this);
		m_pPACSParams = pParams;
		switch (m_pPACSParams->m_TipoAccion) {
			//no es posible hacer dos comandos de estos en paralelo dcmtk no es multithread
			case GADAPI::PACS::TAC_Buscar :
				SetId(IDC_PACS_BUSCAR);
#if !defined(PARALLEL)
				EsperaA(IDC_PACS_BUSCAR);
				EsperaA(IDC_PACS_DESCARGAR);
				EsperaA(IDC_PACS_SUBIR);
#endif
				AbortaSi(IDC_PACS_ABORTAR_TODOS);
				break;
			case GADAPI::PACS::TAC_Descargar :
				SetId(IDC_PACS_DESCARGAR);
				EsperaA(IDC_PACS_DESCARGAR);
#if !defined(PARALLEL)
				EsperaA(IDC_PACS_BUSCAR);
				EsperaA(IDC_PACS_DESCARGAR);
				EsperaA(IDC_PACS_SUBIR);
#endif
				AbortaSi(IDC_PACS_ABORTAR_TODOS);
				break;
		}

		GTRACE("<< ComandoPACS::ComandoPACS(): " << this);
	}

	void ComandoPACS::Execute()
	{
		if(m_pPACSParams->m_TipoAccion == GADAPI::PACS::TAC_Buscar)
		{
			Search();
		} else if(m_pPACSParams->m_TipoAccion == GADAPI::PACS::TAC_Descargar){
			Download();
		}
	}

	void ComandoPACS::Update()
	{
		GTRACE("UPDATE " << this);

		if (EstaAbortado()) {
		    return;
		}
		
		if(m_pPACSParams->m_TipoAccion == GADAPI::PACS::TAC_Buscar) {
			GTRACE("buscar... " << this);
			if(m_pPACSParams->m_pNotificador!=NULL){
				GTRACE("cargamos listado de:... "<< m_pPACSParams->m_pModelo->ListaPacientes().size()<< " pacientes " << this);
				if(m_pPACSParams->m_error!="" && m_pPACSParams->m_pModelo->ListaPacientes().size() == 0){
					if (m_pPACSParams->m_informar) {
						GNC::GCS::ControladorEventos::Instance()->ProcesarEvento(new GNC::GCS::Events::EventoMensajes(NULL, _Std("Failed to perform search: ") + "\n" + m_pPACSParams->m_error, GNC::GCS::Events::EventoMensajes::PopUpMessage,false, GNC::GCS::Events::EventoMensajes::Error));
					}
					m_pPACSParams->m_pNotificador->PACSCargarListado(m_pPACSParams->m_pModelo);
				} else {
					m_pPACSParams->m_pNotificador->PACSCargarListado(m_pPACSParams->m_pModelo);
				}
			} else {
				GTRACE("no hay notificador... " << this);
			}
		}
		else if(m_pPACSParams->m_TipoAccion == GADAPI::PACS::TAC_Descargar) {
			GTRACE("descargar... " << this);

			if(m_pPACSParams->m_error!=""){
				LOG_ERROR("C-MOVE/C-GET", "Error Downloading study: " << m_pPACSParams->m_error);
				if (m_pPACSParams->m_informar) {
					GNC::GCS::ControladorEventos::Instance()->ProcesarEvento(new GNC::GCS::Events::EventoMensajes(NULL, _Std("Error downloading study: ") + "\n" + m_pPACSParams->m_error, GNC::GCS::Events::EventoMensajes::PopUpMessage,false, GNC::GCS::Events::EventoMensajes::Error));
				}
				return ;
			}
			else {

				std::list<std::string> rutas;
				std::string rutaImagen;
				if (m_pPACSParams->m_pModelo.IsValid()) {
					//listamos las imagenes que nos hemos bajado
					for (IModeloDicom::ListaPacientesType::const_iterator it = m_pPACSParams->m_pModelo->ListaPacientes().begin(); it != m_pPACSParams->m_pModelo->ListaPacientes().end(); ++it) {
						const IModeloPaciente& p = *it;
						for (IModeloPaciente::ListaEstudiosType::const_iterator it2 = p.ListaEstudios().begin(); it2 != p.ListaEstudios().end(); ++it2) {
							const IModeloEstudio& e = *it2;
							for (IModeloEstudio::ListaSeriesType::const_iterator it3 = e.ListaSeries().begin(); it3 != e.ListaSeries().end(); ++it3) {
								const IModeloSerie& s = *it3;
								for (IModeloSerie::ListaImagenesType::const_iterator it4 = s.ListaImagenes().begin(); it4 != s.ListaImagenes().end(); ++it4) {
									const IModeloImagen& im = *it4;
									if(GIL::DICOM::PACSController::Instance()->GetRutaImagenTemp(p.GetUID(),e.GetUID(),s.GetUID(),im.GetUID(), rutaImagen)){
										rutas.push_back(rutaImagen);
									}
								}
							}
						}
					}
				}

				//si ha descargado algo...
				if(rutas.empty()){
					LOG_WARN("C-MOVE/C-GET", _Std("No results obtained. Maybe you have a wrong PACS server configuration"));
					if (m_pPACSParams->m_informar) {
						GNC::GCS::ControladorEventos::Instance()->ProcesarEvento(new GNC::GCS::Events::EventoMensajes(NULL, _Std("No results obtained in PACS retrieve.\nMaybe study doesn't exist or you have a wrong PACS server configuration."), GNC::GCS::Events::EventoMensajes::PopUpMessage,false, GNC::GCS::Events::EventoMensajes::Error));
					}
					return;
				}

				//se lanza un evento para incluir las imagenes en el historial
				GADAPI::ComandoIncluirHistorial::ComandoIncluirHistorialParams* pParams = new GADAPI::ComandoIncluirHistorial::ComandoIncluirHistorialParams(rutas);
				pParams->m_informar = m_pPACSParams->m_informar;
				GADAPI::ComandoIncluirHistorial::ComandoIncluirHistorial * pCmd = new GADAPI::ComandoIncluirHistorial::ComandoIncluirHistorial(pParams);
				GNC::GCS::IControladorComandos::Instance()->ProcessAsync(_Std("Including files..."),pCmd,NULL);
			}
		}
	}

	void ComandoPACS::Search()
	{
		GTRACE("Consultando pacs... " << this);
		std::string tarea=_Std("PACS Consulting ...");
		if (!NotificarProgreso(0.0f,tarea)) {
		    return;
		}
		GIL::DICOM::IPACSController* pCI = NULL;
		try {

			pCI = GNC::Entorno::Instance()->GetPACSController();

			pCI->GetConnection(this);

			if (pCI == NULL) {
				throw GIL::DICOM::PACSException(_Std("Error accessing the controller subsystem integration: (GIL:: DICOM)."));
			}
			if (!m_pPACSParams->m_pModelo.IsValid()) {
				throw GIL::DICOM::PACSException(_Std("Subsystem integration error: uninitialized result data container."));
			}

			std::string mensaje = _Std("Starting Search ...");
			if ( !NotificarProgreso(0.0f, mensaje) ) {
			    return;
			}

			switch (m_pPACSParams->m_Ambito) {
				case ComandoPACSParams::TA_Paciente:
					//std::cout << "patient" << std::endl;
					break;
				case ComandoPACSParams::TA_Estudio:
					pCI->BuscarEstudio(
						this,
						m_pPACSParams->m_serverSeleccionado, // Server ID
						m_pPACSParams->m_pacienteID, // ID Paciente
						m_pPACSParams->m_pacienteNombre, // Nombre Paciente
						m_pPACSParams->m_studyUID,
						m_pPACSParams->m_accessionNumber, // Accesion Number
						m_pPACSParams->m_estudioModalidad, // Modalidad
						m_pPACSParams->m_estudioFechaDesde, // Fecha Desde
						m_pPACSParams->m_estudioFechaHasta, // Fecha Hasta
						m_pPACSParams->m_studyTimeFrom,  // time from
						m_pPACSParams->m_studyTimeTo,		// time To
						"", // Description
						"", // Nombre de la estación
						m_pPACSParams->m_pModelo,
						this);
					break;
				case ComandoPACSParams::TA_Serie:
					{
						const IModeloEstudio* estudio = NULL;
						m_pPACSParams->m_pModelo->BuscarEstudio(m_pPACSParams->m_studyUID,&estudio);
						if (estudio == NULL) {
							pCI->BuscarEstudio(
								this,
								m_pPACSParams->m_serverSeleccionado, // Server ID
								"", // ID Paciente
								"", // Nombre Paciente
								m_pPACSParams->m_studyUID,
								"", // Accesion Number
								"", // Modalidad
								"", // Fecha Desde
								"", // Fecha Hasta
								"", // time from
								"", // time to
								"", // Descripcion del Estudio
								"", // Nombre de la estación
								m_pPACSParams->m_pModelo,this
							);
						}
						GNC::Entorno::Instance()->GetPACSController()->BuscarSeries(
							this,
							m_pPACSParams->m_serverSeleccionado, // Server ID
							m_pPACSParams->m_studyUID,
							std::string(),
							m_pPACSParams->m_pModelo,this
						);
					}
					break;
				default:
					break;
			}
			GTRACE(m_pPACSParams->m_pModelo);
		} catch (GinkgoNoServerFoundException& ) {
			GTRACE("excepción no server found... " << this);
			m_pPACSParams->m_error= _Std("Server ID not found. ID = ") + m_pPACSParams->m_serverSeleccionado;
			m_pPACSParams->m_pModelo->Error = true;
		} catch (GIL::DICOM::PACSException& ex) {
			GTRACE("excepción pacsexception: " << ex << "            " << this);
			m_pPACSParams->m_error= _Std("Query error with PACS Id ") + m_pPACSParams->m_serverSeleccionado + "\n" + (const std::string)ex;
			m_pPACSParams->m_pModelo->Error = true;
		} catch (GIL::DICOM::ModelException& ex) {
			GTRACE("excepción pacsexception: " << ex << "            " << this);
			m_pPACSParams->m_error= _Std("Query error with PACS Id ") + m_pPACSParams->m_serverSeleccionado + "\n" + (const std::string)ex;
			m_pPACSParams->m_pModelo->Error = true;
		} catch (std::exception& ex) {
			GTRACE("excepción stdexception: "<< ex.what()<<"            " << this);
			m_pPACSParams->m_error= _Std("Query error with PACS Id ") + m_pPACSParams->m_serverSeleccionado + "\n" + ex.what();
			m_pPACSParams->m_pModelo->Error = true;
		} catch ( ... ) {
			m_pPACSParams->m_error= _Std("Query error with PACS Id ") + m_pPACSParams->m_serverSeleccionado + "\n" + _Std("Internal error");
			m_pPACSParams->m_pModelo->Error = true;
		}
		if (pCI) {
			pCI->ReleaseConnection(this);
		}
		if (!NotificarProgreso(1.0f,tarea)) {
		    return;
		}
	}

	void ComandoPACS::Download()
	{
		GTRACE("descargando...... " << this);
		std::string tarea= _Std("Downloading files ...");
		if (!NotificarProgreso(0.0f,tarea)) {
		    return;
		}

		GIL::DICOM::IPACSController* pCI = NULL;

		try {
			pCI = GNC::Entorno::Instance()->GetPACSController();
			pCI->GetConnection(this);
			pCI->QueryRetrieve(this, m_pPACSParams->m_serverSeleccionado, m_pPACSParams->m_pModelo, m_pPACSParams->m_base, this);
		}
		catch (GinkgoNoServerFoundException& ) {
			GTRACE("excepcion no server found... " << this);
			m_pPACSParams->m_error= _Std("Server ID not found. ID = ") + m_pPACSParams->m_serverSeleccionado;
			m_pPACSParams->m_pModelo->Error = true;
		}
		catch (GIL::DICOM::PACSException& ex) {
			GTRACE("excepcion en pacs: " << ex << "            " << this);
			m_pPACSParams->m_error =  (const std::string)ex;
			m_pPACSParams->m_pModelo->Error = true;
		}
		catch (std::exception& ex) {
			GTRACE("excepcion en pacs: " << ex.what() << "            " << this);
			m_pPACSParams->m_error= ex.what();
			m_pPACSParams->m_pModelo->Error = true;
		}
		catch (...)
		{
			GTRACE("excepcion en pacs: Error interno            " << this);
			m_pPACSParams->m_error= _Std("Internal Error");
			m_pPACSParams->m_pModelo->Error = true;
		}
		if (pCI) {
			pCI->ReleaseConnection(this);
		}
		GTRACE(m_pPACSParams->m_pModelo);
		NotificarProgreso(1.0f,tarea);
	}

	bool ComandoPACS::NotificarProgreso(float progresoNormalizado,const std::string &texto) {
		if (EstaAbortado())
		{
			return false;
		}
		return IComando::NotificarProgreso(progresoNormalizado, texto);
	}

	void ComandoPACS::LiberarRecursos()
	{
	}

}
