/*
*
*  $Id: historypanel3.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 <api/globals.h>
#include <api/ilock.h>
#include <set>
#include <wx/ginkgostyle/ginkgostyle.h>
#include <wx/aui/aui.h>
#include <wx/imaglist.h>

#include "historypanel3.h"
#include "wxhistoryimagethumbnail.h"
#include "historytoolmenu.h"
#include "confirmdeletedialog.h"
#include "openwithdialog.h"

#include <resources/ginkgoresourcesmanager.h>
#include <main/entorno.h>
#include <main/gui/mainwindow/ventanaprincipal.h>
#include <main/gui/taskcontrol/taskcontrol.h>
#include <main/controllers/historycontroller.h>
#include <main/controllers/controladoreventos.h>
#include <main/controllers/controladorpermisos.h>
#include <main/controllers/controladorcomandos.h>
#include <main/controllers/configurationcontroller.h>
#include <main/controllers/controladorvistas.h>
#include <main/controllers/controladorlog.h>
#include <main/controllers/controladorextensiones.h>
#include <main/controllers/controladorenviohl7.h>
#include <main/controllers/streaming/streamingloader.h>
#include <main/controllers/integrationcontroller.h>
#include <main/controllers/hangingprotocolcontroller.h>

#include <commands/comandoincluirhistorial.h>

#include <main/gui/import/wxwizardimportacionginkgo.h>
#include <main/gui/acquisition/dialogoadquisicion.h>
#include <main/gui/progress/statusbarprogreso.h>

#include <api/dicom/idicommanager.h>
#include <export/tagsprivadoscomunes.h>

#include <commands/openremovableunit.h>
#include <commands/sendpacscommand.h>

#include <eventos/progresocomando.h>

#include <vtkImageData.h>
#include <vtkUnsignedCharArray.h>
#include <vtkPointData.h>
#include <vtk/vtkginkgoimageviewer.h>
#include <wxVTKRenderWindowInteractor.h>
#include <vtk/interactor/ginkgointeractorstyleimage2d.h>
#include <main/gui/droptargetmainwindow.h>

#define SIZE_ICONOS 16

#define ICONO_ESTUDIO 0
#define ICONO_SERIE 1
#define ICONO_HOMBRE 2
#define ICONO_MUJER 3
#define ICONO_OTRO 4


#define SIZE_THUMBNAILS 96

		

//////////////////////////////////////////////////////////////////////////
namespace GNC {
	namespace GUI {
		class ReloadHistoryTimer:public wxTimer
		{
		public:
			ReloadHistoryTimer(HistoryPanel3* pHistory){
				m_pHistory = pHistory;
			}

			~ReloadHistoryTimer()
			{
				m_pHistory=NULL;
			}

			virtual void Notify()
			{
				m_pHistory->RefreshSearch(true);
			}

			HistoryPanel3* m_pHistory;
		};
		///////////////////////////////////////////////////////////////////////////////////////////////////////
		class wxPatientData: public wxClientData {
		public:
			wxPatientData(const GNC::GCS::HistoryController::PatientModel& patientModel):wxClientData()
			{
				m_PatientModel = patientModel;
			}
			~wxPatientData() {
			}
			GNC::GCS::HistoryController::PatientModel m_PatientModel;
		};
		//////////////////////////////////////////////////////////////////////////
		class TableDataModel {
		public:
			TableDataModel(wxTreeListCtrl* pTree) 
			{
				m_pTree = pTree;
				m_sortCriteria = 0;
				m_reverse = false;
			}
			~TableDataModel(){}

			void ReloadTree(const GNC::GCS::HistoryController::StudyModelList& studyList, bool force) 
			{
				wxCriticalSectionLocker locker(criticalSection);				
				if (force) {
					m_pTree->DeleteRoot();
					m_pTree->AddRoot(wxT("Top"));
					mapOfStudies.clear();
				} else {
					//remove nodes that doesn't come in this new list
					std::set<long> setOfpk;
					for(GNC::GCS::HistoryController::StudyModelList::const_iterator it = studyList.begin(); it!= studyList.end(); ++it) {
						setOfpk.insert((*it).pk);
					}
					std::list<long> deleteIdList;
					for (TMapIndex::iterator itIndex = mapOfStudies.begin(); itIndex != mapOfStudies.end(); ++itIndex) {
						if (setOfpk.find((*itIndex).first) == setOfpk.end()) {
							deleteIdList.push_back((*itIndex).first);
						}
					}
					for (std::list<long>::iterator it = deleteIdList.begin(); it != deleteIdList.end(); ++it) {
						m_pTree->Delete(mapOfStudies[(*it)]);
						mapOfStudies.erase(mapOfStudies.find((*it)));
					}
				}

				for(GNC::GCS::HistoryController::StudyModelList::const_iterator it = studyList.begin(); it!= studyList.end(); ++it) {
					GNC::GCS::HistoryController::StudyModel studyModel = (*it);
					InsertOrUpdateStudy(studyModel);
				}
				m_pTree->SortChildren(m_pTree->GetRootItem(), m_sortCriteria, m_reverse);
			}

			bool ExpandStudy(const int pk_study) 
			{
				wxCriticalSectionLocker locker(criticalSection);
				if (mapOfStudies.find(pk_study) == mapOfStudies.end())  {
					return false;
				}
				wxTreeItemId nodeStudy = mapOfStudies[pk_study];
				m_pTree->DeleteChildren(nodeStudy);
				GNC::GCS::HistoryController::SeriesModelList seriesList;
				GNC::GCS::HistoryController::Instance()->GetSeriesFromStudy(pk_study, seriesList);
				for(GNC::GCS::HistoryController::SeriesModelList::const_iterator it = seriesList.begin(); it != seriesList.end(); ++it) {
					InsertSeries(nodeStudy,(*it));
				}
				m_pTree->SortChildren(nodeStudy, m_sortCriteria, m_reverse);

				return true;				
			}

			void ChangeSortCriteria(int column) {
				wxCriticalSectionLocker locker(criticalSection);
				if (column >= 0) {
					if (column == m_sortCriteria) {
						m_reverse  = !m_reverse;
					}
					m_sortCriteria = column;
					m_pTree->SortChildren(m_pTree->GetRootItem(), column, m_reverse);
				}
			}

			void GetSeriesPkSelected(std::set<long>& setOfPks)
			{
				wxCriticalSectionLocker locker(criticalSection);
				wxArrayTreeItemIds selectedItems;
				m_pTree->GetSelections(selectedItems);
				wxTreeItemId root = m_pTree->GetRootItem();
				if (!root.IsOk())
					return;
				
				for (wxArrayTreeItemIds::iterator itSelection = selectedItems.begin(); itSelection != selectedItems.end(); ++itSelection) 
				{
					long pk;
					m_pTree->GetItemText((*itSelection), COL_PK).ToLong(&pk);
					if (m_pTree->GetItemParent((*itSelection)) == root) {
						//study adds child series
						GNC::GCS::HistoryController::SeriesModelList seriesModel;
						GNC::GCS::HistoryController::Instance()->GetSeriesFromStudy(pk, seriesModel);
						for (GNC::GCS::HistoryController::SeriesModelList::iterator itSeries = seriesModel.begin(); itSeries!= seriesModel.end(); ++itSeries) 
						{
							setOfPks.insert((*itSeries).pk);
						}
					} else {
						setOfPks.insert(pk);
					}
				}
			}

			void RemoveSelected()
			{
				wxCriticalSectionLocker locker(criticalSection);
				wxArrayTreeItemIds selected;
				//first delete leaves...
				m_pTree->GetSelections(selected);
				while (!selected.empty()) {
					wxTreeItemId id = selected.back();
					selected.pop_back();
					if (m_pTree->GetItemParent(id) == m_pTree->GetRootItem()) {
						long pk;
						m_pTree->GetItemText(id, COL_PK).ToLong(&pk);
						if (mapOfStudies.find(pk) != mapOfStudies.end()) {
							mapOfStudies.erase(mapOfStudies.find(pk));
						}
						//delete from selected childs of this node
						wxArrayTreeItemIds newSelection;
						for (wxArrayTreeItemIds::iterator it = selected.begin(); it != selected.end(); ++it) {
							if (m_pTree->GetItemParent((*it)) != id) {
								newSelection.push_back((*it));
							}
						}					
						selected = newSelection;
					}
					m_pTree->Delete(id);
				}
			}

			void SelectAll()
			{
				wxCriticalSectionLocker locker(criticalSection);
				m_pTree->SelectAll();
			}

			void DeselectAll()
			{
				wxCriticalSectionLocker locker(criticalSection);
				m_pTree->UnselectAll();
			}

		protected:
			wxTreeItemId InsertOrUpdateStudy(GNC::GCS::HistoryController::StudyModel& studyModel) 
			{
				TMapIndex::iterator itMap = mapOfStudies.find(studyModel.pk);
				wxTreeItemId idNode;

				//iconos
				int icono = 0;
				if(studyModel.pat_sex == 'M') {
					icono = ICONO_HOMBRE;
				} else if(studyModel.pat_sex == 'F') {
					icono = ICONO_MUJER;
				} else {
					icono = ICONO_OTRO;
				}

				if(itMap != mapOfStudies.end()) 
				{
					idNode = (*itMap).second;	
					m_pTree->SetItemText(m_pTree->GetRootItem(), wxString::FromUTF8(studyModel.pat_name.c_str()));
					if (m_pTree->GetChildrenCount(idNode) == 0) {
						m_pTree->AppendItem(idNode, _("Searching..."));
					}
				} else {
					idNode = m_pTree->AppendItem(m_pTree->GetRootItem(), wxString::FromUTF8(studyModel.pat_name.c_str()), icono, icono, NULL);
					m_pTree->AppendItem(idNode, _("Searching..."));
					mapOfStudies[studyModel.pk] = idNode;
				}

				wxDateTime birthDate, studyDate;
				birthDate.ParseFormat(wxString::FromUTF8( studyModel.pat_bithdate.c_str() ).GetData(), wxT("%Y-%m-%d"), wxDefaultDateTime);
				studyDate.ParseFormat(wxString::FromUTF8( studyModel.study_datetime.c_str() ).GetData(), wxT("%Y-%m-%dT%H:%M:%S"), wxDefaultDateTime);
				wxString dateTimeStr;
				int age = GetAge(birthDate, studyDate);
				{
					if(studyDate.IsValid()){
						dateTimeStr = wxString(studyDate.Format(_("%m/%d/%Y %H:%M:%S"), wxDateTime::TimeZone(wxDateTime::GMT1)));
					}
					else {
						dateTimeStr = _("00/00/0000 00:00:00");
					}
				}
				
				m_pTree->SetItemText(idNode, COL_PATIENT_ID, wxString::FromUTF8(studyModel.pat_id.c_str()));
				if (age >= 0) {
					m_pTree->SetItemText(idNode, COL_AGE, wxString::Format(wxT("%d"), age));
				}
				wxString modsInStudy;
				for (GNC::GCS::HistoryController::StringList::iterator it = studyModel.mods_in_study.begin(); it != studyModel.mods_in_study.end(); ++it) {
					if (it != studyModel.mods_in_study.begin()) {
						modsInStudy += wxT("/");
					}
					modsInStudy += wxString::FromUTF8((*it).c_str());
				}
				m_pTree->SetItemText(idNode, COL_MODALITY, modsInStudy);
				m_pTree->SetItemText(idNode, COL_DESCRIPTION, wxString::FromUTF8(studyModel.study_desc.c_str()));
				m_pTree->SetItemText(idNode, COL_DATE_TIME, dateTimeStr);
				m_pTree->SetItemText(idNode, COL_ACCNUMBER, wxString::FromUTF8(studyModel.study_acc_no.c_str()));
				m_pTree->SetItemText(idNode, COL_PK, wxString::Format(wxT("%d"),(studyModel.pk)));
				if (studyModel.pending_tasks > 0) {
					m_pTree->SetItemBackgroundColour(idNode, wxColour(255,128,64));
				} else {
					m_pTree->SetItemBackgroundColour(idNode, wxColour());
				}
				m_pTree->SetItemText(idNode, COL_PENDING_TASKS, wxString::Format(wxT("%d"),studyModel.pending_tasks));

				//to enable expand...
				if (m_pTree->GetChildrenCount(idNode) == 0) {
					//m_pTree->AppendItem(idNode, _("Searching..."));
				}

				return idNode;
			}

			int GetAge(wxDateTime& birthDate, wxDateTime& other) {
				if (!birthDate.IsValid() || !other.IsValid()) {
					return -1;
				}
				if (other.GetYear() == birthDate.GetYear()) {
					return 0;
				} else {
					if (other.GetMonth() > birthDate.GetMonth()) {
						return other.GetYear() - birthDate.GetYear();
					} else if (other.GetMonth() < birthDate.GetMonth()) {
						return other.GetYear() - birthDate.GetYear() -1;
					} else {
						if (other.GetDay() >= birthDate.GetDay()) {
							return other.GetYear() - birthDate.GetYear();
						} else {
							return other.GetYear() - birthDate.GetYear() -1;
						}
					}
				}
			}

			wxTreeItemId InsertSeries(wxTreeItemId parent, const GNC::GCS::HistoryController::SeriesModel& model)
			{
				wxDateTime seriesDate;
				seriesDate.ParseFormat(wxString::FromUTF8( model.series_datetime.c_str() ).GetData(), wxT("%Y-%m-%dT%H:%M:%S"), wxDefaultDateTime);
				wxString dateTimeStr;
				{
					if(seriesDate.IsValid()){
						dateTimeStr = wxString(seriesDate.Format(_("%m/%d/%Y %H:%M:%S"), wxDateTime::TimeZone(wxDateTime::GMT1)));
					}
					else {
						dateTimeStr = _("0000/00/00 00:00:00");
					}
				}

				wxTreeItemId idNode = m_pTree->AppendItem(parent, wxString::FromUTF8(model.series_desc.c_str()), -1, -1, NULL);
				m_pTree->SetItemText(idNode, COL_MODALITY, wxString::FromUTF8(model.series_modality.c_str()));
				m_pTree->SetItemText(idNode, COL_DESCRIPTION, wxString::FromUTF8(model.series_desc.c_str()));
				m_pTree->SetItemText(idNode, COL_DATE_TIME, dateTimeStr);
				m_pTree->SetItemText(idNode, COL_PENDING_TASKS, wxString::Format(wxT("%d"),model.pendingTasks.size()));
				m_pTree->SetItemText(idNode, COL_PK, wxString::Format(wxT("%d"),model.pk));
				return idNode;
			}

			

			/*wxTreeItemId getSeries
			{
			}*/
		protected:
			wxTreeListCtrl* m_pTree;
			typedef std::map<long, wxTreeItemId> TMapIndex;
			TMapIndex mapOfStudies;
			int m_sortCriteria;
			wxCriticalSection criticalSection;
			bool m_reverse;
		};
		///////////////////////////////////////////////
		class wxPopUpMenuThumbnails: public wxMenu
		{
		public:
			wxPopUpMenuThumbnails(GNC::GUI::HistoryPanel3* historyPanel, long seriesPk) :wxMenu(), HistoryPanel(historyPanel), SeriesPk(seriesPk)
			{				
				if (seriesPk != -1) {
					wxMenuItem* pItem = Append(wxID_ANY, _("Open Series"));
					Connect(pItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( wxPopUpMenuThumbnails::OnOpenMenu), NULL, this);
					pItem = Append(wxID_ANY, _("Open Series with .."));
					Connect(pItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( wxPopUpMenuThumbnails::OnOpenWithMenu), NULL, this);
					AppendSeparator();
				}

				GNC::HistoryToolsController::Instance()->AppendsToolInMenu(this, this, GNC::GCS::IHistoryTool::TFamily_Open);
				if (GetMenuItemCount() > 0 && !GetMenuItems().back()->IsSeparator()) {
					AppendSeparator();
				}
				GNC::HistoryToolsController::Instance()->AppendsToolInMenu(this, this, GNC::GCS::IHistoryTool::TFamily_Q_R);
				if (GetMenuItemCount() > 0 && !GetMenuItems().back()->IsSeparator()) {
					AppendSeparator();
				}
				GNC::HistoryToolsController::Instance()->AppendsToolInMenu(this, this, GNC::GCS::IHistoryTool::TFamily_Dicomize);
			}
			~wxPopUpMenuThumbnails()
			{
				Disconnect(wxID_ANY,wxEVT_COMMAND_MENU_SELECTED,wxCommandEventHandler( wxPopUpMenuThumbnails::OnOpenMenu),NULL,this);
				Disconnect(wxID_ANY,wxEVT_COMMAND_MENU_SELECTED,wxCommandEventHandler( wxPopUpMenuThumbnails::OnOpenWithMenu),NULL,this);
			}

			void OnOpenMenu(wxCommandEvent& )
			{
				HistoryPanel->OpenSeriesOrStudy(SeriesPk, true);
			}

			void OnOpenWithMenu(wxCommandEvent& )
			{
				HistoryPanel->OpenSeriesOrStudyWith(SeriesPk, true);
			}

			long SeriesPk;
			GNC::GUI::HistoryPanel3* HistoryPanel;
		};

	}
}

