/*
 *
 *  $Id: panelconfiguracionpermisos.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/hangingprotocolcontroller.h>
#include <main/controllers/controladorextensiones.h>
#include <api/controllers/ipacscontroller.h>
#include <main/entorno.h>
#include <api/dicom/dcmdictionary.h>
#include <api/dicom/idicommanager.h>

#include <resources/ginkgoresourcesmanager.h>
#include <api/internationalization/internationalization.h>
#include <wx/tooltip.h>
#include <wx/pen.h>
#include <wx/pen.h>
#include <wx/sizer.h>
#include <wx/aui/auibar.h>
#include <wx/menu.h>
#include "hangingprotocolconfigurationpanel.h"
#include <resources/ginkgoresourcesmanager.h>

#define COL_CRITERIA_DESCRIPTION	0
#define COL_CRITERIA_VALUE			1
#define COL_CRITERIA_ID				2

namespace GNC {
	namespace GUI {
		//////////////////////////////////////////
		class HangingButtonsBar:public wxAuiToolBar{
		public:
			HangingButtonsBar(wxWindow* pParent, const wxColour& color, const wxFont& fuente, int style): wxAuiToolBar(pParent,wxID_ANY, wxDefaultPosition, wxDefaultSize, style)
			{
				SetToolBitmapSize(wxSize(16,16));

				wxAuiDefaultToolBarArt* pToolArt= new wxAuiDefaultToolBarArt();
			#if defined(USE_PATCHED_LIBS) && !defined(__WXOSX__)
				pToolArt->SetBaseColor(color);

				pToolArt->SetFont(fuente);
			#endif
				SetArtProvider(pToolArt);

				Realize();
			}

			~HangingButtonsBar()
			{
			}
		};
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		class SelectOpeningMode: public SelectOpeningModeBase
		{
		public:
			SelectOpeningMode(wxWindow* pParent): SelectOpeningModeBase(pParent)
			{
				GNC::ControladorExtensiones::ListaModulos listaModulos = ControladorExtensiones::Instance()->Modulos();
				for(GNC::ControladorExtensiones::IteradorListaModulos itModulos=listaModulos.begin();itModulos!=listaModulos.end();++itModulos){
					for(GNC::GCS::IModuleController::IteradorListaModos itModos=(*itModulos).second->GetListaModos().begin();itModos!=(*itModulos).second->GetListaModos().end();++itModos){
						wxString wxStr = wxString::FromUTF8((*itModos)->GetDescripcion().c_str());
						m_pOpeningMode->AppendString(wxStr);
						m_modulos.push_back((*itModulos).second);
						m_modos.push_back((*itModos));
					}
				}
				if(m_pOpeningMode->GetCount() > 0) {
					m_pOpeningMode->Select(0);
				}				
				m_pPanelMessage->Layout();
				m_pBody->Layout();
			}

			~SelectOpeningMode()
			{
			}

			GNC::GCS::IModuleController* GetModuloSeleccionado(){
				return m_modulos[m_pOpeningMode->GetSelection()];
			}

			GNC::GCS::ModoControlador* GetModoSeleccionado(){
				return m_modos[m_pOpeningMode->GetSelection()];
			}
			typedef std::vector<GNC::GCS::IModuleController*> TipoVectorModulos;
			typedef std::vector<GNC::GCS::ModoControlador*> TipoVectorModos;
			TipoVectorModulos m_modulos;
			TipoVectorModos m_modos;
		};
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		class AddTagDialog: public AddTagDialogBase
		{
		public:
			AddTagDialog(wxWindow* pParent): AddTagDialogBase(pParent)
			{
				listId.push_back(GKDCM_PatientID);
				listId.push_back(GKDCM_IssuerOfPatientID);
				listId.push_back(GKDCM_PatientBirthDate);
				listId.push_back(GKDCM_PatientSex);
				listId.push_back(GKDCM_PatientName);
				listId.push_back(GKDCM_StudyInstanceUID);
				listId.push_back(GKDCM_StudyID);
				listId.push_back(GKDCM_AccessionNumber);
				listId.push_back(GKDCM_ReferringPhysicianName);
				listId.push_back(GKDCM_StudyDescription);
				listId.push_back(GKDCM_ModalitiesInStudy);
				listId.push_back(GKDCM_SeriesInstanceUID);
				listId.push_back(GKDCM_SeriesNumber);
				listId.push_back(GKDCM_Modality);
				listId.push_back(GKDCM_BodyPartExamined);
				listId.push_back(GKDCM_Laterality);
				listId.push_back(GKDCM_InstitutionName);
				listId.push_back(GKDCM_StationName);
				listId.push_back(GKDCM_InstitutionalDepartmentName);
				listId.push_back(GKDCM_PerformingPhysicianName);
				listId.push_back(GKDCM_ProtocolName);
				listId.push_back(GKDCM_SeriesDescription);

				GIL::DICOM::IDICOMManager*	pDICOMManager = GNC::GCS::IEntorno::Instance()->GetPACSController()->CrearInstanciaDeDICOMManager();
				for (std::vector<std::string>::const_iterator it = listId.begin(); it != listId.end(); ++it)
				{
					std::string description = pDICOMManager->GetDescription((*it));
					m_pChoiceTag->AppendString(wxString::FromUTF8(description.c_str()));
				}
				m_pChoiceTag->Select(0);
				GNC::Entorno::Instance()->GetPACSController()->LiberarInstanciaDeDICOMManager(pDICOMManager);
			}
			~AddTagDialog()
			{
				listId.clear();
			}

			std::pair<std::string, std::string> getTag()
			{
				std::pair<std::string, std::string> value;
				value.first = listId[m_pChoiceTag->GetSelection()];
				value.second = m_pTextValue->GetValue().ToUTF8();
				return value;
			}
		protected:
			std::vector<std::string> listId;
		};
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		class EditCriteriaPanel: public EditCriteriaPanelBase
		{
		public:
			EditCriteriaPanel(wxWindow* pParent): EditCriteriaPanelBase(pParent)
			{
				m_pTreeListCriteria->AddRoot(wxT("Root"));
				m_pTreeListCriteria->Connect(wxEVT_COMMAND_TREE_SEL_CHANGED, wxTreeEventHandler( EditCriteriaPanel::OnCriteriaChangeSelection ), NULL, this );
			}
			~EditCriteriaPanel()
			{
				m_pTreeListCriteria->Disconnect(wxEVT_COMMAND_TREE_SEL_CHANGED, wxTreeEventHandler( EditCriteriaPanel::OnCriteriaChangeSelection ), NULL, this );
			}			

			virtual void loadMatcher(const GNC::GCS::Ptr<GNC::GCS::Matcher>& matcher)
			{
				m_pTreeListCriteria->DeleteRoot();
				m_pTreeListCriteria->AddRoot(wxT("Root"));
				if (matcher.IsValid()) {
					for (std::map<std::string, std::string>::const_iterator it = matcher->getMatchingCriteria().begin(); it != matcher->getMatchingCriteria().end(); ++it)
					{
						addTag((*it).first, (*it).second);
					}
				}
			}

			virtual void updateMatcher(GNC::GCS::Ptr<GNC::GCS::Matcher>& matcher)
			{
				if (matcher.IsValid()) {
					matcher->getMatchingCriteria().clear();
					wxTreeItemIdValue cookie;
					wxTreeItemId itemActual = m_pTreeListCriteria->GetFirstChild(m_pTreeListCriteria->GetRootItem(), cookie);
					while (itemActual.IsOk())
					{
						matcher->getMatchingCriteria()[std::string(m_pTreeListCriteria->GetItemText(itemActual, COL_CRITERIA_ID).ToUTF8())] = m_pTreeListCriteria->GetItemText(itemActual, COL_CRITERIA_VALUE).ToUTF8();	
						itemActual = m_pTreeListCriteria->GetNextChild(m_pTreeListCriteria->GetRootItem(), cookie);
					}
				}
			}

			virtual void addTag(const std::string& tagKey, const std::string& value) 
			{
				GIL::DICOM::IDICOMManager*	pDICOMManager = GNC::GCS::IEntorno::Instance()->GetPACSController()->CrearInstanciaDeDICOMManager();
				std::string description = pDICOMManager->GetDescription(tagKey);
				wxTreeItemId idItem = m_pTreeListCriteria->AppendItem(m_pTreeListCriteria->GetRootItem(),wxString::FromUTF8(description.c_str()));
				m_pTreeListCriteria->SetItemText(idItem, COL_CRITERIA_VALUE, wxString::FromUTF8(value.c_str()));
				m_pTreeListCriteria->SetItemText(idItem, COL_CRITERIA_ID, wxString::FromUTF8(tagKey.c_str()));
				GNC::Entorno::Instance()->GetPACSController()->LiberarInstanciaDeDICOMManager(pDICOMManager);
			}

		protected:
			virtual void OnAddClick(wxCommandEvent& ) 
			{
				AddTagDialog dlg(this);
				if (dlg.ShowModal() == wxID_OK) {
					std::pair<std::string, std::string> value = dlg.getTag();
					wxTreeItemIdValue cookie;
					wxTreeItemId itemActual = m_pTreeListCriteria->GetFirstChild(m_pTreeListCriteria->GetRootItem(), cookie);
					bool exists = false;
					while (itemActual.IsOk())
					{
						if (std::string(m_pTreeListCriteria->GetItemText(itemActual, COL_CRITERIA_ID).ToUTF8()) == value.first)
						{
							m_pTreeListCriteria->SetItemText(itemActual, COL_CRITERIA_VALUE, wxString::FromUTF8(value.second.c_str()));
							exists = true;
							break;
						}
						itemActual = m_pTreeListCriteria->GetNextChild(m_pTreeListCriteria->GetRootItem(), cookie);
					}
					if (!exists) {
						addTag(value.first, value.second);
					}
				}
			}

			virtual void OnDeleteClick(wxCommandEvent& )
			{
				wxTreeItemId item = m_pTreeListCriteria->GetSelection();
				if(item.IsOk()){
					m_pTreeListCriteria->Delete(item);
				}
			}

			virtual void OnCriteriaChangeSelection(wxTreeEvent& event)
			{
				m_pBDelete->Enable(event.GetItem().IsOk());
			}

		};
		
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		class EditHangingProtocolDialog: public EditHangingProtocolDialogBase, public GNC::GCS::IHangingProtocolContract
		{
			class PreviewLayoutPanel: public wxPanel, public GNC::GCS::IHangingSeriesViewer
			{
			public:
				PreviewLayoutPanel(EditHangingProtocolDialog* pSelectionManager, wxWindow* pParent, const GNC::GCS::Ptr<GNC::GCS::Matcher>& seriesMatcher = NULL): wxPanel(pParent, wxID_ANY, wxDefaultPosition, wxSize(100,100)),
					isSelected(false),
					pEdigHangingDialog(pSelectionManager)
				{
					wxPanel::SetBackgroundColour(wxBG_STYLE_CUSTOM);
					if (seriesMatcher.IsValid()) {
						this->seriesMatcher = seriesMatcher;
					} else {
						this->seriesMatcher = new GNC::GCS::Matcher();
						this->seriesMatcher->getMatchingCriteria()[GKDCM_SeriesDescription] =  "";
						this->seriesMatcher->getMatchingCriteria()[GKDCM_Modality] =  "";
					}

					this->Connect( wxEVT_LEFT_UP, wxMouseEventHandler( PreviewLayoutPanel::OnLeftClick ) );
					this->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( PreviewLayoutPanel::OnRightClick ) );
					this->Connect( wxEVT_PAINT, wxPaintEventHandler( PreviewLayoutPanel::OnPaint ) );
				}

				~PreviewLayoutPanel()
				{
					this->Disconnect( wxEVT_LEFT_UP, wxMouseEventHandler( PreviewLayoutPanel::OnLeftClick ) );
					this->Disconnect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( PreviewLayoutPanel::OnRightClick ) );
					this->Disconnect( wxEVT_PAINT, wxPaintEventHandler( PreviewLayoutPanel::OnPaint ) );
				}

				void select(bool selected) 
				{
					if (selected != isSelected) {
						isSelected = selected;
						Refresh(true);
					}
				}

				GNC::GCS::Ptr<GNC::GCS::Matcher>& getMatcher()
				{
					return this->seriesMatcher;
				}

				void getSeriesBase(GIL::DICOM::DicomDataset& seriesBase)
				{
					for (std::map<std::string, std::string>::iterator it = seriesMatcher->getMatchingCriteria().begin(); it != seriesMatcher->getMatchingCriteria().end(); ++it)
					{
						seriesBase.tags[(*it).first] = (*it).second;
					}
				}
			protected:
				virtual void OnLeftClick(wxMouseEvent &)
				{
					if (pEdigHangingDialog->hangingSupportLevel == GNC::GCS::ModoControlador::THSL_FULL) {
						pEdigHangingDialog->doSelect(this);
					}
				}

				virtual void OnRightClick(wxMouseEvent &)
				{
					if (pEdigHangingDialog->hangingSupportLevel == GNC::GCS::ModoControlador::THSL_FULL) {
						pEdigHangingDialog->doSelect(this);
						wxMenu popupMenu;
						int id = 0;
						wxMenuItem* pItem = popupMenu.Append(id, _("Split horizontally..."));
						#ifdef __WXMSW__
						pItem->SetBitmaps(GinkgoResourcesManager::LayoutBar::GetIcoLayout2x1Blue());
						#else
						pItem->SetBitmap(GinkgoResourcesManager::LayoutBar::GetIcoLayout2x1Blue());
						#endif						
						popupMenu.Connect(id++,wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( PreviewLayoutPanel::OnSplitH ), NULL, this);
						pItem = popupMenu.Append(id, _("Split vertically..."));
						#ifdef __WXMSW__
						pItem->SetBitmaps(GinkgoResourcesManager::LayoutBar::GetIcoLayout1x2Blue());
						#else
						pItem->SetBitmap(GinkgoResourcesManager::LayoutBar::GetIcoLayout1x2Blue());
						#endif
						popupMenu.Connect(id++,wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( PreviewLayoutPanel::OnSplitV ), NULL, this);
						this->PopupMenu(&popupMenu);
					}
				}

				virtual void OnSplitH(wxCommandEvent& )
				{
					pEdigHangingDialog->SplitActive(true);
				}

				virtual void OnSplitV(wxCommandEvent& )
				{
					pEdigHangingDialog->SplitActive(false);
				}

				virtual void OnPaint(wxPaintEvent &/*event*/)
				{
					wxPaintDC dc(this);
					//no muestra la rallita de abajo
					//wxBufferedPaintDC dc(this);

					const int width = dc.GetSize().x;
					const int height = dc.GetSize().y;
					// Title background
					wxRect rTitle(0, 0, width, height);
					if (this->isSelected) {
						dc.GradientFillLinear(rTitle, wxColour(50, 180, 50), wxColour(100, 230, 100), wxWEST);
					} else {
						dc.GradientFillLinear(rTitle, wxColour(180, 180, 180), wxColour(230, 230, 230), wxWEST);
					}

					// Title border
					dc.SetBrush(*wxTRANSPARENT_BRUSH);
					if (this->isSelected) {
						dc.SetPen(wxPen(wxColour(30, 115, 30), 1, wxSOLID));
					} else {
						dc.SetPen(wxPen(wxColour(115, 115, 115), 1, wxSOLID));
					}
					dc.DrawRectangle(rTitle);
				}

				GNC::GCS::Ptr<GNC::GCS::Matcher> seriesMatcher;
				bool isSelected;
				EditHangingProtocolDialog* pEdigHangingDialog;
			};
		public:
			EditHangingProtocolDialog(wxWindow* pParent): EditHangingProtocolDialogBase(pParent)
			{	
			}
			EditHangingProtocolDialog(wxWindow* pParent, const GNC::GCS::Ptr<GNC::GCS::HangingProtocol>& hP): EditHangingProtocolDialogBase(pParent),
				hangingProtocol(new GNC::GCS::HangingProtocol(*hP))
			{
			}

			~EditHangingProtocolDialog()
			{
				listPreviewLayouts.clear();
			}

			virtual int ShowModal()
			{
				if (!hangingProtocol.IsValid()) {
					SelectOpeningMode dlg(this->GetParent());
					if (dlg.ShowModal() == wxID_OK) {
						hangingProtocol = new GNC::GCS::HangingProtocol();
						hangingProtocol->setModuleSid(dlg.GetModuloSeleccionado()->GetUID());
						hangingProtocol->setOpeningMode(dlg.GetModoSeleccionado()->GetId());
						//basic criteria...
						GNC::GCS::Ptr<GNC::GCS::Matcher> studyMatcher(new GNC::GCS::Matcher());
						studyMatcher->getMatchingCriteria()[GKDCM_ModalitiesInStudy] =  "";
						studyMatcher->getMatchingCriteria()[GKDCM_StudyDescription] =  "";
						hangingProtocol->setStudyMatcher(studyMatcher);
					} else {
						return wxID_CANCEL;
					}
				}
				InitPanels();
				return EditHangingProtocolDialogBase::ShowModal();
			}

			/**
			IHangingProtocolContract
			*/
			virtual wxWindow* createSeriesViewer(const std::map<std::string, std::string>& /*properties*/, long /*pk = -1*/, const GNC::GCS::Ptr<GNC::GCS::Matcher>& matcher)
			{
				listPreviewLayouts.push_back(new PreviewLayoutPanel(this, m_pLayoutPreview, matcher));
				return listPreviewLayouts.back();
			}

			virtual const std::list<long>& getOpeningSeries()
			{
				return fooList;
			}
			//
			void doLayout()
			{
				m_pLayoutPreview->Freeze();
				selectedPreview = NULL;
				m_pPreviewSizer->Clear(true);
				listPreviewLayouts.clear();
				if (!hangingProtocol->getLayout().IsValid()) {
					//basic layout...
					GNC::GCS::Ptr<GNC::GCS::Layout> layout(new GNC::GCS::Layout());
					layout->setRows(m_pSpinRows->GetValue());
					layout->setColumns(m_pSpinCols->GetValue());
					hangingProtocol->setLayout(layout);
				}

				hangingProtocol->getLayout()->doLayout(this, m_pPreviewSizer);
				
				if (!listPreviewLayouts.empty()) {
					for (std::list<PreviewLayoutPanel*>::const_iterator it = listPreviewLayouts.begin(); it != listPreviewLayouts.end(); ++it) {
						(*it)->select((*it) == selectedPreview);
					}
					doSelect(listPreviewLayouts.front());
				}

				m_pLayoutPreview->Layout();
				m_pLayoutPreview->Thaw();
				m_pLayoutPreview->Refresh();
			}

			void doSelect(PreviewLayoutPanel* pPanel) {
				if (selectedPreview == pPanel)
					return;
				m_pLayoutPreview->Freeze();
				if (selectedPreview != NULL) {
					selectedPreview->select(false);
					//store matcher...
					editSeriesCriteriaPanel->updateMatcher(selectedPreview->getMatcher());
				}
				selectedPreview = pPanel;
				selectedPreview->select(true);

				editSeriesCriteriaPanel->loadMatcher(selectedPreview->getMatcher());
				m_pLayoutPreview->Thaw();
			}

			void SplitActive(bool horizontally)
			{
				m_pLayoutPreview->Freeze();
				wxBoxSizer* pNewSizer;
				if (horizontally) {
					pNewSizer = new wxBoxSizer(wxVERTICAL);
				} else {
					pNewSizer = new wxBoxSizer(wxHORIZONTAL);
				}
				wxSizer* pSizerActive = (wxSizer*)selectedPreview->GetContainingSizer();
				wxSizerItem* pItem = pSizerActive->GetItem(selectedPreview);

				pItem->SetSizer(pNewSizer);
				pNewSizer->Add(selectedPreview, 1, wxEXPAND|wxALL);
				std::map<std::string, std::string> prop;
				pNewSizer->Add(createSeriesViewer(prop, -1, NULL), 1, wxEXPAND|wxALL);
				m_pLayoutPreview->Layout();
				m_pLayoutPreview->Thaw();
			}

			GNC::GCS::Ptr<GNC::GCS::HangingProtocol>& getHangingProtocol()
			{
				if (selectedPreview != NULL) {
					editSeriesCriteriaPanel->updateMatcher(selectedPreview->getMatcher());
				}

				this->hangingProtocol->setDescription(std::string(m_textDescription->GetValue().ToUTF8()));
				this->hangingProtocol->setName(std::string(m_textName->GetValue().ToUTF8()));
				GNC::GCS::Ptr<GNC::GCS::Matcher> pStudyMatcher(new GNC::GCS::Matcher());
				editStudyCriteriaPanel->updateMatcher(pStudyMatcher);
				this->hangingProtocol->setStudyMatcher(pStudyMatcher);
				if (hangingSupportLevel == GNC::GCS::ModoControlador::THSL_FULL) {
					this->hangingProtocol->setLayout(GNC::GCS::Layout::getLayoutFromSizer(m_pPreviewSizer));
				} else {
					GNC::GCS::Ptr<GNC::GCS::Layout> pLayout(new GNC::GCS::Layout());
					pLayout->setRows(m_pSpinRows->GetValue());
					pLayout->setColumns(m_pSpinCols->GetValue());
					GNC::GCS::Ptr<GNC::GCS::Matcher> pSeriesMatcher(new GNC::GCS::Matcher());
					editSeriesCriteriaPanel->updateMatcher(pSeriesMatcher);
					pLayout->setMatcher(pSeriesMatcher);
					this->hangingProtocol->setLayout(pLayout);
				}
				return this->hangingProtocol;
			}
		protected:
			virtual void OnSpinRows( wxSpinEvent&  )
			{
				RebuildLayout();
			}

			virtual void OnSpinCols( wxSpinEvent&  )
			{
				RebuildLayout();
			}

			virtual void OnSplitH(wxCommandEvent &)
			{
				SplitActive(true);
			}

			virtual void OnSplitV(wxCommandEvent &)
			{
				SplitActive(false);
			}

			virtual void RebuildLayout() 
			{
				//rebuild layout...
				GNC::GCS::Ptr<GNC::GCS::Layout> newLayout(new GNC::GCS::Layout());
				newLayout->setColumns(m_pSpinCols->GetValue());
				newLayout->setRows(m_pSpinRows->GetValue());
				hangingProtocol->setLayout(newLayout);
				doLayout();
				Layout();
			}

			void InitPanels()
			{
				editStudyCriteriaPanel = new EditCriteriaPanel(m_panelStudyCriteria);
				m_pSizerStudyCriteria->Add(editStudyCriteriaPanel, 1, wxEXPAND|wxALL, 5);
				m_panelStudyCriteria->Layout();
				m_pPanelGeneral->Layout();

				editSeriesCriteriaPanel = new EditCriteriaPanel(m_panelSeriesCriteria);
				m_pSizerSeriesCriteria->Add(editSeriesCriteriaPanel, 1, wxEXPAND|wxALL, 5);
				m_panelSeriesCriteria->Layout();
				m_pPanelLayout->Layout();


				//fillin hanging...
				m_textOpeningMode->SetValue(wxT("Unknown"));
				hangingSupportLevel = GNC::GCS::ModoControlador::THSL_ONLY_1x1;
				GNC::GCS::IModuleController* pModule = GNC::ControladorExtensiones::Instance()->ObtenerModulo(hangingProtocol->getModuleSid());
				if (pModule != NULL) {
					GNC::GCS::ModoControlador* pController = pModule->GetModo(hangingProtocol->getOpeningMode());
					if (pController != NULL) {
						m_textOpeningMode->SetValue(wxString::FromUTF8(pController->GetDescripcion().c_str()));
						hangingSupportLevel = pController->GetHangingSupportLevel();
					}
				}

				m_pSpinCols->Enable(hangingSupportLevel != GNC::GCS::ModoControlador::THSL_ONLY_1x1);
				m_pSpinRows->Enable(hangingSupportLevel != GNC::GCS::ModoControlador::THSL_ONLY_1x1);

				//button bar
				{
					wxColour barColor = wxColour(200,200,200);
					wxFont fontBar = wxFont( 10, 70, 90, wxFONTWEIGHT_BOLD, false, wxEmptyString );
					HangingButtonsBar* m_pButtonsBar = new HangingButtonsBar(m_pLayoutPreview, barColor, fontBar, wxAUI_TB_DEFAULT_STYLE);
					int i = 1;
					m_pButtonsBar->AddTool(i, _("Split active horizontally"), GinkgoResourcesManager::LayoutBar::GetIcoLayout2x1Blue(), _("Split active horizontally"));
					m_pButtonsBar->EnableTool(i, hangingSupportLevel == GNC::GCS::ModoControlador::THSL_FULL);
					m_pButtonsBar->Connect(i++, wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler(EditHangingProtocolDialog::OnSplitH), NULL, this);
					m_pButtonsBar->AddTool(i, _("Split active vertically"), GinkgoResourcesManager::LayoutBar::GetIcoLayout1x2Blue(), _("Split active vertically"));
					m_pButtonsBar->EnableTool(i, hangingSupportLevel == GNC::GCS::ModoControlador::THSL_FULL);
					m_pButtonsBar->Connect(i++, wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler(EditHangingProtocolDialog::OnSplitV), NULL, this);
					m_pButtonsBar->Realize();
					m_pSizerLayoutTools->Insert(0,m_pButtonsBar, 0, wxEXPAND| wxALL, 0);
				}

				m_textName->SetValue(wxString::FromUTF8(hangingProtocol->getName().c_str()));
				m_textDescription->SetValue(wxString::FromUTF8(hangingProtocol->getDescription().c_str()));

				this->editStudyCriteriaPanel->loadMatcher(hangingProtocol->getStudyMatcher());
				
				if (hangingProtocol->getLayout().IsValid()) {
					this->m_pSpinRows->SetValue(hangingProtocol->getLayout()->getRows());
					this->m_pSpinCols->SetValue(hangingProtocol->getLayout()->getColumns());
				}
				//dolayout...
				m_notebook1->Layout();
				doLayout();
				Layout();
			}

		protected:
			GNC::GCS::Ptr<GNC::GCS::HangingProtocol> hangingProtocol;
			EditCriteriaPanel* editStudyCriteriaPanel;			
			EditCriteriaPanel* editSeriesCriteriaPanel;
			std::list<long> fooList;
			PreviewLayoutPanel* selectedPreview;
			std::list<PreviewLayoutPanel*> listPreviewLayouts;
			GNC::GCS::ModoControlador::T_HangingProtocolSupportLevel hangingSupportLevel;
		};
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		class wxTreeItemDataProtocols: public wxTreeItemData
		{
		public:
			wxTreeItemDataProtocols(const GNC::GCS::Ptr<GNC::GCS::HangingProtocol>& hp): hangingProtocol(hp)
			{
			}
			~wxTreeItemDataProtocols()
			{
			}
			GNC::GCS::Ptr<GNC::GCS::HangingProtocol> hangingProtocol;
		};
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		HangingProtocolConfigurationPanel::HangingProtocolConfigurationPanel(wxWindow* pParent,IDialogoConfiguracion* pDialogo): HangingProtocolConfigurationPanelBase(pParent), IPasoConfiguracion(pDialogo)
		{
			Recargar();
			wxColour barColor = wxColour(200,200,200);
			wxFont fontBar = wxFont( 10, 70, 90, wxFONTWEIGHT_BOLD, false, wxEmptyString );
			m_pTreeListProtocols->Connect(wxEVT_COMMAND_TREE_ITEM_ACTIVATED, wxTreeEventHandler( HangingProtocolConfigurationPanel::OnHangingListDClick ), NULL, this );
			m_pTreeListProtocols->Connect(wxEVT_COMMAND_TREE_SEL_CHANGED, wxTreeEventHandler( HangingProtocolConfigurationPanel::OnHangingListChangeSelection ), NULL, this );
		}

		HangingProtocolConfigurationPanel::~HangingProtocolConfigurationPanel()
		{
		}

		void HangingProtocolConfigurationPanel::Recargar()
		{
			std::list<GNC::GCS::Ptr<GNC::GCS::HangingProtocol> > listOfProtocols = GNC::GCS::HangingProtocolController::Instance()->getHangingProtocols();

			bool primero =true;
			m_pTreeListProtocols->DeleteRoot();
			wxTreeItemId idRoot = m_pTreeListProtocols->AddRoot(wxT("Root"));

			for (std::list<GNC::GCS::Ptr<GNC::GCS::HangingProtocol> >::iterator it = listOfProtocols.begin(); it != listOfProtocols.end(); ++it) 
			{
				wxTreeItemId idItem = m_pTreeListProtocols->AppendItem(idRoot,wxString::FromUTF8((*it)->getName().c_str()));
				if ((*it)->isActive()) {
					m_pTreeListProtocols->SetItemText(idItem, 1, _("Yes"));
				} else {
					m_pTreeListProtocols->SetItemText(idItem, 1, _("No"));
				}
				m_pTreeListProtocols->SetItemData(idItem, new wxTreeItemDataProtocols((*it)));
				if(primero) {
					m_pTreeListProtocols->SelectItem(idItem);
					m_pBEdit->Enable(true);
					m_pBDelete->Enable(true);
					m_pBActive->Enable(true);
					primero = false;
				}
			}
		}

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

		std::string HangingProtocolConfigurationPanel::GetTitle()
		{
			return _Std("Hanging protocols");
		}

		std::string HangingProtocolConfigurationPanel::GetCabecera()
		{
			return _Std("Hanging protocols");
		}

		bool HangingProtocolConfigurationPanel::Validar()
		{
			bool ok = true;
			return ok;
		}

		bool HangingProtocolConfigurationPanel::Guardar()
		{
			//get hanging protocols...
			std::list<GNC::GCS::Ptr<GNC::GCS::HangingProtocol> > listOfProtocols;
			wxTreeItemIdValue cookie;
			wxTreeItemId itemActual = m_pTreeListProtocols->GetFirstChild(m_pTreeListProtocols->GetRootItem(), cookie);
			while (itemActual.IsOk())
			{
				listOfProtocols.push_back(((wxTreeItemDataProtocols*)m_pTreeListProtocols->GetItemData(itemActual))->hangingProtocol);
				itemActual = m_pTreeListProtocols->GetNextChild(m_pTreeListProtocols->GetRootItem(), cookie);
			}

			GNC::GCS::HangingProtocolController::Instance()->setHangingProtocols(listOfProtocols);
			return true;
		}
		//endregion


		void HangingProtocolConfigurationPanel::OnHangingListDClick(wxTreeEvent& )
		{
			Edit();
		}

		void HangingProtocolConfigurationPanel::OnHangingListChangeSelection(wxTreeEvent& event)
		{
			if(event.GetItem().IsOk()) {
				m_pBEdit->Enable(true);
				m_pBDelete->Enable(true);
				m_pBActive->Enable(true);
			} else {
				m_pBEdit->Enable(false);
				m_pBDelete->Enable(false);
				m_pBActive->Enable(false);
			}
		}

		void HangingProtocolConfigurationPanel::OnSetActive(wxCommandEvent &)
		{
			wxTreeItemId item = m_pTreeListProtocols->GetSelection();
			if (item.IsOk()) {
				GNC::GCS::Ptr<GNC::GCS::HangingProtocol>& hp = ((wxTreeItemDataProtocols*)m_pTreeListProtocols->GetItemData(item))->hangingProtocol;
				hp->setActive(!hp->isActive());
				if (hp->isActive()) {
					m_pTreeListProtocols->SetItemText(item, 1, _("Yes"));
				} else {
					m_pTreeListProtocols->SetItemText(item, 1, _("No"));
				}
				OnPropiedadCambiada();
			}
		}

		void HangingProtocolConfigurationPanel::OnNuevoClick(wxCommandEvent &)
		{
			EditHangingProtocolDialog dlg(this);
			if (dlg.ShowModal() == wxID_OK) {
				GNC::GCS::Ptr<GNC::GCS::HangingProtocol> hp = dlg.getHangingProtocol();
				wxTreeItemId idItem = m_pTreeListProtocols->AppendItem(m_pTreeListProtocols->GetRootItem(),wxString::FromUTF8(hp->getName().c_str()));
				if (hp->isActive()) {
					m_pTreeListProtocols->SetItemText(idItem, 1, _("Yes"));
				} else {
					m_pTreeListProtocols->SetItemText(idItem, 1, _("No"));
				}
				m_pTreeListProtocols->SetItemData(idItem, new wxTreeItemDataProtocols(hp));
				OnPropiedadCambiada();
			}
		}

		void HangingProtocolConfigurationPanel::OnEditarClick(wxCommandEvent &)
		{
			Edit();
		}

		void HangingProtocolConfigurationPanel::Edit()
		{
			wxTreeItemId item = m_pTreeListProtocols->GetSelection();
			if (item.IsOk()) {
				EditHangingProtocolDialog dlg(this, ((wxTreeItemDataProtocols*)m_pTreeListProtocols->GetItemData(item))->hangingProtocol);
				if (dlg.ShowModal() == wxID_OK) {
					GNC::GCS::Ptr<GNC::GCS::HangingProtocol> hp = dlg.getHangingProtocol();
					if (hp->isActive()) {
						m_pTreeListProtocols->SetItemText(item, 1, _("Yes"));
					} else {
						m_pTreeListProtocols->SetItemText(item, 1, _("No"));
					}
					m_pTreeListProtocols->SetItemData(item, new wxTreeItemDataProtocols(hp));
					OnPropiedadCambiada();
				}
			}
		}

		void HangingProtocolConfigurationPanel::OnEliminarClick(wxCommandEvent &)
		{
			wxTreeItemId item = m_pTreeListProtocols->GetSelection();
			if (item.IsOk()) {
				m_pTreeListProtocols->Delete(item);
				OnPropiedadCambiada();
			}
		}

		void HangingProtocolConfigurationPanel::OnPropiedadCambiada()
		{
			IPasoConfiguracion::OnPropiedadCambiada();
		}

		void HangingProtocolConfigurationPanel::OnTextoCambiado(wxCommandEvent & )
		{
		}

		void HangingProtocolConfigurationPanel::OnSize(wxSizeEvent & event){
			event.Skip(true);
		}
	}
}
