/*
 *
 *  $Id: ventanaprincipal.cpp $
 *  Ginkgo CADx Project
 *
 *  Copyright 2008-14 MetaEmotion S.L. All rights reserved.
 *  http://ginkgo-cadx.com
 *
 *  This file is licensed under LGPL v3 license.
 *  See License.txt for details
 *
 *
 */
//#define _GINKGO_TRACE

#include <iostream>
#include <sstream>

#include <wx/wx.h>
#include <wx/zstream.h>
#include <wx/wfstream.h>
#include <wx/aui/aui.h>
#include <wx/app.h>
#include <wx/propgrid/propgrid.h>
#include <wx/dir.h>
#include <wx/filename.h>
#include <wx/file.h>
#include <wx/mstream.h>
#include <wx/textfile.h>
#include <wx/statbmp.h>

#include <wx/filedlg.h>
#include <wx/dirdlg.h>
#include <wx/msgdlg.h>
#include <wx/msgout.h>
#include <wx/xml/xml.h>
#include <wx/sstream.h>
#include <wx/html/htmlwin.h>
#include <wx/gbsizer.h>
#include <wx/txtstrm.h>
#include <wx/display.h>
#include <wx/cmdline.h>
#include <wx/stdpaths.h>
#include <wx/mimetype.h>

#include <main/gui/mainwindow/ventanaprincipal.h>
#include <main/gui/mainwindow/detacheddialog.h>
#include <main/gui/login/dialogologin.h>
#include <main/gui/open/abrir.h>
#include <main/gui/license/aboutdialog.h>
#include <main/gui/license/acceptlicensedialog.h>
#include <main/gui/import/wxwizardimportacionginkgo.h>
#include <main/gui/acquisition/dialogoadquisicion.h>
#include <main/gui/ginkgocloud/ginkgocloudsearchdialog.h>
#include <main/gui/history3/historypanel3.h>
#include <main/gui/progress/statusbarprogreso.h>
#include <main/gui/configuration/dialogoconfiguracion.h>
#include <main/gui/hl7controlwindow/ventanacontrolhl7.h>
#include <main/gui/logcontrolwindow/ventanacontrollogs.h>
#include <main/gui/startup/startupview.h>
#include <main/gui/droptargetmainwindow.h>

#include <api/globals.h>
#include <api/ivista.h>
#include <api/controllers/imodulecontroller.h>
#include <api/controllers/ipacscontroller.h>
#include <api/controllers/icontroladorcarga.h>
#include <api/toolsystem/itoolcontroller.h>
#include <api/toolsystem/itoolsregistry.h>

#include <main/entorno.h>

#include <main/controllers/controladorextensiones.h>
#include <main/controllers/integrationcontroller.h>
#include <main/controllers/controladorvistas.h>
#include <main/controllers/commandcontroller.h>
#include <main/controllers/controladorpermisos.h>
#include <main/controllers/controladorhl7.h>
#include <main/controllers/controladorenviohl7.h>
#include <main/controllers/controladorautenticacion.h>
#include <main/controllers/controladorlog.h>
#include <main/controllers/controladoreventos.h>
#include <main/controllers/dcmtk/dicomservers.h>
#include <main/controllers/configurationcontroller.h>
#include <main/controllers/windowattributescontroller.h>

#include <commands/comandoactualizaciones.h>
#include <commands/comandoincluirhistorial.h>
#include <commands/openremovableunit.h>
#include <commands/commandsynchronizewithgui.h>

#include <eventos/updateavailable.h>

#include <resources/ginkgoresourcesmanager.h>

#define ID_CERRAR 1054
#define ID_CERRAR_TODAS 1055
#define ID_SALIR 1059
#define ID_ONLINE_SUPPORT 1060
#define ID_ACERCA_DE 1062
#define ID_CONFIGURACION 1063
#define ID_PANTALLA_COMPLETA 1070
#define ID_MOSAICO_VERTICAL 1071
#define ID_MOSAICO_HORIZONTAL 1072
#define ID_GRID_2_COLUMNAS 1073
#define ID_GRID_3_COLUMNAS 1074
#define ID_MOSAICO_RESTAURAR 1075
#define ID_CONTROLHL7 1076
#define ID_CONTROLLOGS 1077
#define ID_CHECK_UPDATES 1078
#define ID_ONLINE_MANUAL 1079
#define ID_EXTENSIONS_SUPPORT 1081
#define ID_OPEN_TEST_CARD 1082

#define MAIN_WINDOW_ID "GinkgoCADxMain"

//////////////////////////
#if defined(GINKGO_PRO)
int InitTest(const std::string& pathTests);
/**
launches cppunit tests
*/
class TestLauncher: public wxThread
{
public:
	TestLauncher(const std::string& pathTests) :m_path(pathTests)
	{
	}
	virtual void *Entry() 
	{
		LOG_INFO("INITWX", "Launching from external thread");
		InitTest(m_path);
		LOG_INFO("INITWX", "tests complete, launching closing command");

		class CloseCommand: public GADAPI::ISynchronizedWithGUI
		{
			virtual void ExecuteSynchronized(GADAPI::ISynchronizedData* )
			{
				LOG_INFO("INITWX", "Closing Ginkgo CADx...");
				GNC::Entorno::Instance()->GetVentanaPrincipal()->Close(true);
				wxExit();
				exit(0);
			}
		};
		GADAPI::CommandSynchronizeWithGUI* pCmd = new GADAPI::CommandSynchronizeWithGUI(new CloseCommand());
		GNC::CommandController::Instance()->ProcessAsync("", pCmd, NULL);
		LOG_INFO("INITWX", "closing command launched");
		
		return NULL;
	}
	std::string m_path;
};
#endif
///////////

class wxGinkgoAuiNoteBook: public wxAuiNotebook
{
public:
	wxGinkgoAuiNoteBook(): wxAuiNotebook()
	{ }

    wxGinkgoAuiNoteBook(wxWindow* parent,
                  wxWindowID id = wxID_ANY,
                  const wxPoint& pos = wxDefaultPosition,
                  const wxSize& size = wxDefaultSize,
				  long style = wxAUI_NB_DEFAULT_STYLE): wxAuiNotebook(parent, id, pos, size, style)
    { 
    }

    virtual ~wxGinkgoAuiNoteBook()
	{
	}
	//hack to expose this method
	virtual wxAuiTabCtrl* GetActiveTabCtrl()
	{
		return wxAuiNotebook::GetActiveTabCtrl();
	}
};

////


EventoProgreso::EventoProgreso(TipoProgreso tipo, long threadId)
{
	SetEventType(wxEVT_PROGRESO);
	m_Tipo = tipo;
	m_ThreadId = threadId;
}

EventoProgreso::EventoProgreso(const EventoProgreso& event) : wxEvent(event), m_Tipo(event.m_Tipo), m_ThreadId(event.m_ThreadId)
{
}

EventoProgreso::~EventoProgreso()
{
}

wxEvent* EventoProgreso::Clone() const
{
	return new EventoProgreso(*this);
}

IMPLEMENT_DYNAMIC_CLASS(EventoProgreso, wxEvent)

// Mapeo de eventos

BEGIN_EVENT_TABLE(VentanaPrincipal, VentanaPrincipalBase)
EVT_CLOSE(VentanaPrincipal::OnWindowClose)
EVT_MENU(ID_Inicio_Aplicacion, VentanaPrincipal::OnInicioAplicacion)
END_EVENT_TABLE()

VentanaPrincipal::VentanaPrincipal(wxWindow* pParent, const wxString& title) : VentanaPrincipalBase(pParent, wxID_ANY, title), m_mgr(m_pPanelCentral, wxAUI_MGR_ALLOW_FLOATING | wxAUI_MGR_TRANSPARENT_DRAG | wxAUI_MGR_VENETIAN_BLINDS_HINT ),
	StartupView(NULL)
{
	//load attributes
	GNC::GCS::WindowAttributesController::LoadWindowAttributes(MAIN_WINDOW_ID, this, true);
	//

    //SetDoubleBuffered(true);
	m_Iniciada = false;
	m_VersionChecked = false;
	wxIcon icono;
	icono.CopyFromBitmap(GinkgoResourcesManager::Logos::GetLogoGinkgo32x32());
	this->SetIcon(icono);

	m_TratandoDeCerrar = false;
	m_SuperFreezeCount = 0;

	disabler = NULL;

	GNC::Entorno* pEntorno = GNC::Entorno::Instance();

	pEntorno->SetVentanaPrincipal(this);
	pEntorno->SetVentanaRaiz(m_pPanelCentral);

	SetAutoLayout(true);

	// Subscripción a la notificación de carga y descarga de extensiones
	pEntorno->ExtensionsObservers.push_back(this);

	// Subscripción a la notificación de activación y desactivación de vistas/estudios
	pEntorno->ViewsObservers.push_back(this);
	
	m_mgr.SetDockSizeConstraint(0.5f, 0.5f);

	//menu and tool bar
	m_pMenuBar = new wxMenuBar( wxMB_DOCKABLE );
	//

	GNC::GUI::StatusBarProgreso* pStatusBar = new GNC::GUI::StatusBarProgreso(this, m_pPanelCentral, true);
	SetStatusBar(pStatusBar);

	{
		wxString wxCaption = _("Tasks");
		wxAuiPaneInfo pi(wxAuiPaneInfo().Caption(wxCaption).Float().BestSize(400,170).MinSize(200,100).Resizable(true).CloseButton(true).Show(false));
		pi.DestroyOnClose(false);
		m_mgr.AddPane(pStatusBar->m_pPanelTareas, pi);
	}

	GNC::CommandController::Instance()->RegistrarProgreso(pStatusBar);
	Connect(wxEVT_PROGRESO, EventoProgresoFunctionHandler(VentanaPrincipal::OnComando), NULL, this);

	m_pNoteBook = new wxGinkgoAuiNoteBook(m_pPanelCentral, wxID_ANY,wxDefaultPosition,
												  wxDefaultSize,
												  wxAUI_NB_TAB_SPLIT |  wxAUI_NB_TAB_MOVE | wxAUI_NB_SCROLL_BUTTONS | wxAUI_NB_WINDOWLIST_BUTTON | wxAUI_NB_CLOSE_ON_ALL_TABS | wxEXPAND );
	m_pNoteBook->SetBackgroundColour(wxColour(0, 0, 0));
	m_pNoteBook->Connect( wxEVT_CHILD_FOCUS, wxChildFocusEventHandler( VentanaPrincipal::OnNotebookFocus ) );

	m_mgr.AddPane(m_pNoteBook, wxAuiPaneInfo().Name(wxT("vistas")).CenterPane().Layer(0).PaneBorder(true).Movable(false).Floatable(false).Dockable(false).LeftDockable(false).RightDockable(false).TopDockable(false).BottomDockable(false).CloseButton(false).Hide());
	//

	wxString wxCaption;
	m_mgr.Update();


	//hay que conectarlo al auimanager, porque el notebook delega el procesado de eventos al auimanager
	{
		m_mgr.Connect(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, wxAuiNotebookEventHandler(VentanaPrincipal::OnNotebookPageClose),NULL,this);
		m_mgr.Connect(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, wxAuiNotebookEventHandler(VentanaPrincipal::OnNotebookPageChanging), NULL, this);
		m_mgr.Connect(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, wxAuiNotebookEventHandler(VentanaPrincipal::OnNotebookPageChanged),NULL,this);
		m_mgr.Connect(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP, wxAuiNotebookEventHandler(VentanaPrincipal::OnNotebookMenuTab),NULL,this);
		m_mgr.Connect(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN, wxAuiNotebookEventHandler(VentanaPrincipal::OnNotebookCambiarTab),NULL,this);

		m_mgr.Connect(wxEVT_AUI_PANE_CLOSE, wxAuiManagerEventHandler(VentanaPrincipal::OnPanelClose),NULL,this);
	}

	SetDropTarget(new GNC::GUI::DropTargetMainWindow());

	Layout();

}