//---------------------------------------------------------------------------
/**
helper to launch tasks
**/
void launchTasks(const std::list<GNC::GCS::HistoryController::TaskModel>& tasks) 
{
	for (std::list<GNC::GCS::HistoryController::TaskModel>::const_iterator it = tasks.begin(); it != tasks.end(); ++it) {
		//TODO all tasks are sendcommands
		GADAPI::SendPACSCommand* pCmd = new GADAPI::SendPACSCommand((*it).pk, (*it).seriesId);
		pCmd->init((*it).data);
		GNC::ControladorComandos::Instance()->ProcessAsync("",pCmd,NULL);
	}
}
//---------------------------------------------------------------------------

GNC::GUI::HistoryPanel3* GNC::GUI::HistoryPanel3::Instance()
{
	if (m_pInstance == NULL) {
		m_pInstance = new HistoryPanel3(GNC::Entorno::Instance()->GetVentanaRaiz());
	}
	return m_pInstance;
}

void GNC::GUI::HistoryPanel3::FreeInstance()
{
	if(m_pInstance!=NULL){
		m_pInstance->Close();
		m_pInstance = NULL;
	}
}

GNC::GUI::HistoryPanel3* GNC::GUI::HistoryPanel3::m_pInstance = NULL;


GNC::GUI::HistoryPanel3::HistoryPanel3(wxWindow* pParent) : HistoryPanel3Base(pParent), Loader(new GNC::StreamingLoader())
{
	m_pImageList = new wxImageList(SIZE_ICONOS,SIZE_ICONOS,true);
	m_pTimerReload = new ReloadHistoryTimer(this);
	
	ViewImage2D->IImagePropertiesProxy = Loader;
	ViewImage2D->SetInputConnection(Loader->GetOutputPort());
	ViewImage2D->SetInteractionStyle(vtkGinkgoImageViewer::ZOOM_WITH_SELECT_INTERACTION);
	GinkgoInteractorStyleImage2D* pInteractor = GinkgoInteractorStyleImage2D::SafeDownCast(ViewImage2D->GetInteractorStyle().GetPointer());
	if (pInteractor != NULL) {
		pInteractor->SetPreviewMode(true);
	}
	wxIcon icono;
	icono.CopyFromBitmap(GinkgoResourcesManager::History::GetIcoHistorialOpen());
	this->SetIcon(icono);

	m_pStatusBar = new GNC::GUI::StatusBarProgreso(this, m_pPanelPreviews, false);
	SetStatusBar(m_pStatusBar);

	wxBitmap bmp;
	
	bmp = GinkgoResourcesManager::History::GetIcoEstudio();
	if (bmp.IsOk()) {
		m_pImageList->Add(bmp);
	}
	bmp = GinkgoResourcesManager::History::GetIcoSerie();
	if (bmp.IsOk()) {
		m_pImageList->Add(bmp);
	}
	bmp = GinkgoResourcesManager::History::GetIcoHombre();
	if (bmp.IsOk()) {
		m_pImageList->Add(bmp);
	}
	bmp = GinkgoResourcesManager::History::GetIcoMujer();
	if (bmp.IsOk()) {
		m_pImageList->Add(bmp);
	}
	bmp = GinkgoResourcesManager::History::GetIcoOtro();
	if (bmp.IsOk()) {
		m_pImageList->Add(bmp);
	}
	m_pTreeListResults->SetImageList(m_pImageList);	

	//modalities
	{
		const int MaxModalityNumber=20; // Modificar la constante si se añaden o quitan códigos de modalidad
		std::string modalidades[MaxModalityNumber] = {"CR","CT","DR","DX","IO","MG","MR","NM","OT","PT","RF","RG","SC","OCT","US","XA","XC","ES","ECG","HD"};
		for(int i = 0; i<MaxModalityNumber; i++) {
			wxCheckBox* pCheckBox = new wxCheckBox( m_pAdvancedSearchPanel, wxID_ANY, wxString::FromUTF8(modalidades[i].c_str()), wxDefaultPosition, wxDefaultSize, 0 );
			m_pModalitySizer->Add( pCheckBox, 0, wxALL, 2 );
			m_modalitiesList.push_back(pCheckBox);
			pCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( HistoryPanel3::OnSearchChange ), NULL, this );
		}
	}
	m_pTableModel = new TableDataModel(m_pTreeListResults);

	m_pToolBar = new HistoryToolMenu(this);
	m_pSizerToolBar->Insert(0, m_pToolBar, 0, wxEXPAND, 0);
	m_pToolBar->Show();

	m_pThumbnails->SetThumbnailImageSize(wxSize(SIZE_THUMBNAILS, SIZE_THUMBNAILS));
	m_pThumbnails->SetBackgroundColour(wxColour(100,100,100));
	m_pThumbnails->SetThumbnailMargin(0);
	m_pThumbnails->SetThumbnailTextHeight(0);

	m_pTreeListResults->SetMainColumn(0);
