/*
*  
*  $Id: comandoexportacion.cpp $
*  Ginkgo CADx Project
*
*  Copyright 2008-14 MetaEmotion S.L. All rights reserved.
*  http://ginkgo-cadx.com
*
*  This file is licensed under LGPL v3 license.
*  See License.txt for details
*
*/
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4996)
#endif

#include <sstream>

#include <wx/filename.h>
#include <wx/file.h>
#include <wx/dir.h>
#include <main/controllers/configurationcontroller.h>

#include <api/globals.h>
#include <api/ientorno.h>
#include <api/dicom/idicommanager.h>
#include <api/internationalization/internationalization.h>

#include <api/controllers/ipacscontroller.h>

#include <main/entorno.h>
#include <main/controllers/controladoreventos.h>
#include <main/controllers/historycontroller.h>
#include <main/controllers/commandcontroller.h>
#include <main/gui/history3/historypanel3.h>

#include <eventos/mensajes.h>

#include "comandoexportacion.h"

#include <itkExceptionObject.h>
#include <itkImage.h>
#include <itkOrientedImage.h>
#include <itkRGBPixel.h>
#include <itkGDCMImageIO.h>
#include <itkJPEGImageIO.h>
#include <itkPNGImageIO.h>
#include <itkVectorResampleImageFilter.h>
#include <itkLinearInterpolateImageFunction.h>
#include <itkImageFileWriter.h>
#include <api/istudycontext.h>

#include <api/dicom/dcmdictionary.h>
#include <commands/comandoincluirhistorial.h>



namespace GADAPI {

	ComandoExportacionParams::ComandoExportacionParams(GNC::GCS::Ptr<GNC::GUI::TipoWizardExportacion>& pDatosPersistentes)
	{
		m_pDatosPersistentes = pDatosPersistentes;
		m_hasError = false;
		if (pDatosPersistentes->m_target != GNC::GUI::TipoWizardExportacion::EXTERNAL_FOLDER) {
			m_tempDir = GNC::Entorno::Instance()->CreateGinkgoTempDir();
		}
	}

	ComandoExportacionParams::~ComandoExportacionParams()
	{
	}

	ComandoExportacion::ComandoExportacion(ComandoExportacionParams* pParams): GNC::GCS::IComando(pParams,"Exportacion")
	{
		m_pExportacionParams = pParams;
	}

	void ComandoExportacion::Execute()
	{
		if (!NotificarProgreso(0.0, _Std("Exporting files...")) )
			return;
		
		ExportarDICOM();		

		if (m_pExportacionParams->m_pDatosPersistentes->m_target == GNC::GUI::TipoWizardExportacion::OVERWRITE) {
			GNC::GCS::HistoryController::FileModelList fileModelList;
			for (std::list<long>::iterator it = m_pExportacionParams->m_pDatosPersistentes->ListOfSeriesPks.begin(); it != m_pExportacionParams->m_pDatosPersistentes->ListOfSeriesPks.end(); ++it)
			{
				GNC::GCS::HistoryController::Instance()->GetSeriesSortedFileModels((*it), fileModelList);
			}
			GNC::GCS::HistoryController::Instance()->UpdateFiles(fileModelList);
		}
	}

	void ComandoExportacion::Update()
	{
		switch (m_pExportacionParams->m_pDatosPersistentes->m_target) {
			case GNC::GUI::TipoWizardExportacion::EXTERNAL_FOLDER:
			{
				if (m_pExportacionParams->m_hasError)
				{
					GNC::GCS::ControladorEventos::Instance()->ProcesarEvento(new GNC::GCS::Events::EventoMensajes(NULL,m_pExportacionParams->m_Error, GNC::GCS::Events::EventoMensajes::StatusMessage,true, GNC::GCS::Events::EventoMensajes::Error));
				} else {
					GNC::GCS::ControladorEventos::Instance()->ProcesarEvento(new GNC::GCS::Events::EventoMensajes(NULL, _Std("Export has been finished successfully"), GNC::GCS::Events::EventoMensajes::StatusMessage,true, GNC::GCS::Events::EventoMensajes::Informacion));
				}
			}
			break;
			case GNC::GUI::TipoWizardExportacion::OVERWRITE:
			{
				GNC::GUI::HistoryPanel3::Instance()->ReloadHistory();
			}
			break;
			case GNC::GUI::TipoWizardExportacion::NEW_STUDY:
			{
				//add to history...
				GADAPI::ComandoIncluirHistorial::ComandoIncluirHistorialParams* pParams = new GADAPI::ComandoIncluirHistorial::ComandoIncluirHistorialParams(m_pExportacionParams->m_outputPaths, false, GNC::GCS::HistoryController::TAA_MOVE);
				GADAPI::ComandoIncluirHistorial::ComandoIncluirHistorial* pCmd = new GADAPI::ComandoIncluirHistorial::ComandoIncluirHistorial(pParams);
				GNC::GCS::ICommandController::Instance()->ProcessAsync("Including...", pCmd, NULL);
			} 
			break;
		}
	}

	//endregion