VentanaPrincipal::~VentanaPrincipal()
{
	m_pNoteBook->Disconnect( wxEVT_CHILD_FOCUS, wxChildFocusEventHandler( VentanaPrincipal::OnNotebookFocus ) );

	Disconnect(wxEVT_PROGRESO, EventoProgresoFunctionHandler(VentanaPrincipal::OnComando), NULL, this);
	GNC::CommandController::Instance()->RegistrarProgreso(NULL);
	GNC::GUI::DialogoAdquisicion::FreeInstance();
	GNC::GUI::GinkgoCloudSearchDialog::FreeInstance();
	GNC::GCS::ICommandController::Instance()->AbortarComandosDeOwner(NULL);
	//cierra la ventana si esta abierta
	GNC::GUI::VentanaControlHL7::CerrarSiAbierta();
	GNC::GUI::VentanaControlLogs::CerrarSiAbierta();

	{
		m_mgr.Disconnect(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, wxAuiNotebookEventHandler(VentanaPrincipal::OnNotebookPageClose),NULL,this);
		m_mgr.Disconnect(m_pNoteBook->GetId(), wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, wxAuiNotebookEventHandler(VentanaPrincipal::OnNotebookPageChanged),NULL,this);
	}


	this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( VentanaPrincipal::OnMenuCerrarTabClick ) );
	this->Disconnect( wxID_ANY, wxEVT_UPDATE_UI, wxUpdateUIEventHandler( VentanaPrincipal::OnMenuCerrarTabUpdateUI ) );
	this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( VentanaPrincipal::OnMenuCerrarTodosTabsClick ) );
	this->Disconnect( wxID_ANY, wxEVT_UPDATE_UI, wxUpdateUIEventHandler( VentanaPrincipal::OnMenuCerrarTodosTabsUpdateUI ) );
	this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( VentanaPrincipal::OnSalir ) );
	this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( VentanaPrincipal::OnConfiguracion ) );
	this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( VentanaPrincipal::OnMensajesHL7 ) );
	this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( VentanaPrincipal::OnControlLogs ) );
	this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( VentanaPrincipal::OnAcercaDe ) );
	this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( VentanaPrincipal::OnPantallaCompleta ) );
	this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( VentanaPrincipal::OnMosaicoRestaurar ) );

	//delete history tools
	GNC::HistoryToolsController::Instance()->UnRegisterAll();

	//
	GNC::Entorno* pEntorno = GNC::Entorno::Instance();

	GNC::ControladorExtensiones::Instance()->DesRegistrarModulos();
	GNC::GCS::ControladorVistas::FreeInstance();
	m_mgr.UnInit();
	pEntorno->ExtensionsObservers.remove(this);
	pEntorno->ViewsObservers.remove(this);
	pEntorno->SetVentanaPrincipal(NULL);
	pEntorno->SetVentanaRaiz(NULL);

	//save attributes
	GNC::GCS::WindowAttributesController::SaveWindowAttributes(MAIN_WINDOW_ID, this);
}

//region "Eventos de comprobacion de actualizaciones"
void VentanaPrincipal::ComprobarActualizaciones()
{
	bool check;
	GNC::GCS::ConfigurationController::Instance()->readBoolGeneral("/GinkgoCore/Estacion", "CheckForUpdates", check, true);
	if (check) {
		m_VersionChecked = false;
		//this is the profile
		GNC::GCS::Permisos::EstadoPermiso updates = GNC::GCS::IControladorPermisos::Instance()->Get("core.update","check_updates");
		if (updates) {
			bool tryCheck = false;
			std::string lastDateStr;
			if (GNC::GCS::ConfigurationController::Instance()->readStringGeneral("/GinkgoCore/LastUpdateDateTime", "LastDate", lastDateStr)) 
			{
				GNC::GCS::Permisos::EstadoPermiso period = GNC::GCS::IControladorPermisos::Instance()->Get("core.update","update_period");
				std::string periodStr = period.ObtenerValor<std::string>();
				long iPeriod;
				if (!wxString::FromUTF8(periodStr.c_str()).ToLong(&iPeriod)) {
					iPeriod = 2;
				}

				wxDateTime lastDate;

				lastDate.ParseFormat(wxString::FromUTF8(lastDateStr.c_str()), wxT("%d/%m/%Y %H:%M:%S"));
				if (!lastDate.IsValid()) {
					lastDate = wxDateTime::Now();
					lastDate.Subtract( wxDateSpan(0, 0, 0, iPeriod + 1 ) );
				}

				if (wxDateTime::Now().Subtract(lastDate).GetDays() > iPeriod) {
					tryCheck = true;
					GNC::GCS::ICommandController::Instance()->ProcessAsync(_Std("Check Updates"),
						new GNC::ComandoComprobarActualizaciones(new GNC::ComandoComprobarActualizacionesParams(updates.ObtenerValor<std::string>(), false) ), this);
				}

			} else {
				//if there is no date in the ini file update will be checked
				GNC::GCS::ICommandController::Instance()->ProcessAsync(_Std("Check Updates"),
					new GNC::ComandoComprobarActualizaciones(new GNC::ComandoComprobarActualizacionesParams(updates.ObtenerValor<std::string>(), false) ), this);
				tryCheck = true;
			}

			if (tryCheck) {
				//writes date
				GNC::GCS::ConfigurationController::Instance()->writeStringGeneral("/GinkgoCore/LastUpdateDateTime", "LastDate", std::string(wxDateTime::Now().Format(wxT("%d/%m/%Y %H:%M:%S")).ToUTF8()));
			}
		}
	}

}

void VentanaPrincipal::OnDoNotWarnAgainClicked( wxCommandEvent& /*event*/ )
{
	if (m_VersionChecked) {
		wxString valor;
		if (m_pDoNotWarnAgain->GetValue()) {
			GNC::GCS::ConfigurationController::Instance()->writeStringGeneral("/GinkgoCore/SkipUpdate", m_VersionCheck, "1");
		}
		else{
			GNC::GCS::ConfigurationController::Instance()->writeStringGeneral("/GinkgoCore/SkipUpdate", m_VersionCheck, "0");
		}
		GNC::GCS::ConfigurationController::Instance()->Flush();
	}

}

void VentanaPrincipal::OnVersionNotifierClose( wxCommandEvent& /*event*/ )
{
	wxWindowDisabler dis;
	SuperFreeze();
	m_pPanelActualizacion->Hide();
	//m_pPanelCentral->Layout();
	Layout();
	Refresh(true);
	SuperThaw();

}
//endregion



void VentanaPrincipal::ForzarCambioVista(GNC::GCS::IVista* pVistaCambiar)
{
	//se cambia la pestaña
	//bool cerrar = true;

	this->SetFocus();
	GNC::GCS::ControladorVistas* pcv = GNC::GCS::ControladorVistas::Instance();
	if (pcv == NULL) {
		std::cerr << "Error: No se pudo obtener el controlador de vistas" << std::endl;
		return ;
	}

	if (pcv->GetVistaActiva() != pVistaCambiar) {
		pcv->SolicitarActivarVista(pVistaCambiar);
	}

	for (GNC::GCS::ControladorVistas::MapaVentanas::iterator it = pcv->m_MapaVentanas.begin(); it != pcv->m_MapaVentanas.end(); ++it) {
		wxWindow* pVentana = (*it).first;
		GNC::GCS::IVista*   pVista = (*it).second;
		if (pVentana != NULL && pVista != NULL) {
			if (pVistaCambiar == pVista) {
				//Tenemos la ventana, la vista y el estudio
				//primero cambiamos de pestaña
				int selection = m_pNoteBook->GetPageIndex(pVentana);
				if (m_pNoteBook->IsShown() && selection >= 0) {
					if(selection >= 0 && selection != m_pNoteBook->GetSelection()){
						wxWindowDisabler dis;
						SuperFreeze();
						m_pNoteBook->SetSelection(selection);
						SuperThaw();
						return;
					}
				} else {
					//desencajado
					GNC::GUI::DetachedDialog* pDialogo = dynamic_cast<GNC::GUI::DetachedDialog*> (pVentana->GetParent());
					if(pDialogo != NULL) {
						if (pDialogo->IsIconized()) {
							pDialogo->Iconize(false);
						}
						pDialogo->Raise();
					}
				}
			}
		}
	}
}

void VentanaPrincipal::OnSalir(wxCommandEvent& WXUNUSED(event))
{
	SuperFreeze();
	Close();
	SuperThaw();
}
void VentanaPrincipal::OnAcercaDe(wxCommandEvent& WXUNUSED(event))
{
	AboutDialog* dlg = new AboutDialog(this);
	dlg->ShowModal();
}


void VentanaPrincipal::OnOnlineHelp(wxCommandEvent& /*event*/)
{
	GNC::GCS::Permisos::EstadoPermiso manual = GNC::GCS::IControladorPermisos::Instance()->Get("core.help","url_manual");
	wxString urlManual = wxString::FromUTF8(manual.ObtenerValor<std::string>().c_str());
	if (urlManual != wxEmptyString) {
		if (urlManual.StartsWith(wxT("http://"))) {
			wxLaunchDefaultBrowser(urlManual);
		} else {
			urlManual.Replace(wxT("\\"), wxString(wxFileName::GetPathSeparator()));
			wxFileName executable_path = wxStandardPaths::Get().GetExecutablePath();
			wxString pathDocument = executable_path.GetPath() + wxFileName::GetPathSeparator() + urlManual;
			wxFileType* fileType = wxTheMimeTypesManager->GetFileTypeFromMimeType(wxT("application/pdf"));
			if (fileType == NULL) {
				wxMessageBox(_("There isn't any pdf reader registered in the system"), _("Info"), wxICON_WARNING|wxOK);
				return;
			}

			wxString openCmd = fileType->GetOpenCommand(pathDocument);
			if (!openCmd.IsEmpty()) {
				wxExecute(openCmd);
			} else {
				wxMessageBox(_("There isn't any pdf reader registered in the system"), _("Info"), wxICON_WARNING|wxOK);
			}
			
			delete fileType;
		}
	}
}