/*		m_pTreeListResultados->Connect(wxEVT_COMMAND_TREE_SEL_CHANGED, wxTreeEventHandler( DialogoAdquisicion::OnTreeSelChanged ), NULL, this);*/
	m_pTreeListResults->Connect(wxEVT_COMMAND_TREE_ITEM_MENU, wxTreeEventHandler( HistoryPanel3::OnTreeItemMenu ), NULL, this);
	m_pTreeListResults->Connect(wxEVT_COMMAND_TREE_ITEM_EXPANDED, wxTreeEventHandler( HistoryPanel3::OnTreeItemExpanded ), NULL, this);
	m_pTreeListResults->Connect(wxEVT_COMMAND_TREE_ITEM_ACTIVATED, wxTreeEventHandler( HistoryPanel3::OnTreeItemActivated ), NULL, this);
	m_pTreeListResults->Connect(wxEVT_COMMAND_TREE_SEL_CHANGED, wxTreeEventHandler( HistoryPanel3::OnTreeSelChanged ), NULL, this);
	m_pTreeListResults->Connect(wxEVT_COMMAND_TREE_KEY_DOWN, wxTreeEventHandler( HistoryPanel3::OnTreeKeyDown), NULL, this);
/*	m_pTreeListResultados->Connect(wxEVT_COMMAND_TREE_BEGIN_DRAG, wxTreeEventHandler( DialogoAdquisicion::OnTreeBeginDrag ), NULL, this);*/
	m_pTreeListResults->Connect(wxEVT_COMMAND_LIST_COL_CLICK, wxListEventHandler( HistoryPanel3::OnTreeClickColumnHeader), NULL, this);
	m_pThumbnails->Connect(wxEVT_COMMAND_THUMBNAIL_ITEM_SELECTED,wxThumbnailHandler(HistoryPanel3::OnThumbnailSelected),NULL,this);
	m_pThumbnails->Connect(wxEVT_COMMAND_THUMBNAIL_LEFT_DCLICK,wxThumbnailHandler(HistoryPanel3::OnThumbnailDClick),NULL,this);
	m_pThumbnails->Connect(wxEVT_COMMAND_THUMBNAIL_RIGHT_CLICK, wxThumbnailHandler(HistoryPanel3::OnThumbnailRClick), NULL, this);
	
	m_pPatientCombo->Connect( wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler( HistoryPanel3::OnSearchChange ), NULL, this );
	m_pPatientCombo->Connect( wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler( HistoryPanel3::OnSearchChange ), NULL, this );

	GNC::GCS::ControladorEventos::Instance()->Registrar(this, GNC::GCS::Events::EventoProgresoComando());
	m_pSearchPanel->Layout();
	Layout();
	
	SetDropTarget(new GNC::GUI::DropTargetMainWindow());
}

GNC::GUI::HistoryPanel3::~HistoryPanel3()
{
	delete m_pImageList;
	delete m_pTimerReload;
	if (m_pTableModel != NULL) {
		delete m_pTableModel;
	}
	GNC::GCS::Permisos::EstadoPermiso estado = GNC::GCS::IControladorPermisos::Instance()->Get("core.restrictions", "anonymous_history");
	if (estado) {
		GNC::GCS::HistoryController::Instance()->EmptyHistory(true);
	}

	ViewImage2D->Detach();
	//necesario para que no haga un doble delete
	ViewInteractor2D->Delete();
	ViewInteractor2D->Reparent(NULL);		
}

void GNC::GUI::HistoryPanel3::ReloadHistory()
{
	ReloadCombos(false);
	RefreshSearch(true);
}

void GNC::GUI::HistoryPanel3::ReloadToolBar()
{
	m_pToolBar->Reload();
	//reload menus..
	while (m_pMenuBar->GetMenuCount() > 0)
		delete m_pMenuBar->Remove(0);
	wxMenu* pMenuAcquire = new wxMenu();
	GNC::HistoryToolsController::Instance()->AppendsToolInMenu(this, pMenuAcquire, GNC::GCS::IHistoryTool::TFamily_Open);
	if (pMenuAcquire->GetMenuItemCount() > 0 && !pMenuAcquire->GetMenuItems().back()->IsSeparator()) {
		pMenuAcquire->AppendSeparator();
	}
	GNC::HistoryToolsController::Instance()->AppendsToolInMenu(this, pMenuAcquire, GNC::GCS::IHistoryTool::TFamily_Q_R);
	if (pMenuAcquire->GetMenuItemCount() >0) {
		m_pMenuBar->Append( pMenuAcquire, _("Acquire") );
	} else {
		delete pMenuAcquire;
	}

	wxMenu* pMenuDicomize = new wxMenu();
	GNC::HistoryToolsController::Instance()->AppendsToolInMenu(this, pMenuDicomize, GNC::GCS::IHistoryTool::TFamily_Dicomize);
	if (pMenuDicomize->GetMenuItemCount() >0) {
		m_pMenuBar->Append( pMenuDicomize, _("Dicomize") );
	} else {
		delete pMenuDicomize;
	}

	wxMenu* pMenuTools = new wxMenu();
	GNC::HistoryToolsController::Instance()->AppendsToolInMenu(this, pMenuTools, GNC::GCS::IHistoryTool::TFamily_Delete);
	if (pMenuTools->GetMenuItemCount() > 0 && !pMenuTools->GetMenuItems().back()->IsSeparator()) {
		pMenuTools->AppendSeparator();
	}
	GNC::HistoryToolsController::Instance()->AppendsToolInMenu(this, pMenuTools, GNC::GCS::IHistoryTool::TFamily_ShowMetadata);
	if (pMenuTools->GetMenuItemCount() >0) {
		m_pMenuBar->Append( pMenuTools, _("Tools") );
	} else {
		delete pMenuTools;
	}

	wxMenu* pMenuExport = new wxMenu();
	GNC::HistoryToolsController::Instance()->AppendsToolInMenu(this, pMenuExport, GNC::GCS::IHistoryTool::TFamily_Send);
	if (pMenuExport->GetMenuItemCount() > 0 && !pMenuExport->GetMenuItems().back()->IsSeparator()) {
		pMenuExport->AppendSeparator();
	}
	GNC::HistoryToolsController::Instance()->AppendsToolInMenu(this, pMenuExport, GNC::GCS::IHistoryTool::TFamily_Export);
	if (pMenuExport->GetMenuItemCount() >0) {
		m_pMenuBar->Append( pMenuExport, _("Export") );
	} else {
		delete pMenuExport;
	}
}

