/*
*  
*  $Id: dicombrowsercomponent.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 <wx/filename.h>
#include <wx/imaglist.h>
#include <wx/file.h>
#include <wx/dnd.h>
#include <wx/dir.h>
#include <wx/busyinfo.h>
#include <wx/filedlg.h>
#include <wx/menu.h>
#include <wx/dirdlg.h>
#include <main/controllers/configurationcontroller.h>
#include <wx/msgdlg.h>
#include "dicombrowsercomponent.h"



#include <vector>
#include <sstream>

#include <main/entorno.h>
#include <main/controllers/controladorextensiones.h>
#include <main/controllers/controladorcomandos.h>
#include <main/controllers/pacscontroller.h>
#include <commands/comandoincluirhistorial.h>
#include <api/dicom/imodelodicom.h>
#include <resources/ginkgoresourcesmanager.h>

#define ICONO_ESTUDIO 0
#define ICONO_SERIE 1
#define ICONO_HOMBRE 2
#define ICONO_MUJER 3
#define ICONO_OTRO 4
#define ICONO_DIAGNOSTICO 5
#define SIZE_ICONOS 16

#define COLUMNA_DCMDIR_FECHA 2
#define COLUMNA_DCMDIR_MODALIDAD 1
#define COLUMNA_DCMDIR_MEDICO 3
#define COLUMNA_DCMDIR_ACCNUMBER 4
#define COLUMNA_DCMDIR_UID 5

namespace GNC {
	namespace GUI {
		//datos de los nodos...
		class wxPathsNodo: public wxTreeItemData {
		public:
			wxPathsNodo(const std::string& uid, bool isDiagnostic) :
					m_pListaPaths(),
					m_uid(uid),
					m_isDiagnostic(isDiagnostic)
			{
				
			}

			~wxPathsNodo() {
				m_pListaPaths.clear();
			}

			wxPathsNodo(const wxPathsNodo& otro) :
					m_pListaPaths(otro.m_pListaPaths),
					m_uid(otro.m_uid),
					m_isDiagnostic(otro.m_isDiagnostic)
			{
			}

			std::list<std::string> m_pListaPaths;
			std::string m_uid;
			bool m_isDiagnostic;
		};
		//////////////////////BEGIN D&D/////////////////////////
		class wxDicomDirDnD : public wxCustomDataObject
		{
		public:
			wxDicomDirDnD(bool arrancaIzquierda = true)
			{
				m_arrancaIzquierda = arrancaIzquierda;

				m_format.SetId(wxT("DicomDirOpenFormat"));
				SetFormat(m_format);
			}
			bool ArrancaIzquierda()
			{
				return m_arrancaIzquierda;
			}
			// implement base class pure virtuals
			// ----------------------------------
			virtual wxDataFormat GetPreferredFormat(Direction WXUNUSED(dir)) const
			{
				return m_format;
			}

			virtual size_t GetFormatCount(Direction /*dir*/) const
			{
				size_t nFormats = 1;
				return nFormats;
			}

			virtual void GetAllFormats(wxDataFormat *formats, Direction /*dir*/) const
			{
				formats[0] = m_format;
			}
			virtual size_t GetDataSize() const
			{
				return sizeof(m_arrancaIzquierda);
			}
			virtual bool GetDataHere(void *buf) const
			{
				(*((bool*)buf)) = m_arrancaIzquierda;
				return true;
			}
			virtual bool SetData(size_t /*len*/, const void *buf)
			{
				m_arrancaIzquierda = (*(const bool*)buf);
				return true;
			}
			// Must provide overloads to avoid hiding them (and warnings about it)
			virtual size_t GetDataSize(const wxDataFormat&) const
			{
				return GetDataSize();
			}
			virtual bool GetDataHere(const wxDataFormat&, void *buf) const
			{
				return GetDataHere(buf);
			}
			virtual bool SetData(const wxDataFormat&, size_t len, const void *buf)
			{
				return SetData(len, buf);
			}

		private:
			bool m_arrancaIzquierda;
			wxDataFormat m_format;

			DECLARE_NO_COPY_CLASS(wxDicomDirDnD)
		};

		class wxDropTargetDicomDir: public wxDropTarget
		{
		public:
			wxDropTargetDicomDir(bool aceptaIzquierda = true)
			{
				SetDataObject(new wxDicomDirDnD);
				SetDefaultAction(wxDragCopy);
				m_aceptaIzquierda = aceptaIzquierda;
			}

			~wxDropTargetDicomDir()
			{
			}

			virtual wxDragResult OnData(wxCoord /*x*/, wxCoord /*y*/, wxDragResult def)
			{
				if ( !GetData() )
					return wxDragNone;

				wxDicomDirDnD *dobj = static_cast<wxDicomDirDnD*>(m_dataObject);
				return (dobj->ArrancaIzquierda() && m_aceptaIzquierda) || (!dobj->ArrancaIzquierda() && !m_aceptaIzquierda) ? def : wxDragNone;
			}

		private:
			bool m_aceptaIzquierda;
		};
		//////////////////////END D&D/////////////////////////


		DicomBrowserComponent::DicomBrowserComponent(wxWindow *parent, wxWindowID winid, const wxPoint& pos, const wxSize& size, long style): 
			DicomBrowserComponentBase(parent,winid,pos,size,style)
		{
			m_pImageList = new wxImageList(SIZE_ICONOS,SIZE_ICONOS,true);
			m_pImageList->Add(GinkgoResourcesManager::History::GetIcoEstudio());
			m_pImageList->Add(GinkgoResourcesManager::History::GetIcoSerie());
			m_pImageList->Add(GinkgoResourcesManager::History::GetIcoHombre());
			m_pImageList->Add(GinkgoResourcesManager::History::GetIcoMujer());
			m_pImageList->Add(GinkgoResourcesManager::History::GetIcoOtro());
			m_pImageList->Add(GinkgoResourcesManager::History::GetIcoFicheroClave());
			m_pTreeListIzq->SetImageList(m_pImageList);
			m_pTreeListIzq->SetMainColumn(0);

			
			m_pTreeListIzq->Connect(wxEVT_COMMAND_TREE_ITEM_ACTIVATED, wxTreeEventHandler( DicomBrowserComponent::OnTreeIzqItemActivated ), NULL, this );
			m_pTreeListIzq->Connect(wxEVT_COMMAND_TREE_ITEM_MENU, wxTreeEventHandler( DicomBrowserComponent::OnTreeIzqItemMenu ), NULL, this );
			m_pTreeListIzq->Connect(wxEVT_COMMAND_TREE_BEGIN_DRAG, wxTreeEventHandler( DicomBrowserComponent::OnTreeIzqBeginDrag ), NULL, this );
			m_pTreeListIzq->SetDropTarget(new wxDropTargetDicomDir(false));

			m_pTreeListDer->Connect(wxEVT_COMMAND_TREE_ITEM_ACTIVATED, wxTreeEventHandler( DicomBrowserComponent::OnTreeDerItemActivated ), NULL, this );
			m_pTreeListDer->Connect(wxEVT_COMMAND_TREE_ITEM_MENU, wxTreeEventHandler( DicomBrowserComponent::OnTreeDerItemMenu ), NULL, this );
			m_pTreeListDer->Connect(wxEVT_COMMAND_TREE_BEGIN_DRAG, wxTreeEventHandler( DicomBrowserComponent::OnTreeDerBeginDrag ), NULL, this );
			m_pTreeListDer->SetDropTarget(new wxDropTargetDicomDir(true));
		}

		DicomBrowserComponent::~DicomBrowserComponent()
		{
			delete m_pImageList;
		}
		

		void DicomBrowserComponent::SetModel(IModeloDicom& modelo)
		{
			m_pTreeListDer->DeleteRoot();
			m_pTreeListDer->SetImageList(m_pImageList);
			m_pTreeListDer->SetMainColumn(0);
			m_pTreeListDer->AddRoot(wxT("Top"));


			m_pTreeListIzq->DeleteRoot();

			wxTreeItemId topTreeId = m_pTreeListIzq->AddRoot(wxT("Top"));

			for (IModeloDicom::ListaPacientesType::const_iterator it = modelo.ListaPacientes().begin(); it != modelo.ListaPacientes().end(); ++it) {
				const IModeloPaciente& p = *it;
				std::string pacienteNombre =p.GetNombre() + " (" + p.GetUID() + ")";
				wxString nombrePaciente = wxString::FromUTF8(pacienteNombre.c_str());
				//columnas
				wxTreeItemId pacienteTreeId = m_pTreeListIzq->AppendItem(topTreeId, nombrePaciente);
				m_pTreeListIzq->SetItemText(pacienteTreeId, COLUMNA_DCMDIR_UID, wxString::FromUTF8(p.GetUID().c_str()) );
				//

				// Estilo
				m_pTreeListIzq->SetItemBold(pacienteTreeId, true);
				m_pTreeListIzq->SetItemTextColour(pacienteTreeId, *wxBLUE);

				//iconos
				int icono = 0;
				if(p.GetSexo() == "M") {
					icono = ICONO_HOMBRE;
				} else if(p.GetSexo() == "F") {
					icono = ICONO_MUJER;
				} else {
					icono = ICONO_OTRO;
				}

				m_pTreeListIzq->SetItemImage(pacienteTreeId,icono,wxTreeItemIcon_Normal);
				m_pTreeListIzq->SetItemImage(pacienteTreeId,icono,wxTreeItemIcon_Selected);
				m_pTreeListIzq->SetItemImage(pacienteTreeId,icono,wxTreeItemIcon_Expanded);
				m_pTreeListIzq->SetItemImage(pacienteTreeId,icono,wxTreeItemIcon_SelectedExpanded);

				//ESTUDIOS
				for (IModeloPaciente::ListaEstudiosType::const_iterator it2 = p.ListaEstudios().begin(); it2 != p.ListaEstudios().end(); ++it2) {
					const IModeloEstudio& e = *it2;
					wxDateTime fecha;
					fecha.ParseFormat(wxString::FromUTF8(e.GetFecha().c_str()).GetData(), wxT("%Y%m%d"), wxDefaultDateTime);
					if (!fecha.IsValid()) {
						fecha.ParseFormat(wxString::FromUTF8(e.GetFecha().c_str()).GetData(), wxT("%Y-%m-%d"), wxDefaultDateTime);
					}

					wxString modalidadEstudio = wxString::FromUTF8(e.GetModalidad().c_str());
					wxString uidEstudio = wxString::FromUTF8(e.GetUID().c_str());
					wxString descripcionEstudio = wxString::FromUTF8(e.GetDescripcion().c_str());
					wxString AccNumber = wxString::FromUTF8(e.GetAccNumber().c_str());

					//columnas
					wxTreeItemId estudioTreeId;
					if (descripcionEstudio.IsEmpty()) {
						estudioTreeId = m_pTreeListIzq->AppendItem(pacienteTreeId, _("Untitled"));
					} else {
						estudioTreeId = m_pTreeListIzq->AppendItem(pacienteTreeId, descripcionEstudio);
					}
					m_pTreeListIzq->SetItemText(estudioTreeId, COLUMNA_DCMDIR_MODALIDAD, modalidadEstudio);
					if(fecha.IsValid()){
						m_pTreeListIzq->SetItemText(estudioTreeId, COLUMNA_DCMDIR_FECHA, wxString(
							fecha.Format(_("%m/%d/%Y"), wxDateTime::TimeZone(wxDateTime::GMT1))));
					}
					m_pTreeListIzq->SetItemText(estudioTreeId, COLUMNA_DCMDIR_MEDICO, wxString::FromUTF8(e.GetDoctor().c_str()));
					m_pTreeListIzq->SetItemText(estudioTreeId, COLUMNA_DCMDIR_ACCNUMBER, AccNumber);
					m_pTreeListIzq->SetItemText(estudioTreeId, COLUMNA_DCMDIR_UID, uidEstudio );
					//

					//ICONOS...
					m_pTreeListIzq->SetItemImage(estudioTreeId,ICONO_ESTUDIO,wxTreeItemIcon_Normal);
					m_pTreeListIzq->SetItemImage(estudioTreeId,ICONO_ESTUDIO,wxTreeItemIcon_Selected);
					m_pTreeListIzq->SetItemImage(estudioTreeId,ICONO_ESTUDIO,wxTreeItemIcon_Expanded);
					m_pTreeListIzq->SetItemImage(estudioTreeId,ICONO_ESTUDIO,wxTreeItemIcon_SelectedExpanded);

					for (IModeloEstudio::ListaSeriesType::const_iterator it3 = e.ListaSeries().begin(); it3 != e.ListaSeries().end(); ++it3) {
						const IModeloSerie& s = *it3;
						wxString uidSerie = wxString::FromUTF8(s.GetUID().c_str());
						wxString numeroDeImagenes = wxString::FromUTF8(s.GetNumero().c_str());
						wxString tipoSerie = wxString::FromUTF8(s.GetTipo().c_str());
						wxString descripcionSerie = wxString::FromUTF8(s.GetDescripcion().c_str());
						wxDateTime fechaSerie;
						fechaSerie.ParseFormat(wxString::FromUTF8(s.GetFecha().c_str()).GetData(), wxT("%Y%m%d"), wxDefaultDateTime);
						if (!fechaSerie.IsValid()) {
							fechaSerie.ParseFormat(wxString::FromUTF8(e.GetFecha().c_str()).GetData(), wxT("%Y-%m-%d"), wxDefaultDateTime);
						}

						wxTreeItemId serieTreeId;
						if (descripcionSerie.IsEmpty()) {
							serieTreeId = m_pTreeListIzq->AppendItem(estudioTreeId, _("Untitled"));
						} else {
							serieTreeId = m_pTreeListIzq->AppendItem(estudioTreeId, descripcionSerie);
						}

						m_pTreeListIzq->SetItemText(serieTreeId, COLUMNA_DCMDIR_MODALIDAD, tipoSerie);
						if(fechaSerie.IsValid()){
							m_pTreeListIzq->SetItemText(serieTreeId, COLUMNA_DCMDIR_FECHA, wxString(
								fechaSerie.Format(_("%m/%d/%Y"), wxDateTime::TimeZone(wxDateTime::GMT1))));
						}
						m_pTreeListIzq->SetItemText(serieTreeId, COLUMNA_DCMDIR_MEDICO, wxString::FromUTF8(s.GetDoctor().c_str()));
						m_pTreeListIzq->SetItemText(serieTreeId, COLUMNA_DCMDIR_ACCNUMBER, AccNumber);
						m_pTreeListIzq->SetItemText(serieTreeId, COLUMNA_DCMDIR_UID, uidSerie );

						m_pTreeListIzq->SetItemImage(serieTreeId,ICONO_SERIE,wxTreeItemIcon_Normal);
						m_pTreeListIzq->SetItemImage(serieTreeId,ICONO_SERIE,wxTreeItemIcon_Selected);
						m_pTreeListIzq->SetItemImage(serieTreeId,ICONO_SERIE,wxTreeItemIcon_Expanded);
						m_pTreeListIzq->SetItemImage(serieTreeId,ICONO_SERIE,wxTreeItemIcon_SelectedExpanded);

						wxPathsNodo* pDatosAsociados = new wxPathsNodo(s.GetUID(), false);
						for(IModeloSerie::ListaImagenesType::const_iterator it4 = s.ListaImagenes().begin(); it4 != s.ListaImagenes().end(); ++it4) {
							const IModeloImagen& i = *it4;
							if(i.GetPathImagen() != "") {
								pDatosAsociados->m_pListaPaths.push_back(i.GetPathImagen());
							} else {
								//std::cout << i.GetUID() << "    " << i.GetPathImagen();
							}
						}
						m_pTreeListIzq->SetItemData(serieTreeId, pDatosAsociados);
					}
				}
			}

			m_pTreeListIzq->ExpandAll(topTreeId);
			m_pTreeListDer->ExpandAll(m_pTreeListDer->GetRootItem());

			m_pTreeListIzq->SetAutoLayout(true);
			m_pTreeListDer->SetAutoLayout(true);

			m_pTreeListIzq->Enable(m_pTreeListIzq->GetCount() > 0);
			Layout();
		}


		void DicomBrowserComponent::SetDiagnosticModel(IModeloDicom& modelo)
		{
			wxTreeItemId topTreeId = m_pTreeListIzq->GetRootItem();

			for (IModeloDicom::ListaPacientesType::const_iterator it = modelo.ListaPacientes().begin(); it != modelo.ListaPacientes().end(); ++it) {
				const IModeloPaciente& p = *it;
				std::string pacienteNombre =p.GetNombre() + " (" + p.GetUID() + ")";
				wxString nombrePaciente = wxString::FromUTF8(pacienteNombre.c_str());
				
				wxTreeItemId pacienteTreeId = m_pTreeListIzq->FindItem(topTreeId, nombrePaciente, wxTL_MODE_FIND_EXACT | wxTL_MODE_NAV_LEVEL);

				if (!pacienteTreeId.IsOk()) {
					//columnas
					pacienteTreeId = m_pTreeListIzq->AppendItem(topTreeId, nombrePaciente);
					m_pTreeListIzq->SetItemText(pacienteTreeId, COLUMNA_DCMDIR_UID, wxString::FromUTF8(p.GetUID().c_str()) );
					//

					// Estilo
					m_pTreeListIzq->SetItemBold(pacienteTreeId, true);
					m_pTreeListIzq->SetItemTextColour(pacienteTreeId, *wxBLUE);

					//iconos
					int icono = 0;
					if(p.GetSexo() == "M") {
						icono = ICONO_HOMBRE;
					} else if(p.GetSexo() == "F") {
						icono = ICONO_MUJER;
					} else {
						icono = ICONO_OTRO;
					}

					m_pTreeListIzq->SetItemImage(pacienteTreeId,icono,wxTreeItemIcon_Normal);
					m_pTreeListIzq->SetItemImage(pacienteTreeId,icono,wxTreeItemIcon_Selected);
					m_pTreeListIzq->SetItemImage(pacienteTreeId,icono,wxTreeItemIcon_Expanded);
					m_pTreeListIzq->SetItemImage(pacienteTreeId,icono,wxTreeItemIcon_SelectedExpanded);
				}

				//ESTUDIOS
				for (IModeloPaciente::ListaEstudiosType::const_iterator it2 = p.ListaEstudios().begin(); it2 != p.ListaEstudios().end(); ++it2) {
					const IModeloEstudio& e = *it2;
					wxDateTime fecha;
					fecha.ParseFormat(wxString::FromUTF8(e.GetFecha().c_str()).GetData(), wxT("%Y%m%d"), wxDefaultDateTime);
					if (!fecha.IsValid()) {
						fecha.ParseFormat(wxString::FromUTF8(e.GetFecha().c_str()).GetData(), wxT("%Y-%m-%d"), wxDefaultDateTime);
					}

					wxString modalidadEstudio = wxString::FromUTF8(e.GetModalidad().c_str());
					wxString uidEstudio = wxString::FromUTF8(e.GetUID().c_str());
					wxString descripcionEstudio = wxString::FromUTF8(e.GetDescripcion().c_str());
					wxString AccNumber = wxString::FromUTF8(e.GetAccNumber().c_str());

					//columnas
					wxTreeItemId estudioTreeId = m_pTreeListIzq->AppendItem(pacienteTreeId, descripcionEstudio);
					m_pTreeListIzq->SetItemText(estudioTreeId, COLUMNA_DCMDIR_MODALIDAD, modalidadEstudio);
					if(fecha.IsValid()){
						m_pTreeListIzq->SetItemText(estudioTreeId, COLUMNA_DCMDIR_FECHA, wxString(
							fecha.Format(_("%m/%d/%Y"), wxDateTime::TimeZone(wxDateTime::GMT1))));
					}
					m_pTreeListIzq->SetItemText(estudioTreeId, COLUMNA_DCMDIR_MEDICO, wxString::FromUTF8(e.GetDoctor().c_str()));
					m_pTreeListIzq->SetItemText(estudioTreeId, COLUMNA_DCMDIR_ACCNUMBER, AccNumber);
					m_pTreeListIzq->SetItemText(estudioTreeId, COLUMNA_DCMDIR_UID, uidEstudio );
					//

					//ICONOS...
					m_pTreeListIzq->SetItemImage(estudioTreeId,ICONO_DIAGNOSTICO,wxTreeItemIcon_Normal);
					m_pTreeListIzq->SetItemImage(estudioTreeId,ICONO_DIAGNOSTICO,wxTreeItemIcon_Selected);
					m_pTreeListIzq->SetItemImage(estudioTreeId,ICONO_DIAGNOSTICO,wxTreeItemIcon_Expanded);
					m_pTreeListIzq->SetItemImage(estudioTreeId,ICONO_DIAGNOSTICO,wxTreeItemIcon_SelectedExpanded);
					
					wxPathsNodo* pDatosAsociados = new wxPathsNodo(e.GetUID(), true);
					m_pTreeListIzq->SetItemData(estudioTreeId, pDatosAsociados);
				}
			}

			m_pTreeListIzq->Expand(topTreeId);

			m_pTreeListIzq->SetAutoLayout(true);
			m_pTreeListDer->SetAutoLayout(true);

			m_pTreeListIzq->Enable(m_pTreeListIzq->GetCount() > 0);
			Layout();
		}

		void DicomBrowserComponent::OnDicomDirIzqAddAll(wxCommandEvent& )
		{
			wxArrayTreeItemIds idsSeleccionados;
			HelperGetAllPatients(m_pTreeListIzq,idsSeleccionados);
			AddItemsSeleccionados(idsSeleccionados);
			m_pTreeListDer->ExpandAll(m_pTreeListDer->GetRootItem());
		}

		void DicomBrowserComponent::OnDicomDirDerDelAll(wxCommandEvent& )
		{
			wxArrayTreeItemIds idsSeleccionados;
			HelperGetAllPatients(m_pTreeListDer,idsSeleccionados);
			DelItemsSeleccionados(idsSeleccionados);
		}

		void DicomBrowserComponent::OnTreeIzqItemActivated(wxTreeEvent& )
		{
			AddItemsSeleccionados();
		}

		void DicomBrowserComponent::OnTreeDerItemActivated(wxTreeEvent& )
		{
			DelItemsSeleccionados();
		}

		void DicomBrowserComponent::OnAdd(wxCommandEvent& )
		{
			AddItemsSeleccionados();
		}

		void DicomBrowserComponent::OnDel(wxCommandEvent&)
		{
			DelItemsSeleccionados();
		}

		void DicomBrowserComponent::OnTreeIzqBeginDrag(wxTreeEvent& )
		{
			wxDicomDirDnD myData(true);
			wxDropSource dragSource(myData,this);
			wxDragResult result = dragSource.DoDragDrop(wxDrag_AllowMove);
			if (result == wxDragCopy) {
				AddItemsSeleccionados();
			}
		}

		void DicomBrowserComponent::OnTreeDerBeginDrag(wxTreeEvent& )
		{
			wxDicomDirDnD myData(false);
			wxDropSource dragSource(myData,this);
			wxDragResult result = dragSource.DoDragDrop(wxDrag_AllowMove);
			if (result == wxDragCopy) {
				DelItemsSeleccionados();
			}
		}

		void DicomBrowserComponent::AddItemsSeleccionados()
		{
			wxArrayTreeItemIds idsSeleccionados;
			AddItemsSeleccionados(idsSeleccionados);
		}
		void DicomBrowserComponent::AddItemsSeleccionados(wxArrayTreeItemIds& idsSeleccionados)
		{
			//adquirimos desde dicomdir
			if(m_pTreeListIzq->GetCount() == 0) {
				wxMessageBox(_("Select a valid DICOMDIR file"), _("Info"),
					wxOK | wxICON_INFORMATION, this);
				return ;
			}

			if (idsSeleccionados.size() == 0) {
				m_pTreeListIzq->GetSelections(idsSeleccionados);
			}
			for(wxArrayTreeItemIds::iterator it = idsSeleccionados.begin(); it!= idsSeleccionados.end(); ++it) {
				//se aņade el nodo seleccionado al otro arbol.. se aņadira sus padres y todos sus hijos
				wxArrayTreeItemIds listaPadres;
				for (wxTreeItemId idPadre = m_pTreeListIzq->GetItemParent((*it)); idPadre != m_pTreeListIzq->GetRootItem(); idPadre = m_pTreeListIzq->GetItemParent(idPadre) ) {
					listaPadres.Add(idPadre);
				}
				//se recorre inverso para insertar los padres
				wxTreeItemId actualIzq;
				wxTreeItemId actualDer;
				wxTreeItemId padreDer = m_pTreeListDer->GetRootItem();
				while (listaPadres.size() >0)
				{
					actualIzq = listaPadres.back();
					actualDer = HelperBuscaID(padreDer, m_pTreeListIzq->GetItemText(actualIzq,COLUMNA_DCMDIR_UID));
					if ( !actualDer.IsOk() ) {
						//se inserta
						actualDer = m_pTreeListDer->AppendItem(padreDer, m_pTreeListIzq->GetItemText(actualIzq), m_pTreeListIzq->GetItemImage(actualIzq, wxTreeItemIcon_Normal), m_pTreeListIzq->GetItemImage(actualIzq, wxTreeItemIcon_Selected) );
						wxTreeItemData* pData = m_pTreeListIzq->GetItemData(actualIzq);
						if(pData != NULL) {
							m_pTreeListDer->SetItemData( actualDer,new wxPathsNodo( *( static_cast<wxPathsNodo*>(pData) ) ));
						}
						for (int i = 1; i < m_pTreeListDer->GetColumnCount(); ++i) {
							m_pTreeListDer->SetItemText( actualDer, i, m_pTreeListIzq->GetItemText(actualIzq,i) );
						}
					}
					padreDer = actualDer;
					listaPadres.pop_back();
				}
				//padres aņadidos
				//se copia el mismo....
				actualIzq =  (*it);
				actualDer = HelperBuscaID(padreDer, m_pTreeListIzq->GetItemText(actualIzq,COLUMNA_DCMDIR_UID));
				if ( !actualDer.IsOk() ) {
					//se inserta
					actualDer = m_pTreeListDer->AppendItem(padreDer, m_pTreeListIzq->GetItemText(actualIzq), m_pTreeListIzq->GetItemImage(actualIzq, wxTreeItemIcon_Normal), m_pTreeListIzq->GetItemImage(actualIzq, wxTreeItemIcon_Selected) );
					wxTreeItemData* pData = m_pTreeListIzq->GetItemData(actualIzq);
					if(pData != NULL) {
						m_pTreeListDer->SetItemData( actualDer, new wxPathsNodo( *( static_cast<wxPathsNodo*>(pData) ) ));
					}
					for (int i = 1; i < m_pTreeListDer->GetColumnCount(); ++i) {
						m_pTreeListDer->SetItemText( actualDer, i, m_pTreeListIzq->GetItemText(actualIzq,i) );
					}
				}
				//se copian sus hijos en profundidad...
				HelperCopiaEnProfundidad(actualDer, actualIzq);
				m_pTreeListDer->EnsureVisible(actualDer);
			}
		}

		void DicomBrowserComponent::DelItemsSeleccionados()
		{
			wxArrayTreeItemIds idsSeleccionados;
			DelItemsSeleccionados(idsSeleccionados);
		}

		void DicomBrowserComponent::DelItemsSeleccionados(wxArrayTreeItemIds& idsSeleccionados)
		{
			if (idsSeleccionados.size() == 0) {
				m_pTreeListDer->GetSelections(idsSeleccionados);
			}
			for(wxArrayTreeItemIds::iterator it = idsSeleccionados.begin(); it!= idsSeleccionados.end(); ++it) {
				wxTreeItemId item = (*it);
				if(item.IsOk()) {
					wxTreeItemId idPadre = m_pTreeListDer->GetItemParent(item);
					m_pTreeListDer->Delete(item);

					while ( m_pTreeListDer->GetChildrenCount(idPadre) == 0 && idPadre != m_pTreeListDer->GetRootItem() ){
						wxTreeItemId padreAux = idPadre;
						idPadre = m_pTreeListDer->GetItemParent(idPadre);
						m_pTreeListDer->Delete(padreAux);
					}
				}
			}
		}

		void DicomBrowserComponent::OnTreeDerItemMenu(wxTreeEvent& event)
		{
			//clase menu contextual
			class PopUpMenuDescargar: public wxMenu
			{
			public:
				PopUpMenuDescargar(DicomBrowserComponent* pPaso):wxMenu()
				{
					m_pPaso = pPaso;
					wxMenuItem* del = new wxMenuItem( this,wxID_ANY,_("Remove"));
					Append(del);

					Connect(del->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( PopUpMenuDescargar::OnDel ),NULL,this);
				}
				~PopUpMenuDescargar()
				{
					m_pPaso = NULL;
					Disconnect(wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( PopUpMenuDescargar::OnDel ),NULL,this);
				}

				void OnDel(wxCommandEvent& )
				{
					m_pPaso->DelItemsSeleccionados();
				}

				DicomBrowserComponent* m_pPaso;
			};
			//

			wxTreeItemId item = event.GetItem();
			if(item.IsOk()){
				PopUpMenuDescargar* pMenu = new PopUpMenuDescargar(this);

				m_pTreeListDer->PopupMenu(pMenu);

				delete pMenu;
			}
		}

		void DicomBrowserComponent::OnTreeIzqItemMenu(wxTreeEvent& event)
		{
			//clase menu contextual
			class PopUpMenuDescargar: public wxMenu
			{
			public:
				PopUpMenuDescargar(DicomBrowserComponent* pPaso):wxMenu()
				{
					m_pPaso = pPaso;
					wxMenuItem* add = new wxMenuItem( this,wxID_ANY,_("Add"));
					Append(add);

					Connect(add->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( PopUpMenuDescargar::OnAdd ),NULL,this);
				}
				~PopUpMenuDescargar()
				{
					m_pPaso = NULL;
					Disconnect(wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( PopUpMenuDescargar::OnAdd ),NULL,this);
				}

				void OnAdd(wxCommandEvent& )
				{
					m_pPaso->AddItemsSeleccionados();
				}

				DicomBrowserComponent* m_pPaso;
			};
			//

			wxTreeItemId item = event.GetItem();
			if(item.IsOk()){
				PopUpMenuDescargar* pMenu = new PopUpMenuDescargar(this);

				m_pTreeListIzq->PopupMenu(pMenu);

				delete pMenu;
			}
		}

		wxTreeItemId DicomBrowserComponent::HelperBuscaID(const wxTreeItemId& padre, const wxString& uid)
		{
			wxTreeItemId resultado;
			wxTreeItemIdValue cookie;
			wxTreeItemId actual = m_pTreeListDer->GetFirstChild(padre,cookie);
			while (actual.IsOk()) {
				if ( m_pTreeListDer->GetItemText(actual, COLUMNA_DCMDIR_UID) == uid ) {
					resultado = actual;
					break;
				}
				actual = m_pTreeListDer->GetNextSibling(actual);
			}
			return resultado;
		}

		void DicomBrowserComponent::HelperCopiaEnProfundidad(const wxTreeItemId& padreDer, const wxTreeItemId& padreIzq)
		{
			wxTreeItemIdValue cookie;
			wxTreeItemId actualIzq = m_pTreeListIzq->GetFirstChild(padreIzq,cookie);
			wxTreeItemId actualDer;
			while ( actualIzq.IsOk() ) {
				//se copia el hijo...
				actualDer = HelperBuscaID(padreDer, m_pTreeListIzq->GetItemText(actualIzq,COLUMNA_DCMDIR_UID));
				if ( !actualDer.IsOk() ) {
					//se inserta
					actualDer = m_pTreeListDer->AppendItem(padreDer, m_pTreeListIzq->GetItemText(actualIzq), m_pTreeListIzq->GetItemImage(actualIzq, wxTreeItemIcon_Normal), m_pTreeListIzq->GetItemImage(actualIzq, wxTreeItemIcon_Selected) );
					wxTreeItemData* pData = m_pTreeListIzq->GetItemData(actualIzq);
					if(pData != NULL) {
						m_pTreeListDer->SetItemData( actualDer, new wxPathsNodo( *( static_cast<wxPathsNodo*>(pData) ) ) );
					}
					for (int i = 1; i < m_pTreeListDer->GetColumnCount(); ++i) {
						m_pTreeListDer->SetItemText( actualDer, i, m_pTreeListIzq->GetItemText(actualIzq,i) );
					}
				}
				//se copian los hijos de actualIzq
				HelperCopiaEnProfundidad(actualDer, actualIzq);
				actualIzq = m_pTreeListDer->GetNextSibling(actualIzq);
			}
		}

		void DicomBrowserComponent::HelperGetAllPatients(wxTreeListCtrl* pTree, wxArrayTreeItemIds& idsSeleccionados)
		{
			wxTreeItemId idTree;
			wxTreeItemId raiz = pTree->GetRootItem();

			wxTreeItemIdValue cookie;
			idTree = pTree->GetFirstChild(raiz,cookie);
			while(idTree.IsOk()) {
				idsSeleccionados.Add(idTree);
				idTree = pTree->GetNextSibling(idTree);
			}
		}

		void DicomBrowserComponent::HelperRellenaPathsDicomDir(const wxTreeItemId& id, std::set<std::string>& listaPaths) 
		{
			if(m_pTreeListDer->GetChildrenCount(id) == 0) {
				wxTreeItemData* pDatos = m_pTreeListDer->GetItemData(id);
				if(pDatos!=NULL){
					wxPathsNodo* pPaths = static_cast<wxPathsNodo*>(pDatos);
					for(std::list<std::string>::iterator it = pPaths->m_pListaPaths.begin(); it != pPaths->m_pListaPaths.end(); ++it) {
						listaPaths.insert((*it));
					}
				}
			} else {
				wxTreeItemIdValue cookie;
				wxTreeItemId idHijo = m_pTreeListDer->GetFirstChild(id, cookie);
				while(idHijo.IsOk()) {
					HelperRellenaPathsDicomDir(idHijo,listaPaths);
					idHijo = m_pTreeListDer->GetNextSibling(idHijo);
				}
			}
		}

		void DicomBrowserComponent::HelperRellenaUIDs(const wxTreeItemId& id, std::set<std::string>& seriesSet, bool isDiagnostic) 
		{
			if(m_pTreeListDer->GetChildrenCount(id) == 0) {
				wxTreeItemData* pDatos = m_pTreeListDer->GetItemData(id);
				if(pDatos!=NULL){
					wxPathsNodo* pPaths = static_cast<wxPathsNodo*>(pDatos);
					if (pPaths->m_isDiagnostic == isDiagnostic) {
						seriesSet.insert(pPaths->m_uid);
					}
				}
			} else {
				wxTreeItemIdValue cookie;
				wxTreeItemId idHijo = m_pTreeListDer->GetFirstChild(id, cookie);
				while(idHijo.IsOk()) {
					HelperRellenaUIDs(idHijo,seriesSet, isDiagnostic);
					idHijo = m_pTreeListDer->GetNextSibling(idHijo);
				}
			}
		}

		std::list<std::string> DicomBrowserComponent::GetSelectedPaths()
		{			
			std::list<std::string> listaPaths;

			std::set<std::string> conjuntoPaths;
			wxTreeItemIdValue cookie;
			wxTreeItemId idPaciente = m_pTreeListDer->GetFirstChild(m_pTreeListDer->GetRootItem(),cookie);
			while(idPaciente.IsOk()) {
				HelperRellenaPathsDicomDir(idPaciente,conjuntoPaths);
				idPaciente = m_pTreeListDer->GetNextSibling(idPaciente);
			}

			for(std::set<std::string>::iterator it = conjuntoPaths.begin(); it != conjuntoPaths.end(); ++it) {
				listaPaths.push_back((*it));
			}

			return listaPaths;
		}

		std::list<std::string> DicomBrowserComponent::GetSelectedUIDs(bool isDiagnostic)
		{
			std::list<std::string> seriesList;

			std::set<std::string> seriesSet;
			wxTreeItemIdValue cookie;
			wxTreeItemId idPaciente = m_pTreeListDer->GetFirstChild(m_pTreeListDer->GetRootItem(),cookie);
			while(idPaciente.IsOk()) {
				HelperRellenaUIDs(idPaciente,seriesSet, isDiagnostic);
				idPaciente = m_pTreeListDer->GetNextSibling(idPaciente);
			}

			for(std::set<std::string>::iterator it = seriesSet.begin(); it != seriesSet.end(); ++it) {
				seriesList.push_back((*it));
			}

			return seriesList;
		}
	}
}