void VentanaPrincipal::OnOnlineSupport(wxCommandEvent& /*event*/)
{
	GNC::GCS::Permisos::EstadoPermiso updates = GNC::GCS::IControladorPermisos::Instance()->Get("core.help","url_support");
	wxString urlSupport = wxString::FromUTF8(updates.ObtenerValor<std::string>().c_str());
	if (urlSupport != wxEmptyString) {
		wxLaunchDefaultBrowser(urlSupport);
	}
}

void VentanaPrincipal::OnOpenTestCard(wxCommandEvent& /*event*/)
{
	wxFileName cpath = FROMPATH(GNC::GCS::IEntorno::Instance()->GetGinkgoResourcesDir()) + wxFileName::GetPathSeparator() + wxT("test_card.dcm");
	std::string stdpath(cpath.GetFullPath().ToUTF8());
	GADAPI::ComandoIncluirHistorial::ComandoIncluirHistorialParams* pParams = new GADAPI::ComandoIncluirHistorial::ComandoIncluirHistorialParams(stdpath, false, GNC::GCS::IHistoryController::TAA_LINK);
	pParams->m_abrirDespuesDeCargar = true;
	GADAPI::ComandoIncluirHistorial::ComandoIncluirHistorial* pCmd = new GADAPI::ComandoIncluirHistorial::ComandoIncluirHistorial(pParams);
	GNC::Entorno::Instance()->GetCommandController()->ProcessAsync(_Std("Included in the history ..."),pCmd, NULL);
}

/* Evento de lanzamiento de la comprobacion de actualizaciones */
void VentanaPrincipal::OnCheckForUpdates(wxCommandEvent& /*event*/)
{
	m_VersionChecked = false;
	GNC::GCS::Permisos::EstadoPermiso updates = GNC::GCS::IControladorPermisos::Instance()->Get("core.update","check_updates");
	if (updates.ObtenerValor<std::string>().empty()) {
		wxMessageBox(_("There is no URL to check updates on the current configuration."), _("Check update error"),wxICON_ERROR);
	}
	else {
		GNC::GCS::ICommandController::Instance()->ProcessAsync(_Std("Check Updates"),
			new GNC::ComandoComprobarActualizaciones(new GNC::ComandoComprobarActualizacionesParams(updates.ObtenerValor<std::string>(), true) ), this);

		GNC::GCS::ConfigurationController::Instance()->writeStringGeneral("/GinkgoCore/LastUpdateDateTime", "LastDate", std::string(wxDateTime::Now().Format().ToUTF8()));
	}
}

/*startup page*/


class DialogoComandosEnEjecucion: public DialogoComandosEnEjecucionBase
{
public:
	DialogoComandosEnEjecucion(wxWindow* pParent, std::list<std::string>& listaNombres) : DialogoComandosEnEjecucionBase(pParent)
	{
		for (std::list<std::string>::iterator it = listaNombres.begin(); it!= listaNombres.end(); ++it) {
			m_pListacomandos->Append(wxString::FromUTF8((*it).c_str()));
		}
		Layout();
	}

	~DialogoComandosEnEjecucion()
	{
	}
};

void VentanaPrincipal::OnWindowClose(wxCloseEvent& event) {
#if defined (_WINDOWS)
	wxWindowDisabler* dis = new wxWindowDisabler();
#endif
	SuperFreeze();

	GNC::CommandController::ListaNombreComandos comandos =  GNC::CommandController::Instance()->GetComandosActivos();
	if(comandos.size()>0 && event.CanVeto()) {
		DialogoComandosEnEjecucion dlg(this,comandos);
#if defined (_WINDOWS)
		delete dis;
		dis = NULL;
#endif
		this->SuperThaw();
		int answer = dlg.ShowModal();
#if defined (_WINDOWS)
		dis = new wxWindowDisabler();
#endif
		this->SuperFreeze();
		if(answer != wxID_OK) {
			event.Veto(true);
#if defined (_WINDOWS)
			delete dis;
#endif
			this->SuperThaw();
			return;
		}
	}

	GNC::GCS::ICommandController::Instance()->AbortarComandosDeOwner(this);

	if(CerrarTodosLosTabsYPanelGrids()) {
		//cerramos todos las ventanas flotantes que podamos haber abierto...
		int numeroVistas = GNC::GCS::ControladorVistas::Instance()->GetVistas().size();
		while (numeroVistas == (int)GNC::GCS::ControladorVistas::Instance()->GetVistas().size() && GNC::GCS::ControladorVistas::Instance()->GetVistas().size()>0) {
			wxWindow* ventana = GNC::GCS::ControladorVistas::Instance()->GetVistas().front()->GetWindow();
			GNC::GUI::DetachedDialog* pDialogo = dynamic_cast<GNC::GUI::DetachedDialog*> (ventana->GetParent());
			if(pDialogo != NULL) {
				if(!pDialogo->Close() && event.CanVeto()){
					event.Veto(true);
					break;
				}
			}
			numeroVistas --;
		}
		if(GNC::GCS::ControladorVistas::Instance()->GetVistas().size() != 0 && event.CanVeto()) {
			event.Veto(true);
		} else {
			this->Destroy();
		}
	} else {
		//si quedan tabs o panelgrids
		if (event.CanVeto()) {
			event.Veto(true);
		}
	}
	SuperThaw();
	if (!event.GetVeto()) {
		GNC::Entorno::Instance()->SetVentanaPrincipal(NULL);
		GNC::Entorno::Instance()->SetVentanaRaiz(NULL);
	}
#if defined(_WINDOWS)
	delete dis;
#endif
}

#ifdef __WXMAC__
void VentanaPrincipal::MacOpenFile(const wxString &fileName) {
	try{
		std::list<std::string> ruta;
		ruta.push_back(std::string(fileName.ToUTF8()));
		//m_pHistorial->CargarDICOM(ruta,true);
	}
	catch(GIL::DICOM::I2DException& i){
		LOG_ERROR("Principal", "Error al cargar fichero: " << i.str());
	}
}
#endif


/* Evento de configuracion */
void VentanaPrincipal::OnConfiguracion(wxCommandEvent& /*event*/){

	GNC::GUI::DialogoConfiguracion config(this);
	config.ShowModal();
}

/*Evento de ventana de control de envio HL7*/
void VentanaPrincipal::OnMensajesHL7(wxCommandEvent& /*event*/)
{
	GNC::GUI::VentanaControlHL7* ventana = GNC::GUI::VentanaControlHL7::Instance();
	if(!ventana->IsActive()) {
		ventana->RequestUserAttention();
	}
}

/*Evento de ventana de control de registros (Logs)*/
void VentanaPrincipal::OnControlLogs(wxCommandEvent& /*event*/)
{
	GNC::GUI::VentanaControlLogs* ventana = GNC::GUI::VentanaControlLogs::Instance();
	if(!ventana->IsActive()) {
		ventana->RequestUserAttention();
	}
}

/* Evento de aplicacion de herramienta*/
void VentanaPrincipal::OnAplicarHerramienta(wxCommandEvent& /*event*/){
	/*
	GNC::GCS::IControladorHerramientas* cH = GNC::Entorno::Instance()->GetControladorHerramientas();
	GNC::GCS::ITool* herr = NULL;
	try {
		// Subscribimos la vista al contrato de herr
		herr= cH->ObtenerHerramienta(event.GetId());
		if(herr!=NULL){
			herr->SolicitarActivacion(GNC::GCS::TriggerButton().EnableLeft());
		}
	}
	catch (GNC::GCS::ControladorHerramientasException& ex) {
		std::cerr << "Error al obtener la herramienta puntero: No se pudo subscribir la herramienta: " << ex.GetCause() << std::endl;
	}
	event.Skip(false);
	*/
}

void VentanaPrincipal::OnUpdateUIHerramienta(wxUpdateUIEvent& /*event*/)
{
	/*
	GNC::GCS::IControladorHerramientas* cH = GNC::Entorno::Instance()->GetControladorHerramientas();
	GNC::GCS::ITool* herr = NULL;
	try {
		// Subscribimos la vista al contrato de herr
		herr = cH->ObtenerHerramienta(event.GetId());
		if(herr!=NULL){
			event.Enable(herr->Habilitada());
			event.Show(herr->Habilitada());
		}
		else{
			event.Enable(false);
			event.Show(false);
		}
	}
	catch (GNC::GCS::ControladorHerramientasException& ex) {
		std::cerr << "Error al obtener la herramienta puntero: No se pudo subscribir la herramienta: " << ex.str() << std::endl;
	}
	event.Skip(true);
	*/
}

/* Eventos de teclado */
void VentanaPrincipal::OnKeyDown(wxKeyEvent& event)
{
	GNC::GCS::IVista* pVista = GNC::GCS::ControladorVistas::Instance()->GetVistaActiva();
	if(pVista != NULL)
	{
		wxKeyEvent evt = event;
		wxWindow* win = pVista->GetWindow();
		if (win) {
			win->GetEventHandler()->AddPendingEvent(evt);
		}
		event.Skip(false);
	}
	else {
		event.Skip(true);
	}
}

void VentanaPrincipal::OnMenuCerrarTabClick(wxCommandEvent& )
{
	GNC::GCS::IVista* pVista = GNC::GCS::ControladorVistas::Instance()->GetVistaActiva();
	if(pVista != NULL)
	{
		wxWindow* pVentana = pVista->GetWindow();
		if(pVentana != NULL) {
			if(m_pNoteBook->GetPageIndex(pVentana) >= 0 && m_pNoteBook->GetSelection()!=-1)
			{
				wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON, m_pNoteBook->GetSelection());
				evt.SetInt(wxAUI_BUTTON_CLOSE);
				evt.SetId(5380+500);
				evt.SetEventObject(((wxGinkgoAuiNoteBook*)m_pNoteBook)->GetActiveTabCtrl());
				m_pNoteBook->GetEventHandler()->ProcessEvent(evt);
			}
		}
	}
}

void VentanaPrincipal::OnMenuCerrarTodoExceptoActiva(wxCommandEvent& )
{
	/*NO ESTA CORRECTO
	 unsigned int pestanias = m_pNoteBook->GetPageCount();
	 //la segunda condicion es para que si das a cancelar pues pare
	 unsigned int tabActual = pestanias - 1;
	 while(m_pNoteBook->GetPageCount() > 1 && pestanias == m_pNoteBook->GetPageCount()){
	 if(m_pNoteBook->GetPage(tabActual) == m_pNoteBook->GetActiveTabCtrl()){

	 } else {
	 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON, m_pNoteBook->GetPage(tabActual)->GetId());
	 evt.SetInt(wxAUI_BUTTON_CLOSE);
	 evt.SetEventObject(m_pNoteBook->GetPage(tabActual));
	 m_pNoteBook->GetEventHandler()->ProcessEvent(evt);
	 pestanias --;
	 }
	 }	*/

}