void GNC::GUI::HistoryPanel3::ReloadCombos(bool checkPurgue)
{
	if (checkPurgue) {
		//si es preciso limpiar historial...
		GNC::GCS::Permisos::EstadoPermiso estado = GNC::GCS::IControladorPermisos::Instance()->Get("core.restrictions", "anonymous_history");
		if (estado) {
			GNC::GCS::HistoryController::Instance()->EmptyHistory(true);
		}
	}

	//combo box pacientes
	GNC::GCS::HistoryController::PatientModelList listaPacientes;
	GNC::GCS::HistoryController::Instance()->GetAllPatients(listaPacientes);

	m_pPatientCombo->Clear();

	m_pPatientCombo->Append(_("All patients"), GinkgoResourcesManager::History::GetIcoAllPatients());

	RefreshPatientFilter();
	if (!m_patientFilter.IsEnabled()) {
		m_pPatientCombo->Select(0);
	}

	for (GNC::GCS::HistoryController::PatientModelList::iterator it = listaPacientes.begin(); it != listaPacientes.end(); ++it) {
		std::ostringstream ostr;
		ostr << (*it).name << " (" << (*it).id << ")";

		wxPatientData* pData = new wxPatientData((*it));
		int indice = -1;
		if ((*it).sex == 'M'){
			indice = m_pPatientCombo->Append(wxString::FromUTF8(ostr.str().c_str()), GinkgoResourcesManager::History::GetIcoHombre(), pData);
		}else if((*it).sex =='F'){
			indice = m_pPatientCombo->Append(wxString::FromUTF8(ostr.str().c_str()), GinkgoResourcesManager::History::GetIcoMujer(), pData);
		}else{
			indice = m_pPatientCombo->Append(wxString::FromUTF8(ostr.str().c_str()), GinkgoResourcesManager::History::GetIcoOtro(), pData);
		}

		if (m_patientFilter.IsEnabled() && (*it).id == m_patientFilter.GetPatientId()) {
			m_pPatientCombo->Select(indice);
		}
	}
	if (m_pPatientCombo->GetSelection() <0) {
		m_pPatientCombo->Select(0);
	}


	if (checkPurgue) {
		//load filter state
		std::string strTmp;
		if (GNC::GCS::ConfigurationController::Instance()->readStringUser("/GinkgoCore/History", "PatientComboValue", strTmp)) {
			int pos = m_pPatientCombo->FindString(wxString::FromUTF8(strTmp.c_str()));
			if (pos >= 0) {
				m_pPatientCombo->Select(pos);
			}
		}
	/*	TODO SAVE/LOAD SETTINGS
	if (GNC::GCS::ConfigurationController::Instance()->readStringUser("/GinkgoCore/History", "ModalityValue", strTmp)) {
			int pos = m_pComboModalidad->FindString(wxString::FromUTF8(strTmp.c_str()));
			if (pos >= 0) {
				m_pComboModalidad->Select(pos);
			}
		}
		int intTmp;
		if (GNC::GCS::ConfigurationController::Instance()->readIntUser("/GinkgoCore/History", "DateChoice", intTmp)) {
			m_pComboDate->Select(intTmp);
		}
		if (m_pComboDate->GetValue() == _("Between:")) {
			if (GNC::GCS::ConfigurationController::Instance()->readStringUser("/GinkgoCore/History", "DateFrom", strTmp)) {
				wxDateTime from;
				from.ParseFormat(wxString::FromUTF8(strTmp.c_str()), wxT("%Y/%m/%d"),wxDateTime::Now());
				m_pDatePickerFrom->SetValue(from);
			}
			if (GNC::GCS::ConfigurationController::Instance()->readStringUser("/GinkgoCore/History", "DateTo", strTmp)) {
				wxDateTime to;
				to.ParseFormat(wxString::FromUTF8(strTmp.c_str()), wxT("%Y/%m/%d"),wxDateTime::Now());
				m_pDatePickerTo->SetValue(to);
			}
		}*/
	}
}

void GNC::GUI::HistoryPanel3::RefreshSearch(bool force)
{
	RefreshPatientFilter();
	RefreshModalityFilter();
	RefreshDateFilter();

	//se eliminan todos los estudios que no están abiertos
	Freeze();
	
	std::list<GNC::GCS::History::IHistoryFilter*> filterList;
	filterList.push_back(&m_modalityFilter);
	filterList.push_back(&m_patientFilter);
	filterList.push_back(&m_dateFilter);

	GNC::GCS::HistoryController::StudyModelList studyList;
	GNC::GCS::HistoryController::Instance()->GetStudies(filterList, studyList);
	{
		wxWindowDisabler disableAll;
		Freeze();
		ShowPreviewPanel(false);
		m_pThumbnails->Clear();
		m_pTableModel->ReloadTree(studyList, force);	
		int numberImages = 0;
		for (GNC::GCS::HistoryController::StudyModelList::iterator it = studyList.begin(); it != studyList.end(); ++it) {
			numberImages += (*it).num_instances;
		}
		m_pResultTitle->SetLabel(_("Results") + wxString::Format(_(" (%d images)"), numberImages));
		Thaw();
	}

	Thaw();
}

void GNC::GUI::HistoryPanel3::checkPendingTasks()
{
	//throw pending commands...
	if (GNC::GCS::HistoryController::Instance()->IsPendingTasks()) {
		if (wxMessageBox(_("There are pending tasks, do you want to execute them?"), _("Pending tasks"), wxYES_NO , GNC::Entorno::Instance()->GetVentanaRaiz()) == wxYES)
		{
			std::list<GNC::GCS::HistoryController::TaskModel> tasks;
			GNC::GCS::HistoryController::Instance()->GetPendingTasks(tasks);
			launchTasks(tasks);
			RefreshSearch();
		}
	}
}

void GNC::GUI::HistoryPanel3::GetSelectedSeriesPk(std::list<long>& listOfPks)
{
	std::set<long> setOfPks;
	m_pTableModel->GetSeriesPkSelected(setOfPks);
	for (std::set<long>::iterator it = setOfPks.begin(); it != setOfPks.end(); ++it) {
		listOfPks.push_back((*it));
	}
}


void GNC::GUI::HistoryPanel3::RefreshPatientFilter()
{
	if (m_pPatientCombo->GetSelection() > 0) {
		wxPatientData* pPatient = static_cast<wxPatientData*>( m_pPatientCombo->GetClientObject(m_pPatientCombo->GetSelection()) );
		if (pPatient != NULL) {
			m_patientFilter.Enable(true);
			m_patientFilter.SetPatientId(pPatient->m_PatientModel.id);
			GNC::GCS::ConfigurationController::Instance()->writeStringUser("/GinkgoCore/History", "PatientComboValue", pPatient->m_PatientModel.id);
		} else {
			m_patientFilter.Enable(false);
		}
	} else {
		m_patientFilter.Enable(false);
	}
}
void GNC::GUI::HistoryPanel3::RefreshModalityFilter()
{
	std::list<std::string> modalities;
	for (TModalitiesVector::iterator it = m_modalitiesList.begin(); it != m_modalitiesList.end(); ++it) {
		if ((*it)->IsChecked()) {
			std::string modality((*it)->GetLabel().ToUTF8());
			modalities.push_back(modality);
		}
	}
	m_modalityFilter.Enable(!modalities.empty());
	m_modalityFilter.SetModalities(modalities);
}

/** Advanced Search button toggled **/
void GNC::GUI::HistoryPanel3::OnAdvancedSearchToggled( wxCommandEvent& event )
{
	Freeze();
	if (event.IsChecked()) {
		m_pAdvancedSearchPanel->Show();
	}
	else {
		m_pAdvancedSearchPanel->Hide();	
	}
	Layout();
	Thaw();
	
}

void GNC::GUI::HistoryPanel3::RefreshDateFilter()
{
	
	wxDateTime fromDate, toDate;
	if (m_pBetween->GetValue()){
		if(m_pTextControlFechaDesde->GetValue().IsValid()){
			fromDate =  m_pTextControlFechaDesde->GetValue();
		}
		if(m_pTextControlFechaHasta->GetValue().IsValid()){
			toDate =  m_pTextControlFechaHasta->GetValue();
		}
	} else if (m_pToday->GetValue() || m_pTodayAM->GetValue() || m_pTodayPM->GetValue()) {
		fromDate = toDate = wxDateTime::Now();
		if (m_pTodayAM->GetValue()) {
			fromDate.SetHour(0);
			fromDate.SetMinute(0);
			fromDate.SetSecond(0);
			toDate.SetHour(11);
			toDate.SetMinute(59);
			toDate.SetSecond(59);
		} else if (m_pTodayPM->GetValue()) {
			fromDate.SetHour(12);
			fromDate.SetMinute(0);
			fromDate.SetSecond(0);
			toDate.SetHour(23);
			toDate.SetMinute(59);
			toDate.SetSecond(59);
		} else  {
			fromDate.SetHour(0);
			fromDate.SetMinute(0);
			fromDate.SetSecond(0);
			toDate.SetHour(23);
			toDate.SetMinute(59);
			toDate.SetSecond(59);
		}
	} else if (m_pYesterday->GetValue()) {
		fromDate = wxDateTime::Now().Add(wxDateSpan(0,0,0,-1));
	} else if (m_pLastWeek->GetValue()) {
		fromDate = wxDateTime::Now().Add(wxDateSpan(0,0,-1,0));
	} else if (m_pLastMonth->GetValue()) {
		fromDate = wxDateTime::Now().Add(wxDateSpan(0,-1,0,0));
	} else if (m_pLastThreeMonths->GetValue()) {
		fromDate = wxDateTime::Now().Add(wxDateSpan(0,-3,0,0));
	}
	m_dateFilter.SetDates(fromDate, toDate);
	m_dateFilter.Enable(fromDate.IsValid() || toDate.IsValid());
}

