/*
 *  
 *  $Id: panelconfiguracionpacs.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 <vector>
#include <sstream>
#include <limits>

#include <main/controllers/dcmtk/dicomservers.h>
#include <main/controllers/pacscontroller.h>
#include <main/controllers/controladorextensiones.h>
#include <main/controllers/dcmtk/dicomnetwork.h>
#include <main/controllers/dcmtk/dicomechoassociation.h>
#include <main/controllers/controladorlog.h>
#include <main/controllers/controladorpermisos.h>

#include <wx/msgdlg.h>
#include <wx/msgout.h>
#include <wx/filename.h>
#include <main/controllers/configurationcontroller.h>
#include <wx/valtext.h>
#include <wx/ginkgostyle/ginkgostyle.h>

#include <wx/file.h>
#include <wx/textfile.h>
#include <wx/dir.h>
#include <wx/filedlg.h>
#include <wx/log.h>
#include <wx/busyinfo.h>
#include <wx/xml/xml.h>


#include "panelconfiguracionpacs.h"

#include <sstream>

#include <main/entorno.h>
#include <resources/ginkgoresourcesmanager.h>


namespace GNC {
	namespace GUI {

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////DialogoEditarCertificado//////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		class DialogoEditarCertificado: public DialogoEditarCertificadoBase
		{
		public:
			DialogoEditarCertificado(wxWindow* pParent, const std::string& cert, const std::string& privateKey, bool permitirDefecto): DialogoEditarCertificadoBase(pParent)
			{
				m_Ok = false;
				m_pTextoCertificado->SetValue(wxString::FromUTF8(cert.c_str()));
				m_pTextoPrivateKey->SetValue(wxString::FromUTF8(privateKey.c_str()));
				
				if (permitirDefecto) {
					m_pCheckDefault->SetValue(cert.size() == 0 && privateKey.size() == 0);
				} else {
					m_pCheckDefault->SetValue(false);
					m_pPanelDefault->Show(false);
					m_pSepDefault->Show(false);
					m_pBody->Layout();
					Layout();
					Refresh(true);
				}
				
				RefrescarEstado();
			}
			~DialogoEditarCertificado()
			{}

			virtual void OnAceptarClick(wxCommandEvent&)
			{
				if (Validar()) {
					m_Ok = true;
					Close();
				}
			}

			void CargarFichero(bool publicKey) 
			{
				wxFileDialog seleccionarFichero (this, _("Select certificate"), wxT(""), wxT(""), _("PEM files(*.pem;*.key)|*.pem;*.key|All files (*.*)|*.*"),wxFD_FILE_MUST_EXIST|wxFD_OPEN);
				int response = seleccionarFichero.ShowModal();
				if (response == wxID_OK) {
					wxTextFile textFile(seleccionarFichero.GetPath());
					if (textFile.Open()) {
						wxString cadena;
						if (!textFile.Eof()) {
							cadena += textFile.GetNextLine();
							while(!textFile.Eof()) {
								cadena += wxT("\n") + textFile.GetNextLine();
							}
						}
						if (publicKey) {
							m_pTextoCertificado->SetValue(cadena);
						} else {
							m_pTextoPrivateKey->SetValue(cadena);
						}
						textFile.Close();
					}
				}				
			}

			virtual void OnLoadPrivateClick(wxCommandEvent& )
			{
				CargarFichero(false);
			}

			virtual void OnLoadPublicClick(wxCommandEvent& )
			{
				CargarFichero(true);
			}

			virtual void OnResetToDefault(wxCommandEvent& ) 
			{
				if (m_pPanelDefault->IsShown()) {
					m_pCheckDefault->SetValue(true);
				} else {
					//cargamos el certificado por defecto...
#ifdef GINKGO_PUBLIC_KEY
					m_pTextoCertificado->SetValue(wxString::FromUTF8(GINKGO_PUBLIC_KEY));
#else
					m_pTextoCertificado->SetValue(wxT(""));
#endif
#ifdef GINKGO_PRIVATE_KEY
					m_pTextoPrivateKey->SetValue(wxString::FromUTF8(GINKGO_PRIVATE_KEY));
#else
					m_pTextoPrivateKey->SetValue(wxT(""));
#endif
				}

				RefrescarEstado();
			}

			virtual void OnCheckDefault(wxCommandEvent&)
			{
				RefrescarEstado();
			}
			virtual void RefrescarEstado()
			{
				m_pPanelPublic->Enable(!m_pCheckDefault->IsChecked());
				m_pPanelPublic->Refresh();
				m_pPanelPrivate->Enable(!m_pCheckDefault->IsChecked());
				m_pPanelPrivate->Refresh();

				if (m_pCheckDefault->IsChecked()) {
					m_pTextoCertificado->SetValue(wxT(""));
					m_pTextoPrivateKey->SetValue(wxT(""));
				}
			}

			std::string GetPublicValue()
			{
				std::string cert(m_pTextoCertificado->GetValue().ToUTF8());
				return cert;
			}

			std::string GetPrivateValue()
			{
				std::string cert(m_pTextoPrivateKey->GetValue().ToUTF8());
				return cert;
			}
			
			bool GetUseDefaultCert()
			{
				return m_pCheckDefault->GetValue();
			}
			
			bool Validar()
			{
				bool ok = true;
				std::stringstream sstream;

				if (!m_pCheckDefault->IsChecked() && m_pCheckDefault->IsShown()) {
					if (m_pTextoCertificado->GetValue().size() == 0 || m_pTextoPrivateKey->GetValue().size() == 0)
					{
						ok = false;
						sstream << _Std("You have to set private and public key") ;
					}
					if (!ok) {
						wxMessageBox(wxString::FromUTF8(sstream.str().c_str()),_("Info"),wxOK | wxICON_INFORMATION, this);
					}
				}
				return ok;
			}

			bool m_Ok;	
		};

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////DialogoLocalPACS//////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		class DialogoLocalPACS: public DialogoLocalPACSBase
		{
		public:
			DialogoLocalPACS(wxWindow* pParent): DialogoLocalPACSBase(pParent)
			{
				m_Ok = false;
			}
			~DialogoLocalPACS()
			{}

			void SetParametros(PanelConfiguracionPACS::TipoConfigLocal& pacsLocal)
			{
				m_pUseTLS->SetValue(pacsLocal.useTLS);

				m_pVerifyServer->SetValue(pacsLocal.verifyCredentials);

				m_certificado = pacsLocal.certificate;
				m_privateKey = pacsLocal.privateKey;
				if (m_certificado.size()>0 || m_privateKey.size()>0) {
					m_pBCert->SetLabel(_("Change ..."));
				} else {
					m_pBCert->SetLabel(_("Import ..."));
				}
			}

			void GetParametros(PanelConfiguracionPACS::TipoConfigLocal& pacsLocal)
			{
				pacsLocal.useTLS = m_pUseTLS->GetValue();

				pacsLocal.verifyCredentials = m_pVerifyServer->GetValue();

				pacsLocal.certificate = m_certificado;
				pacsLocal.privateKey = m_privateKey;
			}


			virtual void OnEditCertificate(wxCommandEvent&)
			{
				DialogoEditarCertificado dlg(this, m_certificado, m_privateKey, false);
				dlg.ShowModal();
				if (dlg.m_Ok) {
					m_certificado = dlg.GetPublicValue();
					m_privateKey = dlg.GetPrivateValue();
					if (m_certificado.size()>0 || m_privateKey.size()>0) {
						m_pBCert->SetLabel(_("Change ..."));
					} else {
						m_pBCert->SetLabel(_("Import ..."));
					}
				}
			}

			virtual void OnAceptarClick(wxCommandEvent&)
			{
				if (Validar()) {
					m_Ok = true;
					Close();
				}
			}

			bool Validar()
			{
				bool ok = true;
				std::stringstream sstream;

				if (m_pUseTLS->GetValue() 
					&& (m_certificado.size() == 0 || m_privateKey.size() == 0))
				{
					ok = false;
					sstream << _Std("If you want to use SSL/TLS you have to set a valid certificate and a valid private key") ;
				}
				if (!ok) {
					wxMessageBox(wxString::FromUTF8(sstream.str().c_str()),_("Info"),wxOK | wxICON_INFORMATION, this);
				}
				return ok;
			}

			bool m_Ok;
			std::string m_certificado;
			std::string m_privateKey;
		};

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////DialogoServidorPACS///////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		class DialogoServidorPACS: public DialogoServidorPACSBase
		{
		public:
			DialogoServidorPACS(wxWindow* pParent, PanelConfiguracionPACS::TipoConfigLocal& configLocal, const wxString& strPuertoLocal, const wxString& aetLocal, std::list<std::string> usedPACSIds) :
				DialogoServidorPACSBase(pParent),
				m_configLocal(configLocal),
				m_Ok(false),
				m_aetLocal(aetLocal.ToUTF8()),
				m_puertoLocal(11112),
				m_idsPacs(usedPACSIds)
			{
				wxTextValidator OnlyNum = wxTextValidator(wxFILTER_NUMERIC);
				m_pPuerto->SetValidator(OnlyNum);

				m_pPDU->SetValue(16384);

				long puertoLocal;
				if(strPuertoLocal.ToLong(&puertoLocal)){
					m_puertoLocal = puertoLocal;
				}

				if(!GNC::GCS::IControladorPermisos::Instance()->Get("core.pacs.limits","pacs_tls")) {
					m_pPanelSeguridad->Show(false);
					m_notebook1->RemovePage(1);
				}
			}

			~DialogoServidorPACS()
			{

			}

			void GetParametros(PanelConfiguracionPACS::TipoPACS& tipoPacs)
			{
				tipoPacs.id = std::string(m_pId->GetValue().ToUTF8());
				tipoPacs.aet= std::string(m_pAET->GetValue().ToUTF8());
				tipoPacs.host = std::string(m_pHost->GetValue().ToUTF8());
				tipoPacs.puerto = atoi(m_pPuerto->GetValue().ToUTF8());
				tipoPacs.pdu = m_pPDU->GetValue();

				tipoPacs.retrieveWithMove = m_pRetrieveMethod->GetSelection() == 0;
				tipoPacs.retrieveSeries = m_pRetrieveMode->GetSelection() == 0;

				tipoPacs.reuseConnection = m_pReuseConnection->GetValue();

				if(GNC::GCS::IControladorPermisos::Instance()->Get("core.pacs.limits","pacs_tls")) {
					tipoPacs.useTLS = m_pUseSSL->GetValue();

					tipoPacs.pacsUser = m_pUser->GetValue().ToUTF8();
					tipoPacs.pacsPass = m_pPassword->GetValue().ToUTF8();
					
					tipoPacs.verifyCredentials = m_pVerifyServer->GetValue();

					tipoPacs.certificate = m_certificado;
					tipoPacs.privateKey = m_privateKey;
				}
				tipoPacs.defaultCharset = m_pComboCharset->GetValue().ToUTF8();
			}

			void SetParametros(PanelConfiguracionPACS::TipoPACS& tipoPacs)
			{
				m_pId->SetValue(wxString::FromUTF8(tipoPacs.id.c_str()));
				m_pAET->SetValue(wxString::FromUTF8(tipoPacs.aet.c_str()));
				m_pHost->SetValue(wxString::FromUTF8(tipoPacs.host.c_str()));
				m_pPuerto->SetValue(wxString::Format(wxT("%d"), tipoPacs.puerto));
				m_pPDU->SetValue(wxString::Format(wxT("%d"), tipoPacs.pdu));

				m_pRetrieveMethod->SetSelection(tipoPacs.retrieveWithMove?0:1);
				m_pRetrieveMode->SetSelection(tipoPacs.retrieveSeries?0:1);

				m_pReuseConnection->SetValue(tipoPacs.reuseConnection);

				if(GNC::GCS::IControladorPermisos::Instance()->Get("core.pacs.limits","pacs_tls")) {
					m_pUseSSL->SetValue(tipoPacs.useTLS);
					m_pUser->SetValue(wxString::FromUTF8(tipoPacs.pacsUser.c_str()));
					m_pPassword->SetValue(wxString::FromUTF8(tipoPacs.pacsPass.c_str()));

					m_pVerifyServer->SetValue(tipoPacs.verifyCredentials);

					m_certificado = tipoPacs.certificate;
					m_privateKey = tipoPacs.privateKey;
				}
				
				m_pComboCharset->SetValue(wxString::FromUTF8(tipoPacs.defaultCharset.c_str()));
			}

			virtual void OnAdvancedConfiguration(wxCommandEvent&)
			{
				DialogoEditarCertificado dlg(this, m_certificado, m_privateKey, true);
				dlg.ShowModal();
				if (dlg.m_Ok) {
					if (dlg.GetUseDefaultCert()) {
						m_certificado = m_configLocal.certificate;
						m_privateKey = m_configLocal.privateKey;
					}
					else {
						m_certificado = dlg.GetPublicValue();
						m_privateKey = dlg.GetPrivateValue();
					}
				}
			}

			virtual void OnCancelClick(wxCommandEvent &){
				m_Ok=false;
				Close();
			}

			virtual void OnOkClick(wxCommandEvent &){
				if(Validar()) {
					m_Ok=true;
					Close();
				}
			}

			bool Validar ()
			{
				bool ok = true;
				if(m_pId->GetValue() != wxEmptyString && m_pAET->GetValue() != wxEmptyString && m_pHost->GetValue() != wxEmptyString && m_pPuerto->GetValue() != wxEmptyString){
					std::stringstream sstream;
					sstream << _Std("There are this errors: ");

					std::string idPACS = std::string(m_pId->GetValue().ToUTF8());
					for (std::list<std::string>::iterator it = m_idsPacs.begin(); it != m_idsPacs.end(); ++it) {
						if (idPACS == (*it)) {
							sstream << _Std("\n- This PACS id is in use");
							ok = false;
							break;
						}
					}

					long numero;
					if(!m_pPuerto->GetValue().ToLong(&numero)){
						ok = false;
						sstream << _Std("\n- The port must be a positive short integer (16 bits)");
					} else{
						if(numero > 32767){//maxshort
							ok = false;
							sstream <<_Std("\n- The port is too large");
						}
					}

					if(m_pAET->GetLabel().size() >16) {
						ok = false;
						sstream <<_Std("\n- The maximum length of the AET is 16 characters");
					}

					if (m_pPDU->GetValue() != 0) {

						if(!m_pPDU->GetValue()){
							ok = false;
							sstream << _Std("\n- The PDU size should be greater than or equal to zero (default = 16384)");
						} else{
							if(m_pPDU->GetValue() > MAX_PDU_LENGTH){ // max, viene de esta constante ASC_MAXIMUMPDUSIZE de DCMTK
								ok = false;
								sstream << _Std("\n- The maximum value of the PDU is ") <<  MAX_PDU_LENGTH << "(" << MAX_PDU_LENGTH/1024 << "K)";
							}
							if(m_pPDU->GetValue() < MIN_PDU_LENGTH){ // min, viene de esta constante ASC_MINIMUMPDUSIZE de DCMTK
								ok = false;
								sstream << _Std("\n- The minimum value of the PDU is ") <<  MIN_PDU_LENGTH << "(" << MIN_PDU_LENGTH/1024 << "K)" ;
							}
						}
					}

					if (m_pUseSSL->GetValue() && ( (m_certificado.size() == 0 || m_privateKey.size() == 0) && (m_configLocal.certificate.size() == 0 || m_configLocal.privateKey.size() == 0 )  ) )
					{
						ok = false;
						sstream << _Std("\n- If you want to use SSL/TLS you have to set a valid certificate and private key") ;
					}

					if(!ok)
						wxMessageBox(wxString::FromUTF8(sstream.str().c_str()),_("Info"),wxOK | wxICON_INFORMATION, this);
				}else{
					ok = false;
					wxMessageBox(_("You must fill in all fields to continue"),_("Info"),wxOK | wxICON_INFORMATION, this);
				}
				return ok;
			}
			virtual void OnProbarClick(wxCommandEvent &)
			{
				if(Validar()) {
					long puerto;
					long pdu = m_pPDU->GetValue();
					if(m_pPuerto->GetValue().ToLong(&puerto)){

						EchoAssociation as("C-ECHO");
						if (m_pUseSSL->GetValue()) {
							if (m_certificado.empty() || m_privateKey.empty()) {							
								as.SetTLS(m_configLocal.certificate, m_configLocal.privateKey, m_pVerifyServer->GetValue());
							}
							else {
								as.SetTLS(m_certificado, m_privateKey, m_pVerifyServer->GetValue());
							}
						}
						if (m_pUser->GetValue() != wxEmptyString) {
							as.SetUserPass(std::string(m_pUser->GetValue().ToUTF8()), std::string(m_pPassword->GetValue().ToUTF8()));
						}
						CONDITION cond;
						wxBusyInfo* info = new wxBusyInfo(_("Testing the connection to the node ..."));
						
						std::string aet(m_pAET->GetValue().ToUTF8());
						std::string host(m_pHost->GetValue().ToUTF8());

						as.Create(aet, host, puerto, m_aetLocal, UID_VerificationSOPClass);

						GIL::DICOM::DCMTK::Network* pNetwork = NULL;
						try {
							pNetwork = GIL::DICOM::DCMTK::Network::Instance(this);
						}
						catch(...)
						{
						}
						if(pNetwork != NULL) {
							as.SetTimeout(10);
							pNetwork->InitializeNetwork(as.GetTimeout());
							cond = pNetwork->ConnectAssociation(&as, pdu);
							if (cond.good()) {
								if (as.SendEchoRequest())
								{			
									LOG_DEBUG("C-TEST", _Std("Connection test successful"));
									delete info;
									info = NULL;
									wxMessageBox(_("Successful connection test."),_("Info"),wxOK | wxICON_INFORMATION, this);
								}
								else {
									delete info;
									info = NULL;
									wxMessageBox(_("The service did not respond correctly to the C-ECHO"),_("Error"), wxICON_ERROR, this);
								}
							}
							else {
								LOG_ERROR("C-TEST", _Std("The service did not respond properly:") << cond.text());
								delete info;
								info = NULL;
								wxMessageBox(_("The service did not respond correctly to the DICOM standard:")  + wxString::FromUTF8(cond.text()), _("Error"), wxICON_ERROR, this);
							}
							as.Drop();
							GIL::DICOM::DCMTK::Network::FreeInstance(this);
							pNetwork = NULL;
						}
						else {
							LOG_ERROR("C-TEST", _Std("Unable to connect: Could not start network support."));
							delete info;
							info = NULL;
							wxMessageBox(_("Error starting network support"), _("Error"), wxICON_ERROR, this);
						}
					}
				}

			}

			PanelConfiguracionPACS::TipoConfigLocal& m_configLocal;

			bool m_Ok;
			std::string m_aetLocal;
			long m_puertoLocal;
			std::string m_certificado;
			std::string m_privateKey;
			std::list<std::string> m_idsPacs;
			std::string m_defCharset;
		};


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////PanelConfiguracionPACS////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		PanelConfiguracionPACS::PanelConfiguracionPACS(wxWindow* pParent,IDialogoConfiguracion* pDialogo): PanelConfiguracionPACSBase(pParent), IPasoConfiguracion(pDialogo)
		{
			this->m_pTreeListPACS->AddColumn(_("Name"), 200, wxALIGN_LEFT, -1, true, false);
			this->m_pTreeListPACS->AddColumn(_("Use by default"), 70, wxALIGN_LEFT, -1, true, false);
			Recargar();
			
			m_pHelpBitmap->SetBitmap(GinkgoResourcesManager::MenuIcons::GetIcoHelp());

			if(!GNC::GCS::IControladorPermisos::Instance()->Get("core.pacs.limits","pacs_tls")) {
				m_pBAdvanced->Show(false);
				m_pPACSLocal->Layout();
				this->Layout();
				this->Refresh(true);
			}

			m_pTreeListPACS->Connect(wxEVT_COMMAND_TREE_ITEM_ACTIVATED, wxTreeEventHandler( PanelConfiguracionPACS::OnListaPACSDClick ), NULL, this );
			m_pTreeListPACS->Connect(wxEVT_COMMAND_TREE_SEL_CHANGED, wxTreeEventHandler( PanelConfiguracionPACS::OnListaPACSChoice ), NULL, this );
		}

		PanelConfiguracionPACS::~PanelConfiguracionPACS()
		{
			m_servidores.clear();
		}

		void PanelConfiguracionPACS::Recargar()
		{
			std::string strTmp;
			if (!GNC::GCS::ConfigurationController::Instance()->readStringGeneral("/GinkgoCore/PACS/Local", "AET", strTmp, "GINKGO_%IP4")) {
				GNC::GCS::ConfigurationController::Instance()->writeStringGeneral("/GinkgoCore/PACS/Local", "AET", strTmp);
			}
			m_pAETLocal->SetValue(wxString::FromUTF8(strTmp.c_str()));
			m_pAETReal->SetLabel(wxString::FromUTF8( GNC::Entorno::Instance()->ParseAET(strTmp).substr(0, 16).c_str() ));

			DicomServer* serverLocal = DicomServerList::Instance()->GetLocalServer();
			m_pPuertoLocal->SetValue(wxString::Format(wxT("%d"),serverLocal->GetPort()));

			wxTextValidator OnlyNum = wxTextValidator(wxFILTER_NUMERIC);
			m_pPuertoLocal->SetValidator(OnlyNum);

			m_configLocal.useTLS = serverLocal->GetUseTLS();

			m_configLocal.verifyCredentials = serverLocal->GetverifyCredentials();
			m_configLocal.privateKey = serverLocal->GetPrivateKey();
			m_configLocal.certificate = serverLocal->GetCertificate();

			if(GNC::GCS::IControladorPermisos::Instance()->Get("core.pacs.limits","remote_pacs")) {
				m_pPACSServers->Enable(true);
				
				m_pTreeListPACS->DeleteRoot();
				wxTreeItemId idRoot = m_pTreeListPACS->AddRoot(wxT("Root"));
				m_servidores.clear();

				DicomServerList::Instance()->FreeInstance();
				for (DicomServerHolder* sl = DicomServerList::Instance()->GetList(); sl != NULL; sl = sl->next) {
					TipoPACS tp;
					tp.id = sl->server.ID;
					tp.aet = sl->server.AET;
					tp.host = sl->server.HostName;
					tp.isDefault = sl->server.isDefault;
					tp.puerto = sl->server.Port;
					tp.pdu = sl->server.PDU;
					tp.retrieveWithMove = sl->server.retrieveWithMove;
					tp.retrieveSeries = sl->server.retrieveSeries;

					tp.reuseConnection = sl->server.reuseConnection;
					
					tp.useTLS = sl->server.useTLS;
					tp.pacsUser = sl->server.pacsUser;
					tp.pacsPass = sl->server.pacsPass;
					
					tp.verifyCredentials = sl->server.verifyCredentials;
					tp.certificate = sl->server.certificate;
					tp.privateKey = sl->server.privateKey;
					tp.defaultCharset = sl->server.defaultCharset;
					m_servidores.push_back(tp);
					wxTreeItemId idItem = m_pTreeListPACS->AppendItem(idRoot, wxString::FromUTF8(tp.id.c_str()));
					if(tp.isDefault) {
						m_pTreeListPACS->SetItemText(idItem, 1, _("Yes"));
					} else {
						m_pTreeListPACS->SetItemText(idItem, 1, _("No"));
					}
				}

				if(m_pTreeListPACS->GetChildrenCount(idRoot) > 0){
					wxTreeItemIdValue cookie;
					m_pTreeListPACS->SelectItem(m_pTreeListPACS->GetFirstChild(idRoot, cookie));
					wxTreeEvent evt;
					OnListaPACSChoice(evt);
				}
			}
			else {
				m_pPACSServers->Enable(false);
			}

		}

		//region "Metodos de IPasoConfiguracion"
		wxWindow* PanelConfiguracionPACS::GetPanel()
		{
			return this;
		}

		std::string PanelConfiguracionPACS::GetTitle()
		{
			return _Std("DICOM nodes");
		}

		std::string PanelConfiguracionPACS::GetCabecera()
		{
			return _Std("DICOM nodes settings");
		}

		bool PanelConfiguracionPACS::Validar()
		{
			bool ok = true;
			std::stringstream sstream;
			sstream << _Std("They have produced the following errors:");

			long numero;
			if(!m_pPuertoLocal->GetValue().ToLong(&numero) && m_pPuertoLocal->GetValue().size() > 0){
				ok = false;
				sstream << _Std("\n- The local port must be a positive short integer (16 bits)");
			} else{
				if(numero > 32767){//maxshort
					ok = false;
					sstream << _Std("\n- The local port is too large");
				}
			}

			if(m_pAETReal->GetLabel().size() >16) {
				ok = false;
				sstream << _Std("\n- Maximum length of local AET is 16 characters");
			}

			if(!ok)
				wxMessageBox(wxString::FromUTF8(sstream.str().c_str()),_("Info"),wxOK | wxICON_INFORMATION, this);
			return ok;
		}

		bool PanelConfiguracionPACS::Guardar()
		{
			//se actualiza el fichero de configuracion
			GNC::GCS::ConfigurationController::Instance()->writeStringGeneral("/GinkgoCore/PACS/Local","AET",std::string(m_pAETLocal->GetValue().ToUTF8()));
			GNC::GCS::ConfigurationController::Instance()->writeStringGeneral("/GinkgoCore/PACS/Local","Puerto",std::string(m_pPuertoLocal->GetValue().ToUTF8()));
			GNC::GCS::ConfigurationController::Instance()->writeBoolGeneral("/GinkgoCore/PACS/Local","useTLS",m_configLocal.useTLS);
			GNC::GCS::ConfigurationController::Instance()->writeBoolGeneral("/GinkgoCore/PACS/Local","verifyCredentials",m_configLocal.verifyCredentials);
			GNC::GCS::ConfigurationController::Instance()->writeStringGeneral("/GinkgoCore/PACS/Local","privateKey",m_configLocal.privateKey);
			GNC::GCS::ConfigurationController::Instance()->writeStringGeneral("/GinkgoCore/PACS/Local","certificate",m_configLocal.certificate);

			GIL::DICOM::PACSController::Instance()->StartServer();
			
			if(GNC::GCS::IControladorPermisos::Instance()->Get("core.pacs.limits","remote_pacs")) {
				wxString clave;
				wxString valor;
				GNC::GCS::ConfigurationController::Instance()->deleteEntryGeneral("/GinkgoCore/PACS/Servidores");
				GNC::GCS::ConfigurationController::TListGroups pacsList;

				for(TipoListaPACS::iterator it = m_servidores.begin(); it!= m_servidores.end(); ++it){
					GNC::GCS::ConfigurationController::TMapValues pacs;
					pacs["Identificador"] = (*it).id;
					pacs["AET"] = (*it).aet;
					pacs["Host"] = (*it).host;
					pacs.insertInt("Puerto",(*it).puerto);
					pacs.insertInt("PDU",(*it).pdu);
					pacs.insertBool("useTLS", (*it).useTLS);
					pacs.insertBool("verifyCredentials", (*it).verifyCredentials);
					pacs.insertBool("retrieveWithMove", (*it).retrieveWithMove);
					pacs.insertBool("reuseConnection", (*it).reuseConnection);
					pacs.insertBool("retrieveSeries", (*it).retrieveSeries);
					pacs["pacsUser"] = (*it).pacsUser;
					pacs["pacsPass"] = (*it).pacsPass;
					pacs["certificate"] = (*it).certificate;
					pacs["privateKey"] = (*it).privateKey;
					pacs.insertBool("isDefault", (*it).isDefault);
					pacs["defaultCharset"] = (*it).defaultCharset;
					pacsList.push_back(pacs);
				}
				GNC::GCS::ConfigurationController::Instance()->writeGroupGeneral("/GinkgoCore/PACS/Servidores", pacsList, "Server");
				DicomServerList::Instance()->Reload();
			}
			else {
				DicomServerList::Instance()->FreeInstance();
			}

			return true;
		}

		//endregion

		void PanelConfiguracionPACS::OnAdvancedLocal(wxCommandEvent &)
		{
			DialogoLocalPACS dlg(this);
			dlg.SetParametros(m_configLocal);
			dlg.ShowModal();
			if(dlg.m_Ok){
				dlg.GetParametros(m_configLocal);
				OnPropiedadCambiada();
			}
		}

		void PanelConfiguracionPACS::OnListaPACSChoice(wxTreeEvent &){
			//se carga la descripcion
			bool enable = m_pTreeListPACS->GetSelection().IsOk();
			m_pEditButton->Enable(enable);
			m_pDelButton->Enable(enable);
			m_pDefaultButton->Enable(enable);
		}

		void PanelConfiguracionPACS::OnListaPACSDClick(wxTreeEvent &)
		{
			wxCommandEvent evt;
			OnEditarClick(evt);
		}

		void PanelConfiguracionPACS::OnNuevoClick(wxCommandEvent &){
			std::list<std::string> listIdsPacs;
			for (TipoListaPACS::iterator it = m_servidores.begin(); it != m_servidores.end(); ++it) {
				listIdsPacs.push_back((*it).id);
			}
			DialogoServidorPACS dialogo(this, m_configLocal, m_pPuertoLocal->GetValue(), wxString::FromUTF8( GNC::Entorno::Instance()->ParseAET( std::string(m_pAETLocal->GetValue().ToUTF8()) ).c_str() ), listIdsPacs );
			dialogo.ShowModal();
			if(dialogo.m_Ok){
				TipoPACS tp;
				dialogo.GetParametros(tp);
				if (m_pTreeListPACS->GetChildrenCount(m_pTreeListPACS->GetRootItem()) == 0) {
					tp.isDefault = true;
				}
				m_servidores.push_back(tp);

				wxTreeItemId idItem = m_pTreeListPACS->AppendItem(m_pTreeListPACS->GetRootItem(), wxString::FromUTF8(tp.id.c_str()));
				if(tp.isDefault) {
					m_pTreeListPACS->SetItemText(idItem, 1, _("Yes"));
				} else {
					m_pTreeListPACS->SetItemText(idItem, 1, _("No"));
				}

				m_pTreeListPACS->SelectItem(idItem);
				wxTreeEvent evt;
				OnListaPACSChoice(evt);
				OnPropiedadCambiada();
			}
		}

		void PanelConfiguracionPACS::OnEditarClick(wxCommandEvent &){
			wxTreeItemId id  = m_pTreeListPACS->GetSelection();
			if(id.IsOk()){
				std::string idSeleccionado(m_pTreeListPACS->GetItemText(id).ToUTF8());

				std::list<std::string> listIdsPacs;
				for (TipoListaPACS::iterator it = m_servidores.begin(); it != m_servidores.end(); ++it) {
					if((*it).id != idSeleccionado){
						listIdsPacs.push_back((*it).id);
					}
				}

				for(TipoListaPACS::iterator it = m_servidores.begin(); it != m_servidores.end(); ++it){
					if((*it).id == idSeleccionado){
						DialogoServidorPACS dialogo(this, m_configLocal, m_pPuertoLocal->GetValue(), wxString::FromUTF8( GNC::Entorno::Instance()->ParseAET( std::string( m_pAETLocal->GetValue().ToUTF8() ) ).c_str() ), listIdsPacs);
						dialogo.SetParametros((*it));

						dialogo.ShowModal();
						if(dialogo.m_Ok){
							dialogo.GetParametros((*it));
							//se refresca el combo
							m_pTreeListPACS->SetItemText(id,wxString::FromUTF8((*it).id.c_str()));
							m_pTreeListPACS->SelectItem(id);

							wxTreeEvent evt;
							OnListaPACSChoice(evt);
							OnPropiedadCambiada();
						}
					}
				}
			}
		}

		void PanelConfiguracionPACS::OnEliminarClick(wxCommandEvent &){
			wxTreeItemId itemSeleccionado = m_pTreeListPACS->GetSelection();
			if(itemSeleccionado.IsOk()){
				std::string idSeleccionado(m_pTreeListPACS->GetItemText(itemSeleccionado).ToUTF8());
				int answer = wxMessageBox(_("Confirm the removal of the node") + wxString::FromUTF8(idSeleccionado.c_str()), _("Data modified"), wxYES_NO | wxCANCEL, this);
				if(answer == wxYES){
					for(TipoListaPACS::iterator it = m_servidores.begin(); it != m_servidores.end(); ++it){
						if((*it).id == idSeleccionado){
							m_pTreeListPACS->Delete(itemSeleccionado);
							m_servidores.erase(it);
							break;
						}
					}
					wxTreeEvent evt;
					OnListaPACSChoice(evt);
					OnPropiedadCambiada();
				}
			}
		}

		void PanelConfiguracionPACS::OnSetDefaultClick(wxCommandEvent &)
		{
			wxTreeItemId itemSeleccionado = m_pTreeListPACS->GetSelection();
			if(itemSeleccionado.IsOk()){
				std::string idSeleccionado(m_pTreeListPACS->GetItemText(itemSeleccionado).ToUTF8());
				for(TipoListaPACS::iterator it = m_servidores.begin(); it != m_servidores.end(); ++it){
					if((*it).id == idSeleccionado){
						(*it).isDefault = true;
					} else {
						(*it).isDefault = false;
					}
				}
				wxTreeItemIdValue cookie;
				wxTreeItemId itemActual = m_pTreeListPACS->GetFirstChild(m_pTreeListPACS->GetRootItem(), cookie);
				while (itemActual.IsOk())
				{
					if (itemActual == itemSeleccionado) {
						m_pTreeListPACS->SetItemText(itemActual,1,_("Yes"));
					} else {
						m_pTreeListPACS->SetItemText(itemActual,1,_("No"));
					}
					itemActual = m_pTreeListPACS->GetNextChild(m_pTreeListPACS->GetRootItem(), cookie);
				}
				wxTreeEvent evt;
				OnListaPACSChoice(evt);
				OnPropiedadCambiada();
			}
		}

		void PanelConfiguracionPACS::OnTextoCambiado(wxCommandEvent & )
		{
			m_pAETReal->SetLabel(wxString::FromUTF8( GNC::Entorno::Instance()->ParseAET(std::string(m_pAETLocal->GetValue().ToUTF8())).c_str() ));
			OnPropiedadCambiada();
		}

		void PanelConfiguracionPACS::OnSize(wxSizeEvent & event){
			wxSize oldSize = m_staticTextExplicacion->GetSize();
			Freeze();
			m_staticTextExplicacion->Freeze();
			m_staticTextExplicacion->SetLabel(_("You must configure the local AET, which is used to communicate with the DICOM nodes. The specified port must be opened in the firewall, as it is essential for transfers."));
			m_staticTextExplicacion->Wrap( event.GetSize().x-25 );
			m_staticTextExplicacion->Thaw();
			//Layout();
			Thaw();
			wxSize newSize = m_staticTextExplicacion->GetSize();
			if (newSize != oldSize) {
				Layout();
				event.Skip(false);
			} else {
				event.Skip(true);
			}
		}
	}
}