void VentanaPrincipal::OnMenuCerrarTodosTabsClick(wxCommandEvent& )
{
	CerrarTodosLosTabsYPanelGrids();
}

//devuelve bool si ha cerrado todos
bool VentanaPrincipal::CerrarTodosLosTabsYPanelGrids() {
	bool todosCerrados = false;
	unsigned int pestanias = m_pNoteBook->GetPageCount();
	//la segunda condicion es para que si das a cancelar pues pare	
	while(m_pNoteBook->GetPageCount() > 0 && pestanias == m_pNoteBook->GetPageCount()){
		wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON, m_pNoteBook->GetSelection());
		evt.SetInt(wxAUI_BUTTON_CLOSE);
		evt.SetId(5380+500);
		evt.SetEventObject(((wxGinkgoAuiNoteBook*)m_pNoteBook)->GetActiveTabCtrl());
		m_pNoteBook->GetEventHandler()->ProcessEvent(evt);
		pestanias --;
	}

	if(m_pNoteBook->GetPageCount() == 0) {
		//se cierran los paneles tabs...
		todosCerrados = true;
	}

	// Se han eliminado todas las paginas
	//se muestra el mosaico
	ShowStartUp(todosCerrados);

	return todosCerrados;
}

bool VentanaPrincipal::ClosesAllUndocked()
{
	std::list<GNC::GUI::DetachedDialog*> listaDesencajados;
	GNC::GCS::ControladorVistas::TipoListaVistas viewsList = GNC::GCS::ControladorVistas::Instance()->GetVistas();
	for (GNC::GCS::ControladorVistas::TipoListaVistas::iterator it = viewsList.begin(); it != viewsList.end(); ++it) {
		GNC::GUI::DetachedDialog* pPanel = dynamic_cast<GNC::GUI::DetachedDialog*> ((*it)->GetWindow()->GetParent());
		if(pPanel!=NULL) {
			listaDesencajados.push_back(pPanel);
		}
	}

	for (std::list<GNC::GUI::DetachedDialog*>::iterator it = listaDesencajados.begin(); it != listaDesencajados.end(); ++it)
	{
		if (!(*it)->Close())
		{
			return false;
		}
	}
	return true;
}

void VentanaPrincipal::OnMenuPrimerPlanoPestaniaActiva(wxCommandEvent& )
{
	if(m_pNoteBook->GetPageCount() > 0) {
		PasarAPrimerPlano(m_pNoteBook->GetPage(m_pNoteBook->GetSelection()));
	}
}

void VentanaPrincipal::OnMenuCerrarTabUpdateUI(wxUpdateUIEvent& event)
{
	event.Enable(m_pNoteBook->GetPageCount() > 0);
}

void VentanaPrincipal::OnMenuCerrarTodosTabsUpdateUI(wxUpdateUIEvent& event)
{
	event.Enable(m_pNoteBook->GetPageCount() > 0);
}


/*Eventos de impresion*/


void VentanaPrincipal::OnPantallaCompleta(wxCommandEvent& )
{
	this->ShowFullScreen(!this->IsFullScreen(),wxFULLSCREEN_NOBORDER|wxFULLSCREEN_NOCAPTION);
}

wxWindow* VentanaPrincipal::GetRootWindow() {
	return m_pPanelCentral;
}

void VentanaPrincipal::EncajarDesencajar(GNC::GCS::IVista* pVista) {
	if(pVista != NULL)
	{
		wxWindow* pVentana = pVista->GetWindow();
		if(pVentana != NULL) {
			GNC::GCS::ControladorVistas::Instance()->SolicitarActivarVista(NULL);
			//la buscamos en el notebook
			if(m_pNoteBook->GetPageIndex(pVentana) >= 0){
				GNC::GUI::DetachedDialog* pDlg;
				{
#if defined (_WINDOWS)
					wxWindowDisabler dis;
#endif

					SuperFreeze();
					wxString caption = m_pNoteBook->GetPageText(m_pNoteBook->GetPageIndex(pVentana));
					wxString titulo = m_pNoteBook->GetPageText(m_pNoteBook->GetPageIndex(pVentana));

					m_pNoteBook->RemovePage(m_pNoteBook->GetPageIndex(pVentana));

					if (m_pNoteBook->GetPageCount() == 0) {
						ShowStartUp(true);
					}

					pDlg = new GNC::GUI::DetachedDialog(this, this);
					pDlg->AddPanel(pVentana, titulo);

					m_mgr.Update();
					pDlg->Show(true);
					SuperThaw();

				}
			} else { //esta desencajada => la encajamos
				GNC::GUI::DetachedDialog* pDlg = dynamic_cast<GNC::GUI::DetachedDialog*>(pVentana->GetParent());
				if(pDlg != NULL)
				{
#if defined (_WINDOWS)
					wxWindowDisabler dis;
#endif
					pDlg->Show(false);
					pDlg->GetSizer()->Detach(pVentana);
					SuperFreeze();
					//encajar!
					//encajar en el notebook
					ShowStartUp(false);
					pVentana->Reparent(m_pNoteBook);
					m_pNoteBook->AddPage(pVentana, pDlg->GetTitulo());
					pDlg->Destroy();
					m_pNoteBook->Refresh();
					m_mgr.GetPane(m_pNoteBook).Show(true);
					m_mgr.Update();
					SuperThaw();
				}
			}
			GNC::GCS::ControladorVistas::Instance()->SolicitarActivarVista(pVista);
		}
	}
}


void VentanaPrincipal::ShowStartUp(bool show) 
{
	bool update = false;
	if (StartupView == NULL) {
		return;
	}
	if (StartupView->GetWindow()->IsShown() != show) {
		m_mgr.GetPane(StartupView->GetWindow()).Show(show);
		update = true;
	}
	if (show) {
		GNC::GCS::ControladorVistas::Instance()->SolicitarActivarVista(StartupView);
	}
	if (m_pNoteBook->IsShown() == show) {
		m_mgr.GetPane(m_pNoteBook).Show(!show);
		update = true;
		m_pNoteBook->Refresh(false);
	}
	if (update) {
		m_mgr.Update();
	}
}

void VentanaPrincipal::OnMosaicoRestaurar(wxCommandEvent& )
{
	wxWindowDisabler disabler;
	SuperFreeze();
	ReplegarPestanias();
	m_mgr.Update();
	SuperThaw();
}

void VentanaPrincipal::ReplegarPestanias()
{
	//remember the tab now selected
	int nowSelected = m_pNoteBook->GetSelection();
	//select first tab as destination
	m_pNoteBook->SetSelection(0);
	//iterate all other tabs
	for( unsigned int idx = 0; idx < m_pNoteBook->GetPageCount(); idx++){
		//get win reference
		wxWindow* win = m_pNoteBook->GetPage(idx);
		//get tab title
		wxString title = m_pNoteBook->GetPageText(idx);
		//remove from notebook
		m_pNoteBook->RemovePage(idx);
		//re-add in the same position so it will tab
		m_pNoteBook->InsertPage(idx, win, title);
	}
	//restore orignial selected tab
	m_pNoteBook->SetSelection(nowSelected);
}

/* Añade una nueva pestaña al panel de estudios */
void VentanaPrincipal::InsertarVentana(wxWindow* pVentana)
{
	wxWindowDisabler disabler;
	SuperFreeze();
	ShowStartUp(false);

	m_pNoteBook->AddPage(pVentana, wxEmptyString, false);
	m_mgr.Update();
	SuperThaw();
}

/* Elimina un tab del panel de estudios */
void VentanaPrincipal::EliminarVentana(wxWindow *WXUNUSED(pVentana))
{
	std::cerr << "Error: Metodo no implementado VentanaPrincipal::EstudioRemoveTab(Tab* t)" << std::endl;
	throw new std::exception();
}

void VentanaPrincipal::OnInicioAplicacion(wxCommandEvent &) 
{	
	//parameters parsing...
	bool aceptedLicense = false;
	bool versionParameter = false;
	wxString pathOfFile = wxEmptyString;

	int argc = GNC::Entorno::Instance()->GetApp()->argc;
	wxChar** argv = GNC::Entorno::Instance()->GetApp()->argv;
	if (argc > 1) {
		for (int i = 1; i < argc; i++) {
			wxString param(argv[i]);

			if ( param.CmpNoCase(wxT("-version")) == 0 || param.CmpNoCase(wxT("--version")) == 0 || param.CmpNoCase(wxT("-v")) == 0 ) {
				versionParameter = true;
				continue;
			}
			if (param.CmpNoCase(wxT("--accepted")) == 0 || param.CmpNoCase(wxT("-a")) == 0) {
				aceptedLicense = true;
				continue;
			}
			#if defined(GINKGO_PRO)
			else if (param.CmpNoCase(wxT("-unittest")) == 0) {
				LOG_INFO("INITWX", "Running unitttests");
				if (argc <= i+1) {
					LOG_ERROR("INITWX", "no tests cases found for -unittest option. Usage -unittest <path_test_cases>");
				} else {
					i++;
					std::string pathTests = wxString(argv[i]).ToUTF8();
					TestLauncher* test = new TestLauncher(pathTests);
					test->Create();
					test->Run();
				}
				continue;
			}
			#endif
			if (!param.StartsWith("--")) {
				pathOfFile = param;
			}
		}
	}

	if (versionParameter) {
		std::cout << GNC::GCS::IEntorno::Instance()->GetGinkgoVersionString() << std::endl;
		GNC::GCS::IEntorno::FreeInstance();
		Close();
	}

	if (!aceptedLicense) 
	{
		//aceptacion de la licencia
		bool aceptada;
		GNC::GCS::ConfigurationController::Instance()->readBoolGeneral("/GinkgoCore/Licencia", "Aceptada", aceptada, false);
		if(!aceptada) {
			GNC::GUI::AcceptLicenseDialog dlgLicencia(NULL);
			wxYield();
			int answer = dlgLicencia.ShowModal();
			if(answer == wxID_OK) {
				GNC::GCS::ConfigurationController::Instance()->writeBoolGeneral("/GinkgoCore/Licencia", "Aceptada", true);
				GNC::GCS::ConfigurationController::Instance()->Flush();
			} else {
				GNC::GCS::ConfigurationController::Instance()->writeBoolGeneral("/GinkgoCore/Licencia", "Aceptada", false);
				GNC::GCS::ConfigurationController::Instance()->Flush();
				Close();
				return;
			}
		}
	}

	//si viene un parametro y es un directorio... abrir directamente
	if(!pathOfFile.empty())
	{
		Login();
		EjecutarParametro(pathOfFile, true);
	} else {
		Login();
	}
}