void GNC::GUI::HistoryPanel3::OnClose(wxCloseEvent &event)
{
	event.Skip(false);
	Hide();
}

void GNC::GUI::HistoryPanel3::OnSearchChange( wxCommandEvent& )
{
	m_pTimerReload->Stop();
	m_pTimerReload->Start(500,true);
}

void GNC::GUI::HistoryPanel3::OnDateChanged( wxDateEvent& /*event*/ )
{
	m_pBetween->SetValue(true);
	m_pTimerReload->Stop();
	m_pTimerReload->Start(500,true);
}

void GNC::GUI::HistoryPanel3::OnTreeItemExpanded(wxTreeEvent& event)
{
	wxTreeItemId item = event.GetItem();
	if(item && item.IsOk()){
		long pk_study;
		m_pTreeListResults->GetItemText(item, COL_PK).ToLong(&pk_study);
		m_pTableModel->ExpandStudy(pk_study);

		event.Skip(false);
	} else {
		event.Skip(true);
	}
}
void GNC::GUI::HistoryPanel3::ShowPreviewPanel(bool visible)
{
	if (ViewInteractor2D->IsShown() != visible) {
		ViewInteractor2D->Show(visible);
		m_pHideInteractorPanel->Show(!visible);
		m_pPanelPreviews->Layout();
	}
}

void GNC::GUI::HistoryPanel3::OnTreeItemActivated(wxTreeEvent& event)
{
	wxTreeItemId item = event.GetItem();
	if (item && item.IsOk()) {
		//series activated...
		long pk;
		m_pTreeListResults->GetItemText(item, COL_PK).ToLong(&pk);		
		if (m_pTreeListResults->GetItemParent(item) != m_pTreeListResults->GetRootItem()){
			OpenSeriesOrStudy(pk, true);
		} else {
			OpenSeriesOrStudy(pk, false);
		}
		event.Skip(false);
	}
}

void GNC::GUI::HistoryPanel3::OnTreeItemMenu(wxTreeEvent& event)
{
	wxTreeItemId item = event.GetItem();
	if(item && item.IsOk()) {
		wxMenu menu;
		int idMenuItem = 1;

		wxArrayTreeItemIds dummyArr;
		if (m_pTreeListResults->GetSelections(dummyArr) == 1) {
			if (m_pTreeListResults->GetItemParent(item) == m_pTreeListResults->GetRootItem()) {
				//study menu...
				long pkSeries;
				m_pTreeListResults->GetItemText(item, COL_PK).ToLong(&pkSeries);
				menu.Append(idMenuItem, _("Open study"));
				menu.Connect(idMenuItem++,wxEVT_COMMAND_MENU_SELECTED,wxCommandEventHandler( HistoryPanel3::OnOpenMenu),NULL,this);
				menu.Append(idMenuItem, _("Open study with .."));
				menu.Connect(idMenuItem++,wxEVT_COMMAND_MENU_SELECTED,wxCommandEventHandler( HistoryPanel3::OnOpenWithMenu),NULL,this);
			} else {
				//series menu...
				long pkSeries;
				m_pTreeListResults->GetItemText(item, COL_PK).ToLong(&pkSeries);
				menu.Append(idMenuItem, _("Open Series"));
				menu.Connect(idMenuItem++,wxEVT_COMMAND_MENU_SELECTED,wxCommandEventHandler( HistoryPanel3::OnOpenMenu),NULL,this);
				menu.Append(idMenuItem, _("Open Series with .."));
				menu.Connect(idMenuItem++,wxEVT_COMMAND_MENU_SELECTED,wxCommandEventHandler( HistoryPanel3::OnOpenWithMenu),NULL,this);
			} // SERIES MENU
		} else {
			//more than one item selected...
		}

		if (dummyArr.size() > 0) {
			if (menu.GetMenuItemCount() > 0 && !menu.GetMenuItems().back()->IsSeparator()) {
				menu.AppendSeparator();
			}
			GNC::HistoryToolsController::Instance()->AppendsToolInMenu(&menu, &menu, GNC::GCS::IHistoryTool::TFamily_Open);
			if (menu.GetMenuItemCount() > 0 && !menu.GetMenuItems().back()->IsSeparator()) {
				menu.AppendSeparator();
			}
			GNC::HistoryToolsController::Instance()->AppendsToolInMenu(&menu, &menu, GNC::GCS::IHistoryTool::TFamily_Q_R);
			if (menu.GetMenuItemCount() > 0 && !menu.GetMenuItems().back()->IsSeparator()) {
				menu.AppendSeparator();
			}
			GNC::HistoryToolsController::Instance()->AppendsToolInMenu(&menu, &menu, GNC::GCS::IHistoryTool::TFamily_Dicomize);
			if (menu.GetMenuItemCount() > 0 && !menu.GetMenuItems().back()->IsSeparator()) {
				menu.AppendSeparator();
			}
			if (!GNC::GCS::HistoryController::Instance()->IsReadOnly()) {
				wxMenuItem* pMenuEliminar = new wxMenuItem(&menu, idMenuItem, wxString( _("&Delete from history") ), _("Delete"), wxITEM_NORMAL );
				menu.Connect(idMenuItem++,wxEVT_COMMAND_MENU_SELECTED,wxCommandEventHandler( HistoryPanel3::OnDelete),NULL,this);
				#ifdef __WXMSW__
				pMenuEliminar->SetBitmaps(GinkgoResourcesManager::MenuIcons::GetIcoEliminar());
				#else
				pMenuEliminar->SetBitmap(GinkgoResourcesManager::MenuIcons::GetIcoEliminar());
				#endif
				menu.Append(pMenuEliminar);

				wxMenuItem* pMenuLimpiar = new wxMenuItem(&menu, idMenuItem, wxString( _("&Clear history") ), _("Delete"), wxITEM_NORMAL );
				menu.Connect(idMenuItem++,wxEVT_COMMAND_MENU_SELECTED,wxCommandEventHandler( HistoryPanel3::OnClearHistory),NULL,this);
				#ifdef __WXMSW__
				pMenuLimpiar->SetBitmaps(GinkgoResourcesManager::History::GetIcoCleanAll());
				#else
				pMenuLimpiar->SetBitmap(GinkgoResourcesManager::History::GetIcoCleanAll());
				#endif
				menu.Append(pMenuLimpiar);
				GNC::HistoryToolsController::Instance()->AppendsToolInMenu(&menu, &menu, GNC::GCS::IHistoryTool::TFamily_Delete);
				if (menu.GetMenuItemCount() > 0 && !menu.GetMenuItems().back()->IsSeparator()) {
					menu.AppendSeparator();
				}
			}
			GNC::HistoryToolsController::Instance()->AppendsToolInMenu(&menu, &menu, GNC::GCS::IHistoryTool::TFamily_ShowMetadata);
			if (menu.GetMenuItemCount() > 0 && !menu.GetMenuItems().back()->IsSeparator()) {
				menu.AppendSeparator();
			}
			GNC::HistoryToolsController::Instance()->AppendsToolInMenu(&menu, &menu, GNC::GCS::IHistoryTool::TFamily_Send);
			if (menu.GetMenuItemCount() > 0 && !menu.GetMenuItems().back()->IsSeparator()) {
				menu.AppendSeparator();
			}
			GNC::HistoryToolsController::Instance()->AppendsToolInMenu(&menu, &menu, GNC::GCS::IHistoryTool::TFamily_Export);
			
			//task management
			if (menu.GetMenuItemCount() > 0 && !menu.GetMenuItems().back()->IsSeparator()) {
				menu.AppendSeparator();
			}
			bool enablePending = m_pTreeListResults->GetItemText(item, COL_PENDING_TASKS) != wxT("0");
			menu.Append(idMenuItem, _("Restart pending tasks"));
			menu.Enable(idMenuItem, enablePending);
			menu.Connect(idMenuItem++,wxEVT_COMMAND_MENU_SELECTED,wxCommandEventHandler( HistoryPanel3::OnRestartPending),NULL,this);
			menu.Append(idMenuItem, _("Remove pending tasks"));
			menu.Enable(idMenuItem, enablePending);
			menu.Connect(idMenuItem++,wxEVT_COMMAND_MENU_SELECTED,wxCommandEventHandler( HistoryPanel3::OnDeletePending),NULL,this);				
			menu.Append(idMenuItem, _("Advanced tasks management..."));
			menu.Connect(idMenuItem++,wxEVT_COMMAND_MENU_SELECTED,wxCommandEventHandler( HistoryPanel3::OnAdvancedTasksEdition),NULL,this);
		}

		if (menu.GetMenuItemCount() > 0) {
			this->PopupMenu(&menu);
		}

		event.Skip(false);
	} else {
		event.Skip(true);
	}
}

