/*************************************************************************
 * This file is part of Graphic des EDitor project    
 *
 * Project created in conformity with the requirements for the Degree of
 * Master of Engineering in Software Engineering, Computing and Software
 * Department, McMaster University 2004 - 2008
 *
 * Author:	Xiao Ma
 * Supervisor: Dr. Ryan Leduc
*************************************************************************/

/* 
 NAME
   GedDesTransEditor.cpp - implementation of Ged DES transition function editor. 
 FUNCTION
   The class provides a dialog to modify the properties of a graphic transition
   function by adding or removing events to the transition. A graphic transition
   function may represent multiple DES transition function. 
 NOTES
 MODIFIED
   xma	    04/01/08 - CREATION 
*/
#include <QtGui>
#include "GedDesTransEditor.h"
#include "GedDesTrans.h"
#include <QString>
#include "Des.h"

namespace DESpot
{

GedDesTransEditor::GedDesTransEditor(Des* des, GedDesTrans *gedTrans,QWidget *parent)
    : QDialog(parent),des(des),gedTrans(gedTrans)
{
	
	modified = false;

	availEventListWidget = new QListWidget(this);
    selectedEventListWidget = new QListWidget(this);

	createAvailEventList();
	createSelectedEventList();

    availEventListWidget->setSelectionMode(QAbstractItemView::SingleSelection);
    selectedEventListWidget->setSelectionMode(QAbstractItemView::SingleSelection);

	QGroupBox *availBox = new QGroupBox(tr("Available Events"));
	QGroupBox *selectedBox = new QGroupBox(tr("Selected Events"));
	QHBoxLayout *availLayout = new QHBoxLayout;
	availLayout->addWidget(availEventListWidget);
	QHBoxLayout *selectedLayout = new QHBoxLayout;
	selectedLayout->addWidget(selectedEventListWidget);
	availBox->setLayout(availLayout);
	selectedBox->setLayout(selectedLayout);

    okButton = new QPushButton(tr("OK"));
    okButton->setDefault(true);
    cancelButton = new QPushButton(tr("Cancel"));

    addButton = new QPushButton(tr("Add"));
    removeButton = new QPushButton(tr("Remove"));

	connect(addButton, SIGNAL(clicked()), this, SLOT(add()));
	connect(removeButton, SIGNAL(clicked()), this, SLOT(remove()));
    connect(okButton, SIGNAL(clicked()), this, SLOT(accept()));
    connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));

    QHBoxLayout *buttonLayout = new QHBoxLayout;
    buttonLayout->addStretch();
    buttonLayout->addWidget(okButton);
    buttonLayout->addWidget(cancelButton);

	QVBoxLayout *editButtonLayout = new QVBoxLayout;
	editButtonLayout->addStretch();
	editButtonLayout->addWidget(addButton);
    editButtonLayout->addWidget(removeButton);
	editButtonLayout->addStretch();

    QHBoxLayout *listLayout = new QHBoxLayout;
    //listLayout->addStretch();
    listLayout->addWidget(availBox);
	listLayout->addLayout(editButtonLayout);
    listLayout->addWidget(selectedBox);

    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainLayout->addLayout(listLayout);
    mainLayout->addLayout(buttonLayout);
    setLayout(mainLayout);

    setWindowTitle(tr("Ged Transition Editor"));
}

void GedDesTransEditor::done(int result)
{
    if (result == QDialog::Accepted) 
	{
	  //removed modified check since when user clicks ok with no
	  //changes,  transition was being deleted!
	  //		if(modified)
	  //		{
			for(int i=0; i< selectedEventListWidget->count(); i++){
				QString eventName = selectedEventListWidget->item(i)->text();
				const DesEvent* event;
				if (des->findEvent(eventName.toStdWString(),event))
				  selectedEvents.append(event);
			}
			// We do not need to set event label if the user empty the list.
			// The scene will check the event list and remove the arrow for us
			if (!selectedEvents.isEmpty())
				gedTrans->setDesEvents(selectedEvents);
			//		}
    }
    QDialog::done(result);
}

void GedDesTransEditor::createAvailEventList()
{
	const DesState* fromState = gedTrans->fromState();

	Des::EventIteratorPtr eventIt = des->createEventIterator();
	for(eventIt->first(); eventIt->isDone() == false; eventIt->next()){
		const DesEvent& ev = eventIt->currentItem();
		DesEvent* evt = const_cast<DesEvent*>(&ev);
		
		// If trans(fromState,event) already exist, this event is not avail -> non-deterministic
		const DesState *toState;
		bool exist = des->transExists(fromState,&ev,toState);
		if (!exist)
                        /*QListWidgetItem *item = */ new QListWidgetItem(
				QString::fromStdWString(evt->getName()),availEventListWidget);
	}

}

void GedDesTransEditor::createSelectedEventList()
{
	const QList<const DesEvent* > events = gedTrans->desEvents();
	QListIterator<const DesEvent* > i(events);
	while (i.hasNext()) {
                /*QListWidgetItem *item = */ new QListWidgetItem(QString::fromStdWString(i.next()->getName()),
                                                   selectedEventListWidget);
	}
}

void GedDesTransEditor::add()
{
	QListWidgetItem *item = availEventListWidget->currentItem();
	if (item){
		availEventListWidget->takeItem(availEventListWidget->currentRow());
		selectedEventListWidget->addItem(item);
	}
	availEventListWidget->update();
	selectedEventListWidget->update();
	modified=true;
}

void GedDesTransEditor::remove()
{
	QListWidgetItem *item = selectedEventListWidget->currentItem();
	if (item){
		selectedEventListWidget->takeItem(selectedEventListWidget->currentRow());
		availEventListWidget->addItem(item);
	}
	availEventListWidget->update();
	selectedEventListWidget->update();
	modified=true;
}

}