void VentanaPrincipal::EjecutarParametro(const wxString cadena, bool doLogin)
{
	std::string xmlString("");
	std::string errorMsg;

	bool error = false;
	
	if (cadena.Lower().StartsWith(wxT("ginkgocadx://"))) {
		try {
			xmlString = GIL::IntegrationController::Instance()->ParsesModelFromURL(cadena);
		} catch (GIL::IntegrationException& ex) {
			LOG_ERROR("GIL/WF", "Semantic/Sintactic error parsing integration url: " << ex.GetFullCause());
			wxMessageBox(_("Semantic/Sintactic error parsing integration URL (see log for details):\n") + wxString::FromUTF8(ex.GetCause().c_str()),_("Error"),wxICON_INFORMATION);
		}
	}
	else {

		wxFileName path = cadena;
		
	
		if (path.IsOk()) {
			LOG_DEBUG("Core", "Interpretando " << std::string(TOPATH(path.GetFullPath())).c_str());
			if (path.IsRelative()) {
				LOG_DEBUG("Core", "Convirtiendo ruta en absoluta");
				#if defined(__WXGTK__)
			
				char* invocation_dir = getenv("INVOCATION_DIR");					
				if (invocation_dir != NULL) {
					wxString invocationDir = wxString::FromUTF8(invocation_dir);
					if (!invocationDir.IsEmpty()) {
						path = invocationDir + wxFileName::GetPathSeparator() + path.GetFullPath();
					}
				}
				#else
				path.MakeAbsolute();
				#endif
				LOG_DEBUG("Core", "Ruta absoluta: " << std::string(TOPATH(path.GetFullPath())).c_str());
			}

			if(wxDirExists(path.GetFullPath()) && path.IsDirReadable()){
				if(doLogin) {
					Login();
				}
				std::list<std::string> rutas;
				rutas.push_back(std::string(TOPATH( path.GetFullPath() )));
				GADAPI::ComandoIncluirHistorial::ComandoIncluirHistorialParams* pParams = new GADAPI::ComandoIncluirHistorial::ComandoIncluirHistorialParams(rutas,true,GNC::GCS::IHistoryController::TAA_LINK);
				GADAPI::ComandoIncluirHistorial::ComandoIncluirHistorial* pCmd = new GADAPI::ComandoIncluirHistorial::ComandoIncluirHistorial(pParams);
				GNC::Entorno::Instance()->GetCommandController()->ProcessAsync(_Std("Included in the history ..."), pCmd, NULL);
				return ;
			} else if(path.FileExists() && path.IsFileReadable()){

				//estamos ante un fichero
				//se mira a ver si a partir del byte 128 pone DICM
				wxFile fichero(path.GetFullPath(), wxFile::read);

				bool esGzip = false;
				bool esDicom = false;
				if(fichero.IsOpened()){
					char buffer[128];
					if(fichero.Read(buffer,128) == 128){
						esGzip = ((unsigned char)buffer[0]==0x1f) && ((unsigned char)buffer[1]==0x8b);
						char numeroMagico[4];
						if(fichero.Read(numeroMagico,4) == 4){
							std::string str(numeroMagico,4);
							if(str == "DICM") {
								esDicom = true;
							}
						}
					}
				}
				if(esDicom) {
					if (doLogin) {
						Login();
					}
					//si no es un xml pues sera un dicom...
					std::list<std::string> rutas;
					rutas.push_back(std::string(TOPATH(path.GetFullPath()) ));
					GADAPI::ComandoIncluirHistorial::ComandoIncluirHistorialParams* pParams = new GADAPI::ComandoIncluirHistorial::ComandoIncluirHistorialParams(rutas,true,GNC::GCS::IHistoryController::TAA_LINK);
					GADAPI::ComandoIncluirHistorial::ComandoIncluirHistorial* pCmd = new GADAPI::ComandoIncluirHistorial::ComandoIncluirHistorial(pParams);
					GNC::Entorno::Instance()->GetCommandController()->ProcessAsync(_Std("Included in the history ..."),pCmd, NULL);			
				} else {				
					//se lee el modelo
					bool loaded = false;
					wxXmlDocument documento;
					if (esGzip) {
						wxFileInputStream* fileIn = new wxFileInputStream(path.GetFullPath());
						wxZlibInputStream zInput(fileIn);
						loaded = documento.Load(zInput);
					} else {
						loaded = documento.Load(path.GetFullPath());
					}
					if(loaded) {
						wxStringOutputStream out;
						documento.Save(out);
						xmlString=out.GetString().ToUTF8();
					} else {
						//dcmurl this is a file with a relative path...
						LOG_DEBUG("GIL/WF", "Try reading dcmurl file...");
						wxTextFile dcmURLFile;
						if (!dcmURLFile.Open(path.GetFullPath(), wxMBConvUTF8())) {
							for (wxString line = dcmURLFile.GetFirstLine(); !dcmURLFile.Eof(); line = dcmURLFile.GetNextLine()) {
								wxFileName fileName(line);
								if (fileName.IsRelative()) {
									fileName.MakeAbsolute(path.GetPath());
								}
								if (wxFileExists(fileName.GetFullPath())) {
									EjecutarParametro(fileName.GetFullPath());
								} else {
									LOG_ERROR("GIL/WF", "File doesn't exists");
									break;
								}
							}
						}
						LOG_ERROR("GIL/WF", "Error al interpretar el fichero de entrada: XML mal formado");
						wxMessageBox(_("Malformed XML"),_("Error"),wxICON_INFORMATION);
						if (doLogin) {
							Login();
						}
					}
				}
			}
			else {
				error = true;
			}
		}
		else {
			error = true;
		}
	}
	if (error) {
		LOG_ERROR("GIL/WF", "Error al interpretar los parámetros de la línea de comandos. (" << cadena.ToUTF8() << ") : " << errorMsg );
			wxMessageBox(
				_("Error in interpreting the parameters of the command line. (")
				+ cadena
				+ wxT(") : ")
				+ wxString::FromUTF8(errorMsg.c_str())
				,_("Error"), wxICON_INFORMATION);
			if (doLogin) {
				Login();
			}
			return;
	}


	if(xmlString != "") {
		try {
			GIL::IntegrationModelList listaModelos;	
			GIL::IntegrationController::Instance()->ParsearModeloIntegracion(listaModelos, xmlString, cadena);
			GIL::IntegrationController::Instance()->Process(listaModelos);
		}
		catch (GIL::IntegrationException& ex) {
			LOG_ERROR("GIL/WF", "Semantic/Sintactic error parsing integration XML: " << ex.GetFullCause());
			wxMessageBox(_("Semantic/Sintactic error parsing integration XML (see log for details):\n") + wxString::FromUTF8(ex.GetCause().c_str()),_("Error"),wxICON_INFORMATION);
		}
		catch (GIL::HL7::HL7XMLException& ex) {
			LOG_ERROR("GIL/WF", "Semantic/Sintactic error parsing integration XML: " << ex.GetFullCause());
			wxMessageBox(_("Semantic/Sintactic error parsing integration XML (see log for details):\n") + wxString::FromUTF8(ex.GetCause().c_str()),_("Error"),wxICON_INFORMATION);
		}
		catch (GIL::HL7::HL7Exception& ex1) {
			LOG_ERROR("GIL/WF", "Error parsing integration XML: " << ex1.GetCause());
			wxMessageBox(_("Error parsing integration XML:\n") + wxString::FromUTF8(ex1.GetCause().c_str()),_("Error"),wxICON_INFORMATION);
		}
		catch (GIL::DICOM::PACSException& ex3) {
			LOG_ERROR("GIL/WF", "PACS error: " << ex3.GetCause());
			wxMessageBox(_("PACS error:\n") + wxString::FromUTF8(ex3.GetCause().c_str()),_("Error"),wxICON_INFORMATION);
		}
		catch (std::exception& ex4) {
			LOG_ERROR("GIL/WF", "Error executing WorkFlow: " << ex4.what());
			wxMessageBox(_("Error executing WorkFlow\n") + wxString::FromUTF8(ex4.what()),_("Error"),wxICON_INFORMATION);
		}
		catch (...) {
			LOG_ERROR("GIL/WF", "Error executing WorkFlow: Internal error.");
			wxMessageBox(_("Error executing WorkFlow\nInternal Error"), _("Error"),wxICON_INFORMATION);
		}

		if (!m_Iniciada) {
			if (doLogin) {
				Login();
			}
		}
	}
	else {
		if (doLogin) {
			Login();
		}
	}
}

void VentanaPrincipal::OnSize(wxSizeEvent& WXUNUSED(event))
{
	Layout();
}