void GNC::GUI::HistoryPanel3::OnTreeSelChanged(wxTreeEvent& event)
{
	wxTreeItemId item = event.GetItem();
	if(item.IsOk() && event.GetOldItem() != event.GetItem() && m_pTreeListResults->IsSelected(event.GetItem())){
		ShowPreviewPanel(false);
		wxTreeItemId parentId = m_pTreeListResults->GetItemParent(item);
		if (parentId == m_pTreeListResults->GetRootItem()) {
			LoadPreviewsFromStudy(item);
		} else {
			LoadPreviewsFromSeries(item);
		}
	}

	event.Skip(true);
}

void GNC::GUI::HistoryPanel3::OnTreeKeyDown(wxTreeEvent& event)
{
	if (event.GetKeyCode() == WXK_DELETE) {
		RemoveSelected();
		event.Veto();
	} else {
		event.Skip(true);
	}
}

void GNC::GUI::HistoryPanel3::OnTreeClickColumnHeader(wxListEvent& event)
{
	int column = event.GetColumn();
	m_pChoiceColumns->SetSelection(column);
	m_pTableModel->ChangeSortCriteria(column);
}

void GNC::GUI::HistoryPanel3::OnThumbnailSelected(wxThumbnailEvent& /*evt*/)
{
	int selected = m_pThumbnails->GetSelection();
	if (selected >= 0) {
		try {
			ShowPreviewPanel(true);
			wxHistoryImageThumbnailItem* pItem = static_cast<wxHistoryImageThumbnailItem*>( m_pThumbnails->GetItem(selected) );
			long file_pk;
			pItem->GetFilename().ToLong(&file_pk);
			GNC::GCS::HistoryController::FileModel selectedFile = GNC::GCS::HistoryController::Instance()->GetFileModel(file_pk);
			if (m_currentPreviewedFile != selectedFile.real_path) 
			{
				m_currentPreviewedFile = selectedFile.real_path;
				Loader->SetInput(selectedFile.real_path);
				Loader->UpdateInformation();
				Loader->SetOutputOrigin(selectedFile.image_position);
				double spacing[3] = {1.0,1.0,1.0};
				sscanf( selectedFile.spacing.c_str(), "%lf\\%lf", &spacing[0], &spacing[1]);
				Loader->SetOutputSpacing(spacing);
				if (ViewImage2D->GetNumberOfComponents() == 1) {
					double window, level;
					if (Loader->GetDefaultWindowLevel(window,level) && window != 0.0) {
						ViewImage2D->SetWindow(window);
						ViewImage2D->SetLevel(level);
					} else {
						ViewImage2D->SetAutoDefaultWindowLevel();
					}
				}
				ViewImage2D->SetupPipeline(true);
				ViewImage2D->ResetZoom(false, 0);
				ViewImage2D->UpdateOrientation();
			}
			ViewInteractor2D->Render();
		}
		catch( GNC::GCS::VistaException& ex )
		{
			ShowPreviewPanel(false);
			std::string error = "Exception loading:" + ex.GetCause();
			LOG_ERROR("History3", error);
		}
		catch (GNC::GCS::ControladorCargaException& ex)
		{
			ShowPreviewPanel(false);
			std::string error = "Exception loading:" + ex.GetCause();
			LOG_ERROR("History3", error);			
		}
		catch (...)
		{
			ShowPreviewPanel(false);
			std::string error = "Unknown exception loading";
			LOG_ERROR("History3", error);
		}
	}	
}

void GNC::GUI::HistoryPanel3::OnThumbnailDClick(wxThumbnailEvent& /*evt*/)
{
	int selected = m_pThumbnails->GetSelection();
	if (selected >= 0) {
		wxHistoryImageThumbnailItem* pItem = static_cast<wxHistoryImageThumbnailItem*>(m_pThumbnails->GetItem(selected));
		if (pItem->GetType() == wxHistoryImageThumbnailItem::TI_Series) {
			//open series
			OpenSeriesOrStudy(pItem->GetSeriesPk(), true);
		} else {
			//open image
			GNC::GCS::IVista* pView = GetViewFromSeries(pItem->GetSeriesPk());
			if (pView != NULL) {
				GNC::Entorno::Instance()->GetVentanaPrincipal()->ForzarCambioVista(pView);
				std::string pathOfFile(TOPATH(pItem->GetFilename()));
				pView->ActivarRuta(pItem->GetFilePk());				
			} else  {
				OpenSeriesOrStudy(pItem->GetSeriesPk(), true);
			}
		}
	}
}	
void GNC::GUI::HistoryPanel3::OnThumbnailRClick(wxThumbnailEvent& evt)
{
	wxHistoryImageThumbnailItem* pItem = static_cast<wxHistoryImageThumbnailItem*>(m_pThumbnails->GetItem(evt.GetIndex()));
	if (pItem != NULL) {
		wxPopUpMenuThumbnails menu(this, pItem->GetSeriesPk());
		m_pThumbnails->PopupMenu(&menu);
	} else {
		wxPopUpMenuThumbnails menu(this, -1);
		m_pThumbnails->PopupMenu(&menu);
	}
}

void GNC::GUI::HistoryPanel3::OnSortColumnChanged(wxCommandEvent& )
{
	m_pTableModel->ChangeSortCriteria(m_pChoiceColumns->GetSelection());
}

void GNC::GUI::HistoryPanel3::OnOpenMenu(wxCommandEvent& /*event*/)
{
	wxTreeItemId item = m_pTreeListResults->GetSelection();
	if (item.IsOk() && m_pTreeListResults->GetItemParent(item) != m_pTreeListResults->GetRootItem()) {
		long pk;
		m_pTreeListResults->GetItemText(item, COL_PK).ToLong(&pk);
		OpenSeriesOrStudy(pk, true);
	} else if (item.IsOk() && m_pTreeListResults->GetItemParent(item) == m_pTreeListResults->GetRootItem()) {
		long pk;
		m_pTreeListResults->GetItemText(item, COL_PK).ToLong(&pk);
		OpenSeriesOrStudy(pk, false);
	}
}

void GNC::GUI::HistoryPanel3::OnOpenWithMenu(wxCommandEvent& /*event*/)
{
	wxTreeItemId item = m_pTreeListResults->GetSelection();
	if (item.IsOk() && m_pTreeListResults->GetItemParent(item) != m_pTreeListResults->GetRootItem()) {
		long pk;
		m_pTreeListResults->GetItemText(item, COL_PK).ToLong(&pk);
		OpenSeriesOrStudyWith(pk, true);
	} else if (item.IsOk() && m_pTreeListResults->GetItemParent(item) == m_pTreeListResults->GetRootItem()) {
		long pk;
		m_pTreeListResults->GetItemText(item, COL_PK).ToLong(&pk);
		OpenSeriesOrStudyWith(pk, false);
	}
}

void GNC::GUI::HistoryPanel3::OnDelete(wxCommandEvent& /*event*/)
{
	RemoveSelected();
}

void GNC::GUI::HistoryPanel3::OnClearHistory(wxCommandEvent& /*event*/)
{
	ClearHistory();
}

void GNC::GUI::HistoryPanel3::OnRestartPending(wxCommandEvent& /*event*/)
{
	RestartPendingSelected();
}

void GNC::GUI::HistoryPanel3::OnDeletePending(wxCommandEvent& /*event*/)
{
	DeletePendingSelected();
}

void GNC::GUI::HistoryPanel3::OnAdvancedTasksEdition(wxCommandEvent& /*event*/)
{
	AdvancedTasksEdition();
}


GNC::GCS::IVista* GNC::GUI::HistoryPanel3::GetViewFromSeries(long pk_series)
{
	GNC::GCS::ControladorVistas::TipoListaVistas viewList = GNC::Entorno::Instance()->GetControladorVistas()->GetVistas();
	for (GNC::GCS::ControladorVistas::TipoListaVistas::iterator itViews = viewList.begin(); itViews != viewList.end(); ++itViews) {
		if ((*itViews)->GetEstudio().IsValid()) {
			for(std::vector<long>::const_iterator itUID = (*itViews)->GetEstudio()->OpenedSeries.begin(); itUID != (*itViews)->GetEstudio()->OpenedSeries.end(); ++itUID)
			{
				if (pk_series == (*itUID)) {
					return (*itViews);
				}
			}
		}
	}
	return NULL;
}

void GNC::GUI::HistoryPanel3::OpenSeriesOrStudyWith(long pk, bool isSeries)
{
	GNC::GCS::Permisos::EstadoPermiso estado = GNC::GCS::IControladorPermisos::Instance()->Get("core.restrictions", "max_tabs");
	if (estado) {
		long maxNumberOfTabs = estado.ObtenerValor<long>();
		if ((int)GNC::Entorno::Instance()->GetControladorVistas()->GetVistas().size() >= maxNumberOfTabs) {
				wxMessageBox(_("You have reached maximum number of opened tabs, close some tabs and try it again"), _("Info"),
					wxOK | wxICON_INFORMATION, GNC::Entorno::Instance()->GetVentanaRaiz());
				return;					
		}
	}
	//max

	GNC::GCS::IHistoryController::SeriesModelList seriesModelList;
	if (isSeries) {
		GNC::GCS::IHistoryController::SeriesModel seriesModel = GNC::GCS::HistoryController::Instance()->GetSeriesModel(pk);
		seriesModelList.push_back(seriesModel);
	} else {
		GNC::GCS::HistoryController::Instance()->GetSeriesFromStudy(pk, seriesModelList);	
	}

	OpenWithDialog::ListaModalidades listaModalidades;
	for (GNC::GCS::IHistoryController::SeriesModelList::iterator itSeries = seriesModelList.begin(); itSeries != seriesModelList.end(); ++itSeries) {
		for (GNC::GCS::HistoryController::StringList::iterator it = (*itSeries).tsuids.begin(); it != (*itSeries).tsuids.end(); ++it) {
			listaModalidades.push_back(std::pair<std::string,std::string>((*itSeries).series_modality, (*it)));
		}
	}

	OpenWithDialog dialogoAbrir(this, listaModalidades);
	int answer = dialogoAbrir.ShowModal();
	if (answer == wxID_OK) {
		OpenSeries(seriesModelList, dialogoAbrir.GetModuloSeleccionado(), dialogoAbrir.GetModoSeleccionado()->GetId());
	}
}

