/*	Author:		Magdin Stoica
	Supervisor: Dr. Ryan Leduc
	
	Project created in conformity with the requirements for the Degree of Master of Engineering in Software Engineering, 
	Computing and Software Department, 
	McMaster University
	2003 - 2007
*/

#include <QGroupBox>									 
#include <QTreeWidget>
#include <qevent.h>
#include <QHeaderView>
#include <QFont>
#include <QMessageBox>

#include "CommonDefinitions.h"
#include "EventEditorUiPart.h"
#include "DesEditor.h"
#include "DesWorkspace.h"
#include "Des.h"
#include "DespotTreeWidget.h"
#include "TransRecorder.h"


namespace DESpot
{

EventEditorUiPart::EventEditorUiPart(DesWorkspace* pWorkspace, Ui::DesEditorUI* pUiContainer, Des* pDes, 
									 TransRecorder& transRecorder): 
		m_eventTypeSubContextMenu(null)
{
	if (pUiContainer == null)
		throw EX("Invalid (null) UI Container. Cannot create the event editor UI part")

	if (pDes == null)
		throw EX("Invalid (null) DES pointer. Cannot create UI part without data")

	//Initialize the data shown in the UI part
	m_pDes = pDes;
	m_desListnerId = m_pDes->subscribe(this);

	//setup widget references
	m_pEventViewWidg = pUiContainer->m_eventViewWidg;
	m_pEventViewWidg->setBoxWidget(pUiContainer->m_eventGroupBox);

	//initialize the transition recorder which is owned by the DES editor
	transRecorder.initEventListWidget(m_pEventViewWidg);

	//initialize widgets
	initEventViewWidget();

	setupConnections(pWorkspace);
}

//_________________________________________________________________________________________________

EventEditorUiPart::~EventEditorUiPart(void)
{
	if (m_pDes)
	{
		m_pDes->unsubscribe(m_desListnerId);
	}
}

//_________________________________________________________________________________________________

void EventEditorUiPart::clearSelection()
{
	QTreeWidgetItem* crtItem = m_pEventViewWidg->currentItem();
	if (crtItem)
	{
		crtItem->setSelected(false);
		m_pEventViewWidg->setCurrentItem(null);
	}
}

//_________________________________________________________________________________________________

//returns the context menu for this UI Part
QMenu& EventEditorUiPart::getContextMenu()
{
	return m_eventEditorContextMenu;
}

//_________________________________________________________________________________________________

//returns the context menu for this UI Part
QMenu& EventEditorUiPart::getEventTypeContextSubMenu()
{
	if (m_eventTypeSubContextMenu == null)
	{
		//Add the sub-context menu in order to create it
		m_eventTypeSubContextMenu = m_eventEditorContextMenu.addMenu(tr("Set &Type"));
	}
	
	return *m_eventTypeSubContextMenu;
}

//_________________________________________________________________________________________________

void EventEditorUiPart::onUserChangedEventName(const DesEvent& changedEvent, const std::wstring& newName)
{
	m_pDes->changeEventName(changedEvent.getId(), newName);
}

//_________________________________________________________________________________________________


void EventEditorUiPart::onUserChangedEventAlias(const DesEvent& changedEvent, const std::wstring& newAlias)
{
	m_pDes->changeEventAlias(changedEvent.getId(), newAlias);
}

//_________________________________________________________________________________________________


void EventEditorUiPart::onUserChangedEventCtrl(const DesEvent& changedEvent, bool newCtrl)
{
	m_pDes->changeEventCtrl(changedEvent.getId(), newCtrl);
}

//_________________________________________________________________________________________________


void EventEditorUiPart::onUserChangedEventType(const DesEvent& changedEvent, EventType newType)
{
	m_pDes->changeEventType(changedEvent.getId(), newType);
}

//_________________________________________________________________________________________________

void EventEditorUiPart::onEventAdded(const DesEvent& addedEvent)
{
	//add the event information to the event editor
	m_pEventViewWidg->addEvent(addedEvent);
}

//_________________________________________________________________________________________________

void EventEditorUiPart::onEventChanged(const DesEvent& changedEvent)
{
	QTreeWidgetItem* pEventUiItem = m_pEventViewWidg->updateEvent(changedEvent);

	//notify clients if this was the curently selected item
	if (pEventUiItem == m_pEventViewWidg->currentItem())
	{
		emit onCurrentEventChanged(changedEvent);
	}
}

//_________________________________________________________________________________________________

void EventEditorUiPart::onRemovingEvent(const DesEvent& event)
{
	m_pEventViewWidg->removeEvent(event);
}

//_________________________________________________________________________________________________

void EventEditorUiPart::initEventViewWidget()
{
	m_pEventViewWidg->initWidget();
	m_pEventViewWidg->setAllowEdit();
	m_pEventViewWidg->setContextMenu(m_eventEditorContextMenu);	
	m_pEventViewWidg->setShareFocus();
	m_pEventViewWidg->setCircularCursor();

	//add all events of m_des into the event view widget
	m_pEventViewWidg->loadEvents(m_pDes);
}

//_________________________________________________________________________________________________

void EventEditorUiPart::setupConnections(DesWorkspace* pWorkspace)
{
	//connect widgets with the part's handlers & workspace handlers
	connect(m_pEventViewWidg, SIGNAL(onUserChangedEventName(const DesEvent&, const std::wstring&)),
			this, SLOT(onUserChangedEventName(const DesEvent&, const std::wstring&)));

	connect(m_pEventViewWidg, SIGNAL(onUserChangedEventAlias(const DesEvent&, const std::wstring&)),
			this, SLOT(onUserChangedEventAlias(const DesEvent&, const std::wstring&)));

	connect(m_pEventViewWidg, SIGNAL(onUserChangedEventCtrl(const DesEvent&, bool)),
			this, SLOT(onUserChangedEventCtrl(const DesEvent&, bool)));

	connect(m_pEventViewWidg, SIGNAL(onUserChangedEventType(const DesEvent&, EventType)),
			this, SLOT(onUserChangedEventType(const DesEvent&, EventType)));

	connect(m_pEventViewWidg, SIGNAL(onChangedCurrentEvent(const DesEvent*, const DesEvent*)), 
		    pWorkspace, SLOT(onChangedCurrentEvent(const DesEvent*, const DesEvent*))) ;

	connect(m_pEventViewWidg, SIGNAL(onChangedActiveEvent(const DesEvent*, const DesEvent*)), 
		    pWorkspace, SLOT(onChangedCurrentEvent(const DesEvent*, const DesEvent*))) ;

	connect(this, SIGNAL(onCurrentEventChanged(const DesEvent&)), 
		    pWorkspace, SLOT(updateCurrentEventUi(const DesEvent&))) ;

	connect(m_pEventViewWidg, SIGNAL(onChangedCurrentEvent(const DesEvent* , const DesEvent*)), 
			pWorkspace->desEditor(), SLOT(onChangedCurrentEvent(const DesEvent* , const DesEvent*)));
}


} //end of namespace DESpot