void VentanaPrincipal::RefrescarMenus()
{

	//se vacía la barra y se borran los menus que se crearon en la anterior pasada
    wxWindowDisabler dis;
    SuperFreeze();

	wxMenu* pMenuArchivo = new wxMenu();
	wxMenu* pMenuEdicion = new wxMenu();
	wxMenu* pMenuVer = new wxMenu();
	wxMenu* pMenuSeries = new wxMenu();
	wxMenu* pMenuHerramientas = new wxMenu();
	wxMenu* pMenuAyuda = new wxMenu();

	{
		//menu archivo
		wxMenuItem* m_pCerrar = new wxMenuItem( pMenuArchivo, ID_CERRAR, wxString( _("Close") ) + wxT("\tAlt+w"), _("Close current view"), wxITEM_NORMAL );
		wxMenuItem* m_pCerrarTodas = new wxMenuItem( pMenuArchivo, ID_CERRAR_TODAS, wxString( _("Close all") ) , _("Close all views"), wxITEM_NORMAL );
		wxMenuItem* m_pMenuSalir = new wxMenuItem( pMenuArchivo, ID_SALIR, wxString( _("&Exit") ) + wxT("\tAlt+s"), _("Exit application"), wxITEM_NORMAL );
#ifdef __WXMSW__
		m_pCerrar->SetBitmaps(GinkgoResourcesManager::MenuIcons::GetIcoCerrarTab());
		m_pMenuSalir->SetBitmaps(GinkgoResourcesManager::MenuIcons::GetIcoSalir());
	#else
		m_pCerrar->SetBitmap(GinkgoResourcesManager::MenuIcons::GetIcoCerrarTab());
		m_pMenuSalir->SetBitmap(GinkgoResourcesManager::MenuIcons::GetIcoSalir());
	#endif
		InsertToolsFromFamily(pMenuArchivo, GNC::GCS::ITool::TMenuArchivo);
		if (pMenuArchivo->GetMenuItemCount() > 0) 
		{
			pMenuArchivo->AppendSeparator();
		}
		pMenuArchivo->Append( m_pCerrar );
		pMenuArchivo->Append( m_pCerrarTodas );
		pMenuArchivo->AppendSeparator();		
		pMenuArchivo->Append( m_pMenuSalir );
		this->Connect( m_pCerrar->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( VentanaPrincipal::OnMenuCerrarTabClick ) );
		this->Connect( m_pCerrar->GetId(), wxEVT_UPDATE_UI, wxUpdateUIEventHandler( VentanaPrincipal::OnMenuCerrarTabUpdateUI ) );
		this->Connect( m_pCerrarTodas->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( VentanaPrincipal::OnMenuCerrarTodosTabsClick ) );
		this->Connect( m_pCerrarTodas->GetId(), wxEVT_UPDATE_UI, wxUpdateUIEventHandler( VentanaPrincipal::OnMenuCerrarTodosTabsUpdateUI ) );
		
		this->Connect( m_pMenuSalir->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( VentanaPrincipal::OnSalir ) );

		//edit
		InsertToolsFromFamily(pMenuEdicion, GNC::GCS::ITool::TMenuEdicion);

		//view
		{
			wxMenuItem*  pPantallaCompleta = new wxMenuItem( pMenuVer, ID_PANTALLA_COMPLETA, wxString(_("Full screen"))+ wxT("\tF11"), _("Show full screen"), wxITEM_NORMAL );
			wxMenuItem* pMosaicoRestaurar = new wxMenuItem(pMenuVer, ID_MOSAICO_RESTAURAR, wxString( _("Tab grouping") ), _("Tab grouping"), wxITEM_NORMAL );

			#ifdef __WXMSW__
			pMosaicoRestaurar->SetBitmaps(GinkgoResourcesManager::MenuTabs::GetIcoReagrupar());
			pPantallaCompleta->SetBitmaps(GinkgoResourcesManager::MenuIcons::GetIcoPantallaCompleta());
			#else
			pMosaicoRestaurar->SetBitmap(GinkgoResourcesManager::MenuTabs::GetIcoReagrupar());
			pPantallaCompleta->SetBitmap(GinkgoResourcesManager::MenuIcons::GetIcoPantallaCompleta());
			#endif
			pMenuVer->Append( pPantallaCompleta );
			pMenuVer->AppendSeparator();
			pMenuVer->Append(pMosaicoRestaurar);

			//image
			InsertToolsFromFamily(pMenuVer, GNC::GCS::ITool::TMenuVer);

			this->Connect( pPantallaCompleta->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( VentanaPrincipal::OnPantallaCompleta ) );
			this->Connect( pMosaicoRestaurar->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( VentanaPrincipal::OnMosaicoRestaurar ) );
		}

		//image
		InsertToolsFromFamily(pMenuSeries, GNC::GCS::ITool::TSeriesMenu);

		//tools
		InsertToolsFromFamily(pMenuHerramientas, GNC::GCS::ITool::TMenuHerramientas);

		//ayuda
		wxMenuItem*  pMenuGNKHelp = new wxMenuItem( pMenuAyuda, ID_ONLINE_MANUAL, wxString( _("Ginkgo CADx manual ...") ), _("Ginkgo CADx manual ..."), wxITEM_NORMAL );
		wxMenuItem*  m_pMenuOpenTestCard = new wxMenuItem( pMenuAyuda, ID_OPEN_TEST_CARD, wxString( _("Open test card") ), _("Open test card"), wxITEM_NORMAL );
		wxMenuItem*  m_pMenuCheckUpdates = new wxMenuItem( pMenuAyuda, ID_CHECK_UPDATES, wxString( _("Check for updates") ), _("Check for newest versions"), wxITEM_NORMAL );
		wxMenuItem*  pMenuOnlineSupport = new wxMenuItem( pMenuAyuda, ID_ONLINE_SUPPORT, wxString( _("Need support ...") ), _("Need support ..."), wxITEM_NORMAL );
		wxMenuItem*  m_pMenuAcercaDe = new wxMenuItem( pMenuAyuda, ID_ACERCA_DE,  _("About") + wxString(wxT(" ")) + wxString::FromUTF8(GNC::Entorno::Instance()->GetApplicationName().c_str()) + wxT(" ...") ,  _("About ") + wxString::FromUTF8(GNC::Entorno::Instance()->GetApplicationName().c_str()) + wxT(" ...") , wxITEM_NORMAL );

		#ifdef __WXMSW__
		pMenuGNKHelp->SetBitmaps(GinkgoResourcesManager::MenuIcons::GetIcoHelp());
		pMenuOnlineSupport->SetBitmaps(GinkgoResourcesManager::MenuIcons::GetIcoSupport());
		#else
		pMenuGNKHelp->SetBitmap(GinkgoResourcesManager::MenuIcons::GetIcoHelp());
		pMenuOnlineSupport->SetBitmap(GinkgoResourcesManager::MenuIcons::GetIcoSupport());
		#endif

		pMenuAyuda->Append( pMenuGNKHelp );
		pMenuAyuda->AppendSeparator();
		pMenuAyuda->Append( pMenuOnlineSupport );
		
		pMenuAyuda->AppendSeparator();		
		pMenuAyuda->Append( m_pMenuCheckUpdates );
		InsertToolsFromFamily(pMenuAyuda, GNC::GCS::ITool::TMenuHelp);
		pMenuAyuda->AppendSeparator();		
		pMenuAyuda->Append( m_pMenuOpenTestCard );
		pMenuAyuda->AppendSeparator();
		pMenuAyuda->Append( m_pMenuAcercaDe );

		this->Connect( pMenuGNKHelp->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( VentanaPrincipal::OnOnlineHelp ) );
		this->Connect( m_pMenuOpenTestCard->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( VentanaPrincipal::OnOpenTestCard ) );
		this->Connect( m_pMenuCheckUpdates->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( VentanaPrincipal::OnCheckForUpdates ) );
		this->Connect( m_pMenuAcercaDe->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( VentanaPrincipal::OnAcercaDe ) );
		this->Connect( pMenuOnlineSupport->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( VentanaPrincipal::OnOnlineSupport ) );
	}

	//herramientas -> configuracion, envio hl7 y logs
	if(GNC::GCS::IControladorPermisos::Instance()->Get("core.menu","configuracion")) {
		if(pMenuHerramientas->GetMenuItemCount() >0)
			pMenuHerramientas->AppendSeparator();
		wxMenuItem*  pMenuConfiguracion = NULL;
		wxMenuItem*  pMenuHL7 = NULL;
		wxMenuItem*  pMenuLogs = NULL;
		//herramientas
		pMenuConfiguracion = new wxMenuItem( pMenuHerramientas, ID_CONFIGURACION, wxString(_("Settings")) + wxT("\tAlt+c"), _("Settings"), wxITEM_NORMAL );
		pMenuHL7 = new wxMenuItem( pMenuHerramientas, ID_CONTROLHL7, wxString(_("HL7 monitor")) + wxT(""), _("HL7 message control"), wxITEM_NORMAL );
		pMenuLogs = new wxMenuItem( pMenuHerramientas, ID_CONTROLLOGS, wxString(_("Log monitor")) + wxT("\tAlt+r"), _("Log monitored"), wxITEM_NORMAL );

#ifdef __WXMSW__
		pMenuConfiguracion->SetBitmaps(GinkgoResourcesManager::MenuIcons::GetIcoConfiguracion());
#else
		pMenuConfiguracion->SetBitmap(GinkgoResourcesManager::MenuIcons::GetIcoConfiguracion());
#endif
		pMenuHerramientas->Append( pMenuLogs );
		pMenuHerramientas->Append( pMenuHL7 );
		pMenuHerramientas->AppendSeparator();
		pMenuHerramientas->Append( pMenuConfiguracion );
		
		this->Connect( pMenuConfiguracion->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( VentanaPrincipal::OnConfiguracion ) );
		this->Connect( pMenuHL7->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( VentanaPrincipal::OnMensajesHL7 ) );
		this->Connect( pMenuLogs->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( VentanaPrincipal::OnControlLogs ) );
	}
	//avoid hide bar => flickering!!
	m_pMenuBar->Freeze();
	m_pMenuBar->Append( pMenuArchivo, _("&File") );
	while (m_pMenuBar->GetMenuCount() > 1)
		delete m_pMenuBar->Remove(0);	
	m_pMenuBar->Append( pMenuEdicion, _("&Edit") );
	m_pMenuBar->Append( pMenuVer, _("View") );
	m_pMenuBar->Append( pMenuSeries, _("Series") );
	m_pMenuBar->Append( pMenuHerramientas, _("Tools") );
	m_pMenuBar->Append( pMenuAyuda, _("&Help") );
	
	m_pMenuBar->Thaw();
	this->SetMenuBar(m_pMenuBar);

#ifdef __WXMAC__
	wxMenuBar::MacSetCommonMenuBar(m_pMenuBar);
#endif
	SuperThaw();
}

void VentanaPrincipal::InsertToolsFromFamily(wxMenu* pParent, GNC::GCS::ITool::TToolFamily family)
{
	//general tools
	GNC::GCS::IToolsRegistry::Instance()->AppendsToolInMenu(this, pParent, family);

	GNC::GCS::IVista* pVistaActiva = GNC::GCS::ControladorVistas::Instance()->GetVistaActiva();
	if (pVistaActiva == NULL) {
		return;
	}

	GNC::GCS::IToolController* pToolController = pVistaActiva->GetToolController();
	pToolController->AppendsToolInMenu(this, pParent, family);
}

void VentanaPrincipal::CargarHistorial()
{
	GNC::GUI::HistoryPanel3::Instance();
	//if unittest... delete current history
	#if defined(GINKGO_PRO)
	int argc = GNC::Entorno::Instance()->GetApp()->argc;
	wxChar** argv = GNC::Entorno::Instance()->GetApp()->argv;
	for (int i = 1; i < argc; i++) {
		wxString param(argv[i]);
		if (param.CmpNoCase(wxT("-unittest")) == 0) {
			//drop file
			std::string dirPath = GNC::GCS::HistoryController::GetDefaultDicomDirPath();
			LOG_INFO("INITWX", "Removing default dicomdir:" << dirPath);
			GNC::GCS::IEntorno::Instance()->RemoveDirRecursive(dirPath);
			LOG_INFO("INITWX", "Default dicomdir removed successfully");
			break;
		}
	}
	#endif
	//

	if (!GNC::GCS::HistoryController::Instance()->IsOk()) {
		wxMessageBox(_("Error loading history, Ginkgo CADx will be closed"), _("Error"), wxICON_ERROR|wxOK, this);
		Close(true);
		return;
	}

	SuperFreeze();
	
	GNC::GUI::HistoryPanel3::Instance()->ReloadCombos(true);
	GNC::GUI::HistoryPanel3::Instance()->RefreshSearch(true);

	GNC::GCS::Ptr<GNC::GUI::StartUpStudy> study(new GNC::GUI::StartUpStudy());
	study->Module = NULL;
	study->ParentWindow = m_pPanelCentral;
	StartupView = new GNC::GUI::StartUpView(study);
	m_mgr.AddPane(StartupView->GetWindow(), wxAuiPaneInfo().Name(_("Mosaic")).CenterPane().Layer(0).PaneBorder(true).Movable(false).Floatable(false).Dockable(false).LeftDockable(false).RightDockable(false).TopDockable(false).BottomDockable(false).CloseButton(false));
	
	GNC::GCS::Ptr<GIL::IModeloIntegracion> ptr;
	GNC::Entorno::Instance()->GetControladorCarga()->CargaAsincrona(StartupView, false);
	m_mgr.Update();
	
	SuperThaw();
}