void GNC::GUI::HistoryPanel3::OpenSeriesOrStudy(long pk, bool isSeries, bool force)
{
	//show current...
	bool seriesIsAlreadyOpen = false;
	GNC::GCS::IHistoryController::SeriesModelList seriesModelList;
	{
		GNC::GCS::IVista* pView = NULL;
		if (isSeries) {
			pView = GetViewFromSeries(pk);
			GNC::GCS::IHistoryController::SeriesModel seriesModel = GNC::GCS::HistoryController::Instance()->GetSeriesModel(pk);
			seriesModelList.push_back(seriesModel);
		} else {
			GNC::GCS::HistoryController::Instance()->GetSeriesFromStudy(pk, seriesModelList);			
			for (GNC::GCS::IHistoryController::SeriesModelList::const_iterator it = seriesModelList.begin(); it != seriesModelList.end(); ++it) {
				pView = GetViewFromSeries((*it).pk);
				if (pView != NULL) {
					break;
				}
			}
		}
		if (seriesModelList.empty()) {
			LOG_WARN("HistoryPanel", "trying to open a series or a study that has been deleted");
			return;
		}
		
		if (pView != NULL) {
			GNC::Entorno::Instance()->GetVentanaPrincipal()->ForzarCambioVista(pView);
			GNC::GCS::HistoryController::FileModel fileModel = GNC::GCS::HistoryController::Instance()->GetFrameOfReference(seriesModelList.front().pk);
			pView->ActivarRuta(fileModel.pk);
			seriesIsAlreadyOpen = true;
			if (!force) {
				return;
			}
		} 	
	}

	//max number of opened tabs
	GNC::GCS::Permisos::EstadoPermiso estado = GNC::GCS::IControladorPermisos::Instance()->Get("core.restrictions", "max_tabs");
	if (estado) {
		long maxNumberOfTabs = estado.ObtenerValor<long>();
		if ((int)GNC::Entorno::Instance()->GetControladorVistas()->GetVistas().size() >= maxNumberOfTabs) {
				wxMessageBox(_("You have reached maximum number of opened tabs, close some tabs and try it again"), _("Info"),
					wxOK | wxICON_INFORMATION, GNC::Entorno::Instance()->GetVentanaRaiz());
				return;					
		}
	}
	//max

	//select modulo and modo that opens all series of a kind...
	GNC::GCS::IModuleController* pModulo = NULL;
	GNC::GCS::ModoControlador* pModo = NULL;
	GNC::GCS::Ptr<GNC::GCS::HangingProtocol> hp;

	//ma
	if (!isSeries) {
		//it's an study maybe hanging protocols.....
		hp = GNC::GCS::HangingProtocolController::Instance()->GetProtocolForStudy(pk);
		if (hp.IsValid()) 
		{
			pModulo = ControladorExtensiones::Instance()->ObtenerModulo(hp->getModuleSid());
			if (pModulo != NULL) {
				pModo = pModulo->GetModo(hp->getOpeningMode());
			}
		}
	}	

	//first try view that supports this importation uid
	GNC::ControladorExtensiones::ListaModulos listaModulos = ControladorExtensiones::Instance()->Modulos();
	for (GNC::GCS::IHistoryController::SeriesModelList::iterator itSeries = seriesModelList.begin(); itSeries != seriesModelList.end() && pModo == NULL && pModulo == NULL; ++itSeries) 
	{
		for(GNC::ControladorExtensiones::IteradorListaModulos itModulos = listaModulos.begin(); itModulos!= listaModulos.end() && pModo == NULL && pModulo == NULL; ++itModulos)
		{
			for(GNC::GCS::IModuleController::IteradorListaModos itModos = (*itModulos).second->GetListaModos().begin(); itModos != (*itModulos).second->GetListaModos().end(); ++itModos){
				bool supports = true;
				for (GNC::GCS::HistoryController::StringList::iterator itTsyntax = (*itSeries).tsuids.begin(); itTsyntax != (*itSeries).tsuids.end(); ++itTsyntax) {
					supports = supports && (*itModos)->SupportsImportationUID((*itSeries).uid_importer) && (*itModos)->SupportsModalityFile((*itSeries).series_modality,(*itTsyntax));				
				}
				if (supports) {
					pModo = (*itModos);
					pModulo = (*itModulos).second;
					break;
				}
			}
		}

		if(pModo== NULL || pModulo == NULL) {
			//second try by modality
			std::list<GNC::GCS::IModuleController*> listaModulos = ControladorExtensiones::Instance()->ModulosOrdenados();
			for(std::list<GNC::GCS::IModuleController*>::iterator itModulos=listaModulos.begin(); itModulos != listaModulos.end() && pModo == NULL && pModulo == NULL; ++itModulos){
				for(GNC::GCS::IModuleController::IteradorListaModos itModos = (*itModulos)->GetListaModos().begin(); itModos != (*itModulos)->GetListaModos().end(); ++itModos){
					bool supports = true;
					for (GNC::GCS::HistoryController::StringList::iterator itTsyntax = (*itSeries).tsuids.begin(); itTsyntax != (*itSeries).tsuids.end(); ++itTsyntax) {
						supports = supports && (*itModos)->SupportsModalityFile((*itSeries).series_modality,(*itTsyntax));				
					}
					if (supports) {
						pModo = (*itModos);
						pModulo = (*itModulos);
						break;
					}
				}
			}
		}
	}

	if (seriesIsAlreadyOpen) {
		int answer = wxMessageBox(_("The series selected is already open\nDo you want to open it again?"),_("Open again"), wxYES_NO , GNC::Entorno::Instance()->GetVentanaRaiz());
		if (answer != wxYES) {
			return;
		}
	}

	if(pModo != NULL && pModulo != NULL){
		//openinG!!!
		OpenSeries(seriesModelList, pModulo, pModo->GetId(), hp);
		
	}
	else{
		wxString strModalidades=wxT("");
		wxMessageBox(_("Unable to open modality ") + wxString::FromUTF8(seriesModelList.front().series_modality.c_str()) + _( " with transfer syntax ") << wxString::FromUTF8(seriesModelList.front().tsuids.front().c_str()), _("Info"),
				 wxOK | wxICON_INFORMATION, GNC::Entorno::Instance()->GetVentanaRaiz());
	}
}

void GNC::GUI::HistoryPanel3::OpenSeries(GNC::GCS::HistoryController::SeriesModelList& seriesModelList, GNC::GCS::IModuleController* pModulo, int idModo, GNC::GCS::Ptr<GNC::GCS::HangingProtocol> hangingProtocol)
{
	try {
		if (pModulo->OpenView(idModo,seriesModelList, hangingProtocol) == NULL) {
			LOG_ERROR("GNC/AbrirEstudio", "OpenView has returned null");
			if (hangingProtocol.IsValid()) {
				wxMessageBox(_("Error loading study, check hanging protocol settings"), _("Error loading study"),wxICON_ERROR);
			} 
		}
	}
	catch (GNC::GCS::VistaException& ex)
	{
		LOG_ERROR("GNC/AbrirEstudio", (std::string)ex );
		wxMessageBox(wxString::FromUTF8( ((std::string)ex).c_str() ), _("Error loading study"),wxICON_ERROR);
	}
	catch (...)
	{
		LOG_ERROR("GNC/AbrirEstudio", "Error al abrir el estudio: Error interno");
		wxMessageBox(_( "Internal error" ), _("Error loading study"),wxICON_ERROR);
	}
}

void GNC::GUI::HistoryPanel3::ClearHistory()
{
	//if there is any view opened...
	GNC::GCS::ControladorVistas::TipoListaVistas viewList = GNC::Entorno::Instance()->GetControladorVistas()->GetVistas();
	for (GNC::GCS::ControladorVistas::TipoListaVistas::iterator itViews = viewList.begin(); itViews != viewList.end(); ++itViews) {
		if ((*itViews)->GetEstudio().IsValid() && (*itViews)->GetEstudio()->OpenedSeries.size() > 0) {
			wxMessageBox(_("Failed to empty the history, you have to close opened studies"), _("Info"),
				wxOK | wxICON_WARNING);
			return;
		}
	}

	bool eliminar = false;

	ConfirmDeleteDialog dlg(this, _("all files"));
	dlg.ShowModal();
	switch (dlg.GetResultado()) {
		case ConfirmDeleteDialog::TR_Eliminar :
			eliminar = GNC::GCS::HistoryController::Instance()->EmptyHistory(true);
			break;
		case ConfirmDeleteDialog::TR_Cancelar :
			break;
	}
	if(eliminar) {
		RefreshSearch(true);
		ReloadCombos(false);
	}
}