	void ComandoExportacion::ExportarDICOM()
	{
		GNC::GCS::Ptr<GNC::GUI::TipoWizardExportacion> pDatosPersistentes = m_pExportacionParams->m_pDatosPersistentes;
		bool correcto = true;

		std::list<std::string> resultado;
		std::list<std::string> listaPaths;

		if (!pDatosPersistentes->ListOfSeriesPks.empty()) {
			for (std::list<long>::iterator itUIDs = pDatosPersistentes->ListOfSeriesPks.begin(); itUIDs != pDatosPersistentes->ListOfSeriesPks.end(); ++itUIDs)
			{
				GNC::GCS::HistoryController::StringList pathsSerie = GNC::GCS::HistoryController::Instance()->GetSeriesSortedPaths((*itUIDs));
				listaPaths.insert(listaPaths.begin(), pathsSerie.begin(), pathsSerie.end());
			}
		} else if (!pDatosPersistentes->ListOfDICOMPaths.empty()) {
			listaPaths.insert(listaPaths.end(), pDatosPersistentes->ListOfDICOMPaths.begin(), pDatosPersistentes->ListOfDICOMPaths.end());
		}

		GIL::DICOM::IDICOMManager*	pDICOMManager;

		
		wxString destino;

		//update ids to get new study...
		std::map<std::string, std::string> mapOfUIDs;
		std::string stringTmp;
		GIL::DICOM::DicomDataset baseUIDs;
		//

		int contador = 1;
		for(std::list<std::string>::iterator it = listaPaths.begin(); it!= listaPaths.end(); ++it,++contador) {
			wxString cadena = wxString::Format(_("Exporting file %d of %d"), (int)contador, (int)listaPaths.size());
			if (!NotificarProgreso((float)contador/listaPaths.size(), std::string(cadena.ToUTF8())))
				return;

			GIL::DICOM::DicomDataset base;

			pDICOMManager = GNC::GCS::IEntorno::Instance()->GetPACSController()->CrearInstanciaDeDICOMManager();
			pDICOMManager->CargarFichero((*it), base);
			
			pDICOMManager->ActualizarJerarquia(pDatosPersistentes->m_base);

			if (pDatosPersistentes->m_target == GNC::GUI::TipoWizardExportacion::NEW_STUDY) {
				baseUIDs.tags.clear();
				//study instance uid
				base.getTag(GKDCM_StudyInstanceUID, stringTmp);
				if (mapOfUIDs.find(stringTmp) == mapOfUIDs.end()) {
					mapOfUIDs[stringTmp] = pDICOMManager->GetNewUID();
				}
				baseUIDs.tags[GKDCM_StudyInstanceUID] = mapOfUIDs[stringTmp];
				//series instance uid
				base.getTag(GKDCM_SeriesInstanceUID, stringTmp);
				if (mapOfUIDs.find(stringTmp) == mapOfUIDs.end()) {
					mapOfUIDs[stringTmp] = pDICOMManager->GetNewUID();
				}
				baseUIDs.tags[GKDCM_SeriesInstanceUID] = mapOfUIDs[stringTmp];
				//sop instance
				base.getTag(GKDCM_SOPInstanceUID, stringTmp);
				if (mapOfUIDs.find(stringTmp) == mapOfUIDs.end()) {
					mapOfUIDs[stringTmp] = pDICOMManager->GetNewUID();
				}
				baseUIDs.tags[GKDCM_SOPInstanceUID] = mapOfUIDs[stringTmp];
				//update uids
				pDICOMManager->ActualizarJerarquia(baseUIDs);
			}

			//anonimizar tags Ginkgo
			if(!pDatosPersistentes->m_incluirTagsGinkgo){
				pDICOMManager->AnonimizarTagsPrivados();
			}


			if (pDatosPersistentes->m_target == GNC::GUI::TipoWizardExportacion::OVERWRITE) {
				destino = FROMPATH((*it));
			} else {
				destino = GetFichero(wxT("dcm"));
			}

			std::string destinoStd(TOPATH(destino));
			correcto = correcto && pDICOMManager->AlmacenarFichero(destinoStd);
			resultado.push_back(destinoStd);
			m_pExportacionParams->m_outputPaths.push_back(destinoStd);
			GNC::Entorno::Instance()->GetPACSController()->LiberarInstanciaDeDICOMManager(pDICOMManager);
		}

		if(!correcto) {
			m_pExportacionParams->m_Error = _Std("Error storing file, check the permissions over the directory.");
			m_pExportacionParams->m_hasError = true;
		}
	}


	wxString ComandoExportacion::GetFichero(const wxString& extension) {
		wxString dir;
		if (m_pExportacionParams->m_pDatosPersistentes->m_target == GNC::GUI::TipoWizardExportacion::EXTERNAL_FOLDER) {
			dir = FROMPATH(m_pExportacionParams->m_pDatosPersistentes->m_pathDestino);
		} else {
			dir = FROMPATH(m_pExportacionParams->m_tempDir);
		}

		//if pathDestino is a file.. then return
		if (!wxDirExists(dir))
		{
			return dir;
		} else {
			wxString destino(wxEmptyString);
			std::string nombre (wxDateTime::Now().Format(_("image_%m-%d-%Y_")).ToUTF8());
			std::string stdDir(TOPATH(dir));
			std::string stdExtension(TOPATH(extension));
			int indice=0;
			//yy-mm-dd_imagen_indice
			do {
				std::ostringstream ostr;
				ostr << stdDir << (char)wxFileName::GetPathSeparator() << nombre << indice++ << "." << stdExtension;
				destino = FROMPATH(ostr.str());
			} while(wxFile::Exists(destino));
			return destino;
		}
	}
};

#ifdef _MSC_VER
#pragma warning(pop)
#endif