void VentanaPrincipal::OnComando(EventoProgreso& evento)
{
	switch (evento.GetTipo()) {
		case EventoProgreso::ComandoIniciado:
			GNC::CommandController::Instance()->OnComandoLanzado(evento.GetThreadId());
			break;
		case EventoProgreso::ComandoEjecutando:
			GNC::CommandController::Instance()->OnComandoProgreso(evento.GetThreadId());
			break;
		case EventoProgreso::ComandoFinalizado:
			GNC::CommandController::Instance()->OnComandoFinalizado(evento.GetThreadId());
			break;
		default:
			std::cerr << "Error, Tipo de notificacion de comando desconocida." << std::endl;
			break;
	}

}

void VentanaPrincipal::OnNotebookPageChanging(wxAuiNotebookEvent& /*event*/)
{
	/*
	int old_idx = event.GetOldSelection();
	int new_idx = event.GetSelection();

	if (old_idx != new_idx && old_idx != -1 && new_idx != -1) {

		wxWindowDisabler dis;
		SuperFreeze();

		m_pNoteBook->SetSelection(new_idx);

		SuperThaw();
	}

	event.Skip(false);
	*/
}


void VentanaPrincipal::OnNotebookPageChanged(wxAuiNotebookEvent& event)
{
	SuperFreeze();
	if (m_pNoteBook->GetPageCount() == 0) { // Se han eliminado todas las paginas
		ShowStartUp(true);
	}
	else
	{ // Se ha cambiado de pagina
		ShowStartUp(false);
		GNC::GCS::IVista* v  = GNC::GCS::ControladorVistas::Instance()->ObtenerVistaRegistrada(m_pNoteBook->GetPage(event.GetSelection()));
		if (v != NULL) {
			GNC::GCS::ControladorVistas::Instance()->SolicitarActivarVista(v);
		}
	}
	SuperThaw();

}

void VentanaPrincipal::OnPanelClose(wxAuiManagerEvent& event)
{
	wxWindowDisabler disabler;
	SuperFreeze();
	if(CerrarVista(event.GetPane()->window)) {
		GNC::GCS::ControladorVistas::Instance()->Destruir(event.GetPane()->window);
	}
	SuperThaw();
}


void VentanaPrincipal::OnNotebookPageClose(wxAuiNotebookEvent& event)
{
	wxWindowDisabler disabler;
	SuperFreeze();
	if(CerrarVista(m_pNoteBook->GetPage(event.GetSelection()))) {
		GNC::GCS::ControladorVistas::Instance()->Destruir(m_pNoteBook->GetPage(event.GetSelection()));
		if (m_pNoteBook->GetPageCount() == 1) { // Se han eliminado todas las paginas
			//se muestra el mosaico
			ShowStartUp(true);
		}
	} else {
		event.Veto();
	}
	SuperThaw();
}

void VentanaPrincipal::PasarAPrimerPlano(wxWindow* window)
{
	wxWindowDisabler disabler;
	SuperFreeze();
	ReplegarPestanias();
	int index = m_pNoteBook->GetPageIndex(window);
	if(index>0) {
		m_pNoteBook->SetSelection(index);
	}
	//este update es necesario porque pasar a primer plano viene cuando estan en pestanias y cuando estan en grid
	m_mgr.Update();
	SuperThaw();
}

void VentanaPrincipal::DestruirPanelVista(wxWindow* panel)
{
	wxAuiNotebook* padreNotebook = dynamic_cast<wxAuiNotebook*> (panel->GetParent());
	if(padreNotebook != NULL)
	{
		CerrarNotebookPage(panel);
	} else {
		GNC::GUI::DetachedDialog* pDialogo = dynamic_cast<GNC::GUI::DetachedDialog*> (panel->GetParent());
		if(pDialogo != NULL)
		{
			pDialogo->Close();
		}
	}
}

void VentanaPrincipal::CerrarNotebookPage(wxWindow* panel)
{
	int index = m_pNoteBook->GetPageIndex(panel);
	if (index < 0 ) {
		return;
	}

	SuperFreeze();
	if(CerrarVista(panel)) {
		m_pNoteBook->DeletePage(index);
		if (m_pNoteBook->GetPageCount() == 0) { // Se han eliminado todas las paginas
			//se muestra el mosaico
			ShowStartUp(true);
		}
		m_mgr.Update();
	}
	SuperThaw();
}

bool VentanaPrincipal::CerrarVista(GNC::GCS::IVista* pVista)
{
	if (pVista == NULL)
		return true;

	//it's important to avoid focus errors
	if (this->IsIconized()) {
		this->Restore();
	}
	this->Raise();

	wxWindow* pWindow = pVista->GetWindow();
	//if it's a tab...
	int idx = m_pNoteBook->GetPageIndex(pWindow);
	if(idx >= 0){
		unsigned int tabCount = m_pNoteBook->GetPageCount();
		//selects the page
		if (idx >= 0) {
			if(idx != m_pNoteBook->GetSelection()){
				wxWindowDisabler dis;
				SuperFreeze();
				m_pNoteBook->SetSelection(idx);
				SuperThaw();
			}
		}
		wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON, m_pNoteBook->GetSelection());
		evt.SetInt(wxAUI_BUTTON_CLOSE);
		evt.SetId(5380+500);
		evt.SetEventObject(((wxGinkgoAuiNoteBook*)m_pNoteBook)->GetActiveTabCtrl());
		m_pNoteBook->GetEventHandler()->ProcessEvent(evt);
		
		return ( tabCount > m_pNoteBook->GetPageCount() );
	} else {
		GNC::GUI::DetachedDialog* pDlg = dynamic_cast<GNC::GUI::DetachedDialog*>(pWindow->GetParent());
		if(pDlg != NULL)
		{
			bool closed = pDlg->Close();
			return closed;;
		} else {
			return false;
		}
	}

}

bool VentanaPrincipal::CerrarVista(wxWindow* window) {
	bool permitido = true;
	SuperFreeze();

	GNC::GCS::ControladorVistas* pcv = GNC::GCS::ControladorVistas::Instance();
	if (pcv == NULL) {
		std::cerr << "Error: No se pudo obtener el controlador de vistas" << std::endl;
		SuperThaw();
		return false;
	}
	GNC::GCS::IVista* v  = pcv->ObtenerVistaRegistrada(window);

	if (v != NULL) {
		if (v->SoportaGuardar() && v->EstaModificada()) {
			std::string titulo = GNC::GCS::ControladorVistas::Instance()->GetTitulo(v);
			wxString descr;
			std::ostringstream os;
			os << _Std("Would you like to save the changes in the study:") << titulo.c_str() << "?";
			PauseSuperFreeze();
			int answer = wxMessageBox(wxString::FromUTF8(os.str().c_str()), _("Unsaved data"), wxYES_NO | wxCANCEL, this);
			ContSuperFreeze();
			if (answer == wxCANCEL) {
				permitido = false;
			}
			else if (answer == wxYES) {
				if (!v->Guardar()) {

					wxMessageDialog dialog(NULL,_("Errors have occurred when saving the series.\nWould you like to continue closing? "),_("Error saving"),wxYES_NO|wxICON_WARNING);
					PauseSuperFreeze();
					permitido = dialog.ShowModal() == wxID_YES;
					ContSuperFreeze();
				}
			}
		}
	}

	SuperThaw();

	return permitido;
}

void VentanaPrincipal::OnNotebookCambiarTab(wxAuiNotebookEvent& event)
{
	wxWindowDisabler disabler;
	SuperFreeze();
	if(m_pNoteBook->GetSelection()!=-1){
		GNC::GCS::IVista* v  = GNC::GCS::ControladorVistas::Instance()->ObtenerVistaRegistrada(m_pNoteBook->GetPage(event.GetSelection()));
		GNC::GCS::ControladorVistas* pcv = GNC::GCS::ControladorVistas::Instance();
		if(v!=NULL && pcv != NULL){
			pcv->SolicitarActivarVista(v);
		}
	}
	SuperThaw();
	event.Skip(true);
}