void GNC::GUI::HistoryPanel3::RemoveSelected()
{
	std::set<long> setOfPks;
	m_pTableModel->GetSeriesPkSelected(setOfPks);
	GNC::GCS::HistoryController::IdList pkList;
	pkList.insert(pkList.begin(), setOfPks.begin(), setOfPks.end());

	if (setOfPks.empty()) {
		wxMessageBox(_("Select at least one series"), _("Info"), wxOK | wxICON_WARNING);
		return;
	}
	//if there is any view opened...
	GNC::GCS::ControladorVistas::TipoListaVistas viewList = GNC::Entorno::Instance()->GetControladorVistas()->GetVistas();
	for (GNC::GCS::ControladorVistas::TipoListaVistas::iterator itViews = viewList.begin(); itViews != viewList.end(); ++itViews) {
		if ((*itViews)->GetEstudio().IsValid()) {
			for (std::vector<long>::const_iterator itUIDs = (*itViews)->GetEstudio()->OpenedSeries.begin(); itUIDs != (*itViews)->GetEstudio()->OpenedSeries.end(); ++itUIDs)
			{
				if (setOfPks.find((*itUIDs)) != setOfPks.end()) {
					wxMessageBox(_("You can't remove opened series"), _("Info"),
					wxOK | wxICON_WARNING);
					return;
				}
			}
		}
	}

	//isn't allowed to delete series with pending tasks
	std::list<GNC::GCS::HistoryController::TaskModel> tasks;
	GNC::GCS::HistoryController::Instance()->GetSeriesPendingTasks(pkList, tasks);
	if (!tasks.empty()) {
		wxMessageBox(_("You can't remove series with pending tasks, cancel tasks and retry"), _("Info"),
				wxOK | wxICON_WARNING);
		return;
	}

	bool eliminar = false;
	wxString msg = (setOfPks.size()>1)?_("those series"):_("this series");
	ConfirmDeleteDialog dlg(this, msg);
	dlg.ShowModal();
	switch (dlg.GetResultado()) {
		case ConfirmDeleteDialog::TR_Eliminar :
			eliminar = true;
			break;
		case ConfirmDeleteDialog::TR_Cancelar :
			break;
	}
	if(eliminar){
		GNC::GCS::HistoryController::Instance()->DeleteSeriesList(pkList);
		m_pTableModel->RemoveSelected();

		RefreshSearch();
		m_pThumbnails->Clear();
		ShowPreviewPanel(false);
		ReloadCombos(false);
	}
}


void GNC::GUI::HistoryPanel3::SelectAll()
{
	m_pTableModel->SelectAll();
}

void GNC::GUI::HistoryPanel3::DeselectAll()
{
	m_pTableModel->DeselectAll();
	m_pThumbnails->Clear();
	ShowPreviewPanel(false);
}

void GNC::GUI::HistoryPanel3::RestartPendingSelected()
{
	std::set<long> setOfPks;
	m_pTableModel->GetSeriesPkSelected(setOfPks);

	if (setOfPks.empty()) {
		wxMessageBox(_("Select at least one series"), _("Info"), wxOK | wxICON_WARNING);
		return;
	}
	GNC::GCS::HistoryController::IdList pkList;
	pkList.insert(pkList.begin(), setOfPks.begin(), setOfPks.end());

	std::list<GNC::GCS::HistoryController::TaskModel> tasks;
	GNC::GCS::HistoryController::Instance()->GetSeriesPendingTasks(pkList, tasks);

	launchTasks(tasks);
	RefreshSearch();
}

void GNC::GUI::HistoryPanel3::DeletePendingSelected()
{
	std::set<long> setOfPks;
	m_pTableModel->GetSeriesPkSelected(setOfPks);

	if (setOfPks.empty()) {
		wxMessageBox(_("Select at least one series"), _("Info"), wxOK | wxICON_WARNING);
		return;
	}

	if (wxMessageBox(_("Are you sure you want to delete task?"), _("Delete tasks"), wxYES_NO , this) == wxYES)
	{
		GNC::GCS::HistoryController::IdList pkList;
		pkList.insert(pkList.begin(), setOfPks.begin(), setOfPks.end());

		std::list<GNC::GCS::HistoryController::TaskModel> tasks;
		GNC::GCS::HistoryController::Instance()->GetSeriesPendingTasks(pkList, tasks);

		GNC::GCS::HistoryController::Instance()->DeleteTasks(tasks);
		RefreshSearch();
	}
}

void GNC::GUI::HistoryPanel3::AdvancedTasksEdition()
{
	std::set<long> setOfPks;
	m_pTableModel->GetSeriesPkSelected(setOfPks);

	if (setOfPks.empty()) {
		wxMessageBox(_("Select at least one series"), _("Info"), wxOK | wxICON_WARNING);
		return;
	}

	GNC::GCS::HistoryController::IdList pkList;
	pkList.insert(pkList.begin(), setOfPks.begin(), setOfPks.end());
	
	GNC::GUI::TaskControl dlg(this, pkList);
	dlg.ShowModal();
	RefreshSearch();
}

void GNC::GUI::HistoryPanel3::LoadPreviewsFromStudy(const wxTreeItemId& itemStudy)
{
	wxWindowDisabler disableAll;
	m_pThumbnails->Freeze();
	while (m_pThumbnails->GetCount()>0) {
		m_pThumbnails->Delete(0);
	}

	long pkStudy;
	m_pTreeListResults->GetItemText(itemStudy, COL_PK).ToLong(&pkStudy);

	GNC::GCS::HistoryController::SeriesModelList seriesList;
	GNC::GCS::HistoryController::Instance()->GetSeriesFromStudy(pkStudy, seriesList);
	
	for (GNC::GCS::HistoryController::SeriesModelList::const_iterator it = seriesList.begin(); it != seriesList.end(); ++it) {
		GNC::GCS::HistoryController::FileModel frame = GNC::GCS::HistoryController::Instance()->GetFrameOfReference((*it).pk);
		wxString pathOfItem = wxString::Format(wxT("%ld"),frame.pk);
		wxHistoryImageThumbnailItem* pItem = new wxHistoryImageThumbnailItem(pathOfItem, wxHistoryImageThumbnailItem::TI_Series, (*it).pk, frame.pk, !frame.file_path.empty());
		m_pThumbnails->Insert(pItem);
	}
	m_pThumbnails->Thaw();
}

void GNC::GUI::HistoryPanel3::LoadPreviewsFromSeries(const wxTreeItemId& itemSeries)
{
	wxWindowDisabler disableAll;
	m_pThumbnails->Freeze();
	while (m_pThumbnails->GetCount()>0) {
		m_pThumbnails->Delete(0);
	}

	long pk;
	m_pTreeListResults->GetItemText(itemSeries, COL_PK).ToLong(&pk);
	GNC::GCS::HistoryController::FileModelList listOfFiles;
	GNC::GCS::HistoryController::Instance()->GetSeriesSortedFileModels(pk, listOfFiles);

	for (GNC::GCS::HistoryController::FileModelList::const_iterator it = listOfFiles.begin(); it != listOfFiles.end(); ++it) {
		wxString pathOfItem = wxString::Format(wxT("%ld"),(*it).pk);
		wxHistoryImageThumbnailItem* pItem = new wxHistoryImageThumbnailItem(pathOfItem, wxHistoryImageThumbnailItem::TI_Image, pk, (*it).pk, !(*it).file_path.empty());
		m_pThumbnails->Append(pItem);
	}
	m_pThumbnails->Thaw();
}

void GNC::GUI::HistoryPanel3::ProcesarEvento(GNC::GCS::Events::IEvent *evt)
{
	switch(evt->GetCodigoEvento()) {
		case ginkgoEVT_Core_ProgresoComando:
		{
			GNC::GCS::Events::EventoProgresoComando* pEvt = dynamic_cast<GNC::GCS::Events::EventoProgresoComando*> (evt);

			if (pEvt == NULL  || pEvt->GetComando() == NULL) {
				return;
			}
			switch (pEvt->GetTipo()) {
				case GNC::GCS::Events::EventoProgresoComando::TEP_Iniciado:
					{
						GNC::GCS::IPersistentCommand* pPersistent = dynamic_cast<GNC::GCS::IPersistentCommand*> (pEvt->GetComando());
						if (pPersistent != NULL) {
							RefreshSearch();
						}
						m_pStatusBar->InsertarTarea(pEvt->GetComando()->GetId(), pEvt->GetTexto());
					}
					break;
				case GNC::GCS::Events::EventoProgresoComando::TEP_Progreso:
					//
					m_pStatusBar->SetProgresoTarea(pEvt->GetComando()->GetId(), pEvt->GetProgresoNormalizado(), pEvt->GetTexto());
					break;
				case GNC::GCS::Events::EventoProgresoComando::TEP_Finalizado:
					{
						m_pStatusBar->EliminarTarea(pEvt->GetComando()->GetId());
						GNC::GCS::IPersistentCommand* pPersistent = dynamic_cast<GNC::GCS::IPersistentCommand*> (pEvt->GetComando());
						if (pPersistent != NULL) {
							RefreshSearch();
						}
					}
					break;
				case GNC::GCS::Events::EventoProgresoComando::TEP_Unknown:
					break;
			}
		}
		break;
	}
}

//endregion