void VentanaPrincipal::OnNotebookMenuTab(wxAuiNotebookEvent& )
{
	wxMenu*  menu = new wxMenu();
	//cerrar pestania activa
	wxMenuItem*  pPantallaCompleta = new wxMenuItem( menu, ID_PANTALLA_COMPLETA, wxString(_("Full Screen")) + wxT("\tF11"), _("View Full Screen"), wxITEM_NORMAL );

	wxMenu* subMenuPestanias = new wxMenu();
	wxMenuItem* pMenuMostrarPrimerPlano = new wxMenuItem(subMenuPestanias, wxID_ANY, _("Tab Regroup"), _("Tab Regroup"), wxITEM_NORMAL );
	wxMenuItem*  pMosaicoHorizontal = new wxMenuItem( subMenuPestanias, ID_MOSAICO_HORIZONTAL, _("Tile Horizontally"), _("Tile Horizontally"), wxITEM_NORMAL );
	wxMenuItem*  pMosaicoVertical = new wxMenuItem( subMenuPestanias, ID_MOSAICO_VERTICAL, _("Tile Vertically"), _("Tile Vertically"), wxITEM_NORMAL );

	wxMenu* subMenuGrid = new wxMenu();
	wxMenuItem*  pGrid2Col = new wxMenuItem( subMenuGrid, ID_GRID_2_COLUMNAS, _("Grid (two columns)"), _("Grid (two columns)"), wxITEM_NORMAL );
	wxMenuItem*  pGrid3Col = new wxMenuItem( subMenuGrid, ID_GRID_3_COLUMNAS, _("Grid (three columns)"), _("Grid (three columns)"), wxITEM_NORMAL );

	wxMenuItem* pMenuCerrarActiva = new wxMenuItem(menu, ID_CERRAR, _("&Close"), _("Close"), wxITEM_NORMAL );
	wxMenuItem* pMenuCerrarTodas = new wxMenuItem(menu, ID_CERRAR_TODAS, _("&Close all") , _("Close all windows"), wxITEM_NORMAL );

	menu->Connect(pMenuMostrarPrimerPlano->GetId(),wxEVT_COMMAND_MENU_SELECTED,wxCommandEventHandler( VentanaPrincipal::OnMenuPrimerPlanoPestaniaActiva),NULL,this);

#ifdef __WXMSW__
	pMenuCerrarActiva->SetBitmaps(GinkgoResourcesManager::MenuIcons::GetIcoCerrarTab());
	pMenuMostrarPrimerPlano->SetBitmaps(GinkgoResourcesManager::MenuTabs::GetIcoReagrupar());
	pPantallaCompleta->SetBitmaps(GinkgoResourcesManager::MenuIcons::GetIcoPantallaCompleta());
	pGrid2Col->SetBitmaps(GinkgoResourcesManager::MenuTabs::GetIcoGrid2Col());
	pGrid3Col->SetBitmaps(GinkgoResourcesManager::MenuTabs::GetIcoGrid3Col());
#else
	pMenuCerrarActiva->SetBitmap(GinkgoResourcesManager::MenuIcons::GetIcoCerrarTab());
	pMenuMostrarPrimerPlano->SetBitmap(GinkgoResourcesManager::MenuTabs::GetIcoReagrupar());
	pPantallaCompleta->SetBitmap(GinkgoResourcesManager::MenuIcons::GetIcoPantallaCompleta());
	pGrid2Col->SetBitmap(GinkgoResourcesManager::MenuTabs::GetIcoGrid2Col());
	pGrid3Col->SetBitmap(GinkgoResourcesManager::MenuTabs::GetIcoGrid3Col());
#endif

	menu->Append( pPantallaCompleta );
	menu->AppendSeparator();
	subMenuPestanias->Append(pMenuMostrarPrimerPlano);
	subMenuPestanias->AppendSeparator();
	subMenuPestanias->Append(pMosaicoHorizontal);
	subMenuPestanias->Append(pMosaicoVertical);
	menu->AppendSubMenu(subMenuPestanias,_("Tabbed organization"));
	subMenuGrid->Append(pGrid2Col);
	subMenuGrid->Append(pGrid3Col);
	menu->AppendSubMenu(subMenuGrid,_("Grid organization"));
	menu->AppendSeparator();
	menu->Append(pMenuCerrarActiva);
	menu->Append(pMenuCerrarTodas);
	m_pNoteBook->PopupMenu(menu);
	delete menu;
}

void VentanaPrincipal::OnNotebookFocus(wxChildFocusEvent&)
{

/*	if(m_pNoteBook->GetPageCount() > 0){
		GNC::GCS::IVista* v  = GNC::GCS::ControladorVistas::Instance()->ObtenerPrimeraVista(m_pNoteBook->GetPage(m_pNoteBook->GetSelection()));
		v->GetWindow()->SetFocus();
	}
	*/
}

//region "eventos ginkgo"
void VentanaPrincipal::ProcesarEvento(GNC::GCS::Events::IEvent *pEvt)
{
	switch (pEvt->GetCodigoEvento()) {
		case ginkgoEVT_Core_UpdateAvailable:
			{
				GNC::GCS::Events::EventoUpdateAvailable* pE = dynamic_cast<GNC::GCS::Events::EventoUpdateAvailable*>(pEvt);
				if (pE != NULL) {

					int curRevision = GNC::GCS::IEntorno::Instance()->GetGinkgoRevision();

					bool superior = false;

					if ( pE->GetRevision() > curRevision ) {
						superior = true;
					}
					
					m_VersionChecked = true;
					m_VersionNueva = pE->GetVersionString();

					if (!superior) {
						if (pE->Informar()) {
							wxMessageBox(_("There is not newest Ginkgo CADx versions at this moment."), _("Ginkgo CADx updated"), wxICON_INFORMATION);
						}
						return;
					}

					std::string valor;
					GNC::GCS::ConfigurationController::Instance()->readStringGeneral("/GinkgoCore/SkipUpdate", m_VersionNueva, valor, "0");
					if (valor == "1" && !pE->Informar()) {
						return;
					}

					//wxWindowDisabler dis;
					//SuperFreeze();

					m_pHipervinculoActualizacion->SetLabel(wxString(_("New version available (")) + wxString::FromUTF8(m_VersionNueva.c_str()) + _T(")") );
					m_pHipervinculoActualizacion->SetURL(wxString::FromUTF8(pE->GetURL().c_str()));
					m_pHipervinculoActualizacion->SetToolTip(wxString::FromUTF8(pE->GetDescription().c_str()));

					if (valor == "1") {
						m_pDoNotWarnAgain->SetValue(true);
					}
					else {
						m_pDoNotWarnAgain->SetValue(false);
					}

					m_pPanelActualizacion->Show();
					//m_pPanelCentral->Layout();
					Layout();
					Refresh(true);

					//SuperThaw();
				}
			}
			break;
		default:
			break;
	}
}
//endregion






//------------------------------------------------------------------------------
//region "IExtensionsObserver realization"

void VentanaPrincipal::OnModuleLoaded(GNC::GCS::IModuleController* )
{
	//GTRACE("VentanaPrincipal::OnModuloCargado(" << pCM->GetNombre().c_str() << ")");
	RefrescarMenus();
	GNC::GUI::HistoryPanel3::Instance()->ReloadToolBar();
}

void VentanaPrincipal::OnModuleUnloaded(GNC::GCS::IModuleController* )
{
	//GTRACE("VentanaPrincipal::OnModuloDescargado(" << pCM->GetNombre().c_str() << ")");
}

void VentanaPrincipal::OnModuleActivated(GNC::GCS::IModuleController* /*pCM*/)
{
	/*
	if (pCM != NULL) {
		GTRACE("VentanaPrincipal::OnModuloActivado(" << pCM->GetNombre().c_str() << ")");
	}
	else {
		GTRACE("VentanaPrincipal::OnModuloActivado(" << pCM->GetNombre().c_str() << ")");
	}
	*/
}

void VentanaPrincipal::OnModuleDeactivated(GNC::GCS::IModuleController* )
{
	//GTRACE("VentanaPrincipal::OnModuloDeactivado(" << pCM->GetNombre().c_str() << ")");
}
//endregion



//------------------------------------------------------------------------------
//region "IExtensionsObserver realization"

void VentanaPrincipal::OnVistaActivada(GNC::GCS::IVista* pVista) {
	#if defined (_WINDOWS)
	wxWindowDisabler dis;
	#endif
	if (pVista != NULL) {
		ForzarCambioVista(pVista);	
	}
	RefrescarMenus();
}

//endregion

//region "helpers"
void VentanaPrincipal::SuperFreeze()
{
	if (m_SuperFreezeCount <= 0) {
		GTRACE("SuperFreeze Locked");
		if (m_SuperFreezeCount < 0) {
			m_SuperFreezeCount = 0;
			std::cerr << "Error: Estado de bloqueo inconsistente." << std::endl;
		}
		/*Freeze();
		m_pPanelActualizacion->Freeze();
		m_pPanelCentral->Freeze();
		m_pNoteBook->Freeze();
		m_pMenuBar->Freeze();
		*/
	}
	m_SuperFreezeCount++;
}

void VentanaPrincipal::SuperThaw()
{
	m_SuperFreezeCount--;

	if (m_SuperFreezeCount <= 0) {
		GTRACE("SuperFreeze Released");
		if (m_SuperFreezeCount < 0) {
			m_SuperFreezeCount = 0;
			std::cerr << "Error: Estado de bloqueo inconsistente." << std::endl;
		}

		/*m_pMenuBar->Thaw();
		m_pNoteBook->Thaw();
		m_pPanelCentral->Thaw();
		m_pPanelActualizacion->Thaw();
		Thaw();*/
	}
}

void VentanaPrincipal::PauseSuperFreeze()
{
	if (m_SuperFreezeCount > 0) {
		GTRACE("SuperFreeze Paused");

		/*m_pMenuBar->Thaw();
		m_pNoteBook->Thaw();
		m_pPanelCentral->Thaw();
		m_pPanelActualizacion->Thaw();
		Thaw();*/
	}
}

void VentanaPrincipal::ContSuperFreeze()
{
	if (m_SuperFreezeCount > 0) {
		GTRACE("SuperFreeze Resumed");
	/*	Freeze();
		m_pPanelCentral->Freeze();
		m_pPanelActualizacion->Freeze();
		m_pNoteBook->Freeze();
		m_pMenuBar->Freeze();*/
	}
}
//endregion

//region "login e inicializacion"
void VentanaPrincipal::Login()
{
	if (GSEC::Auth::ControladorAutenticacion::Instance()->GetTipoAutenticacion() != GSEC::Auth::TA_NO_LOGIN)
	{
		try {

			GNC::GUI::DialogoLogin dlg(NULL);
			if (dlg.ShowModal() == wxID_OK) {
				MostrarVentana();
			}
			else {
				Close();
			}
		}
		catch (...)
		{
			LOG_ERROR("Core/Auth", "Error interno al autenticar");
			wxMessageBox(_("Internal error during auth process"), _("Internal error"), wxICON_ERROR);
			Close();
		}
	}
	else {
		MostrarVentana();
	}
}

void VentanaPrincipal::MostrarVentana()
{
	if (m_Iniciada) {
		Show(true);
		return;
	}
	m_Iniciada = true;
	try {
		//HL7 Service init
		if (GNC::GCS::IControladorPermisos::Instance()->Get("core.hl7", "autostart")) {
			GIL::HL7::ControladorEnvioHl7::Arrancar();
		}
	}
	catch(...)
	{
		LOG_ERROR("Core/Init", "Error starting HL7 service");
	}
	
	wxWindowDisabler dis;

	GNC::GCS::ControladorEventos::Instance()->Registrar(this, GNC::GCS::Events::EventoUpdateAvailable() );

	std::ostringstream os;
	os <<  GNC::Entorno::Instance()->GetApplicationName() << " " << GNC::Entorno::Instance()->GetGinkgoCopyRight() << " " << "MetaEmotion Healthcare";
	SetStatusText(wxString::FromUTF8(os.str().c_str()));
#if !defined(_GINKGO_DEBUG)
	SetSize(wxDisplay().GetClientArea().GetSize());
#endif
	Center();
#if !defined(_GINKGO_DEBUG)
/////////////////ATENCION!!!! esto es porque sino en windows no va bien, se desvincula la status bar
	#ifdef _WIN32
			Show(true);
			Maximize(true);
	#else
			Maximize(true);
			Show(true);
	#endif
#else
	Show(true);
#endif
	SetFocus();
	ComprobarActualizaciones();

}

//endregion

//region "Getters y Setters de elementos de la interfaz"

wxAuiNotebook* VentanaPrincipal::GetAUINoteBook()
{
	return m_pNoteBook;
}

//endregion
