/*	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 <QMenu>
#include <QMenuBar>
#include <QToolBar>
#include <QIcon>
#include <QStatusBar>
#include <qevent.h>
#include <QHeaderView>
#include <QButtonGroup>

#include "FlatProjectWorkspace.h"
#include "CommonDefinitions.h"
#include "FlatProjectEditor.h"
#include "FlatProjStructureUiPart.h"
#include "FlatProjSummaryUiPart.h"
#include "DesViewUiPart.h"
#include "DesFlatProject.h"
#include "OutputUiPart.h"

namespace DESpot
{

FlatProjectWorkspace::FlatProjectWorkspace(FlatProjectEditor* pFlatProjectEditor, DesFlatProject* pProject) : 
	ProjectWorkspace(pFlatProjectEditor, pProject)
{
	//configure the form to use the FlatProjectEditor.ui
	setupUi(pFlatProjectEditor);

	//call the base class to set the title of the window given the fact that this is flat project
	//the base class will compose the full title and set it
	setProjectEditorTitle(STR_FLAT_PROJ_EDITOR, pProject->getName());

	//create the UI Parts of a flat project
	createUiParts(pProject);

	//setup menu, toolbar and status bar	
	createActions();
	setupMenu();
	setupToolBar();
	setupStatusBar();

	//setup event filters for child controls
	setupEventFilters();

	//set the spliter position
	positionSplitters();

	//setup connections between widgets
	setupConnections();

	//TODO: check if we can remove them for good
	m_projDetailsTabWidg->setCurrentIndex(0);
	m_projDetailsTabWidg->removeTab(2);
	m_projDetailsTabWidg->removeTab(1);

	pFlatProjectEditor->resize(630, 520);
}

//_________________________________________________________________________________________________

FlatProjectWorkspace::~FlatProjectWorkspace(void)
{
}

//_________________________________________________________________________________________________

void FlatProjectWorkspace::createUiParts(DesFlatProject* pProject)
{
	m_pProjStructUiPart = new FlatProjStructureUiPart(this, pProject);
	
	m_pSummaryUiPart = new FlatProjSummaryUiPart(this, pProject);
	
	m_pDesViewUiPart = new DesViewUiPart(this, pProject);
	
	m_pOutputUiPart	= new OutputUiPart(this, pProject);
	m_pOutputUiPart->setOwnerTabWidget(m_projDetailsTabWidg);

}

//_________________________________________________________________________________________________

//Added by Adam for BDDExport
void FlatProjectWorkspace::createActions()
{
	ProjectWorkspace::createActions();

	//Added by Adam for BDDExport
	m_exportToBDDsdAct = new QAction(tr("Export to BDDsd"), this);
	m_exportToBDDsdAct->setToolTip(tr("Export to BDDsd"));
	m_exportToBDDsdAct->setStatusTip(tr("Export to BDDsd"));
	connect(m_exportToBDDsdAct, SIGNAL(triggered()), flatProjectEditor(), SLOT(onExportToBDDsd()));

#ifdef __ENABLE_BDD__
	//Added by Adam for Flat project bdd tools

	m_runBddCheckAllToolAct = new QAction(QIcon(":/resources/checkProject.png"), tr("&Check All"), this);
	m_runBddCheckAllToolAct->setToolTip(tr("Check All (BDD)"));
//	m_runBddCheckAllToolAct->setStatusTip(tr("using BDD algorithms"));
	connect(m_runBddCheckAllToolAct, SIGNAL(triggered()), flatProjectEditor(), SLOT(onRunBddCheckAllTool()));

	m_runBddNonblockingToolAct = new QAction(QIcon(":/resources/checkNonblocking.png"), tr("&Nonblocking"), this);
	m_runBddNonblockingToolAct->setToolTip(tr("Check Nonblocking (BDD)"));
	m_runBddNonblockingToolAct->setStatusTip(tr("Verifies if the current DES is nonblocking using BDD algorithms"));
	connect(m_runBddNonblockingToolAct, SIGNAL(triggered()), flatProjectEditor(), SLOT(onRunBddNonblockingTool()));

	m_runBddTDESControllabilityToolAct = new QAction(/*QIcon(":/resources/TDESControllability.png"),*/ tr("&TDES Controllability"), this);
	m_runBddTDESControllabilityToolAct->setToolTip(tr("Check TDES Controllability"));
	m_runBddTDESControllabilityToolAct->setStatusTip(tr("Verifies if the current DES is TDES controllable using BDD algorithms"));
	connect(m_runBddTDESControllabilityToolAct, SIGNAL(triggered()), flatProjectEditor(), SLOT(onRunBddTDESControllabilityTool()));

	m_runBddControllabilityToolAct = new QAction(/*QIcon(":/resources/Controllability.png"),*/ tr("&Controllability"), this);
	m_runBddControllabilityToolAct->setToolTip(tr("Check Untimed Controllability"));
	m_runBddControllabilityToolAct->setStatusTip(tr("Verifies if the current DES is untimed controllable using BDD algorithms"));
	connect(m_runBddControllabilityToolAct, SIGNAL(triggered()), flatProjectEditor(), SLOT(onRunBddControllabilityTool()));

	m_runBddNBControllabilityToolAct = new
	QAction(/*QIcon(":/resources/NBControllability.png"),*/ tr("&Nonblocking and Controllability"), this);
	m_runBddNBControllabilityToolAct->setToolTip(tr("Check Nonblocking and Untimed Controllability"));
	m_runBddNBControllabilityToolAct->setStatusTip(tr("Verifies if the current DES is nonblocking and untimed controllable using BDD algorithms"));
	connect(m_runBddNBControllabilityToolAct, SIGNAL(triggered()), flatProjectEditor(), SLOT(onRunBddNBControllabilityTool()));

	m_runBddSDControllabilityToolAct = new QAction(/*QIcon(":/resources/SDControllability.png"),*/ tr("&SD Controllability"), this);
	m_runBddSDControllabilityToolAct->setToolTip(tr("Check SD Controllability"));
	m_runBddSDControllabilityToolAct->setStatusTip(tr("Verifies if the current DES is SD controllable using BDD algorithms"));
	connect(m_runBddSDControllabilityToolAct, SIGNAL(triggered()), flatProjectEditor(), SLOT(onRunBddSDControllabilityTool()));

	m_runBddProperTimebehaviorToolAct = new QAction(/*QIcon(":/resources/ProperTimebehavior.png"),*/ tr("&Proper Time behavior"), this);
	m_runBddProperTimebehaviorToolAct->setToolTip(tr("Proper Time behavior"));
//	m_runBddProperTimebehaviorToolAct->setStatusTip(tr("Verifies if the current subsystem is level-wise nonblocking using BDD algorithms"));
	connect(m_runBddProperTimebehaviorToolAct, SIGNAL(triggered()), flatProjectEditor(), SLOT(onRunBddProperTimebehaviorTool()));

	m_runBddSSingularProhibitableBehaviorToolAct = new QAction(/*QIcon(":/resources/SSingularProhibitableBehavior.png"),*/ tr("&S-Singular Prohibitable Behavior"), this);
	m_runBddSSingularProhibitableBehaviorToolAct->setToolTip(tr("Check S-Singular Prohibitable Behavior"));
//	m_runBddSSingularProhibitableBehaviorToolAct->setStatusTip(tr("Verifies if the project is level-wise controllable using BDD algorithms"));
	connect(m_runBddSSingularProhibitableBehaviorToolAct, SIGNAL(triggered()), flatProjectEditor(), SLOT(onRunBddSSingularProhibitableBehaviorTool()));

	m_runBddPlantCompletenessToolAct = new QAction(/*QIcon(":/resources/PlantCompleteness.png"),*/ tr("&Plant Completeness"), this);
	m_runBddPlantCompletenessToolAct->setToolTip(tr("Check PlantCompleteness"));
	m_runBddPlantCompletenessToolAct->setStatusTip(tr("Verifies the Plant Completeness using BDD algorithms"));
	connect(m_runBddPlantCompletenessToolAct, SIGNAL(triggered()), flatProjectEditor(), SLOT(onRunBddPlantCompletenessTool()));

	m_runBddALFToolAct = new QAction(/*QIcon(":/resources/ALF.png"),*/ tr("&ALF"), this);
//	m_runBddALFToolAct->setToolTip(tr("Runs level-wise sythesis for HISC project"));
//	m_runBddALFToolAct->setStatusTip(tr("Constructs supremal, controllable, nonblocking level-wise supervisors for project using BDD algorithms"));
	connect(m_runBddALFToolAct, SIGNAL(triggered()), flatProjectEditor(), SLOT(onRunBddALFTool()));
#endif

	// Added by David for Distributed TOols
	m_runDistCheckAll = new QAction(QIcon(":/resources/checkProject.png"), tr("Check All"), this);	
	connect(m_runDistCheckAll, SIGNAL(triggered()), flatProjectEditor(), SLOT(onRunDistCheckAll()));
#ifndef __ENABLE_DIST__
	m_runDistCheckAll->setDisabled(true);
#endif
}

//_________________________________________________________________________________________________

//Added by Adam for BDDExport

void FlatProjectWorkspace::setupMenu()
{
	ProjectWorkspace::setupMenu();

	//Setup actions specific for Flat
	
	//Added by Adam for BDDExport
	m_projectMenu->insertAction(m_projectSetNameAct, m_exportToBDDsdAct);
	m_projectMenu->insertSeparator(m_projectSetNameAct);

#ifdef __ENABLE_BDD__
	//addded by Adam for Flat project specifric BDD tools in the tool menu
	m_bddToolsMenu->insertAction(m_runBddMeetToolAct, m_runBddCheckAllToolAct);
	m_bddToolsMenu->insertAction(m_runBddMeetToolAct, m_runBddNonblockingToolAct);
	m_bddToolsMenu->insertAction(m_runBddMeetToolAct, m_runBddControllabilityToolAct);
	m_bddToolsMenu->insertAction(m_runBddMeetToolAct, m_runBddNBControllabilityToolAct);
	m_bddToolsMenu->insertAction(m_runBddMeetToolAct, m_runBddTDESControllabilityToolAct);
	m_bddToolsMenu->insertAction(m_runBddMeetToolAct, m_runBddSDControllabilityToolAct);
	m_bddToolsMenu->insertAction(m_runBddMeetToolAct, m_runBddProperTimebehaviorToolAct);
	m_bddToolsMenu->insertAction(m_runBddMeetToolAct, m_runBddSSingularProhibitableBehaviorToolAct);
	m_bddToolsMenu->insertAction(m_runBddMeetToolAct, m_runBddPlantCompletenessToolAct);
	m_bddToolsMenu->insertAction(m_runBddMeetToolAct, m_runBddALFToolAct);
	m_bddToolsMenu->insertSeparator(m_runBddMeetToolAct);
#endif

	// Added by David for Distributed Tools
	m_distToolsMenu->addAction(m_runDistCheckAll);
}

//_________________________________________________________________________________________________

void FlatProjectWorkspace::setupConnections()
{
	ProjectWorkspace::setupConnections();

	//TODO: setup connections between the onChangedCurrentDes signal from the project structure UI Part
	//and onChangedCurrentDes slot of the DES view UI part
}

//_________________________________________________________________________________________________

ProgressWidget* FlatProjectWorkspace::progressWidget()
{
	return m_progressWidget;
}

//_________________________________________________________________________________________________

FlatProjectEditor* FlatProjectWorkspace::flatProjectEditor()
{
	return dynamic_cast<FlatProjectEditor*>(projectEditor());
}

//_________________________________________________________________________________________________

void FlatProjectWorkspace::setupEventFilters()
{
	centralWidget->installEventFilter(this);
	m_projDetailsTabWidg->installEventFilter(this);
}

//_________________________________________________________________________________________________

bool FlatProjectWorkspace::eventFilter(QObject* target, QEvent* event)
{	
	if (target == centralWidget && event->type() == QEvent::Resize)
	{
		QResizeEvent* resizeEvent = dynamic_cast<QResizeEvent*>(event);
		m_mainSplitterWidg->resize(resizeEvent->size() - QSize(20, 22));
	}		
	else if (target == m_projDetailsTabWidg && event->type() == QEvent::Resize)
	{
		QResizeEvent* resizeEvent = dynamic_cast<QResizeEvent*>(event);
		
		const QSize layoutSize = resizeEvent->size() - QSize(18,50);		
		m_summaryPageLayout->resize(layoutSize);
		m_nonBlockPageLayout->resize(layoutSize);
		m_ctrlPageLayout->resize(layoutSize);		
		m_desDetailsLayoutWidg->resize(layoutSize);
		m_outputPageLayout->resize(layoutSize);
	}

	return ProjectWorkspace::eventFilter(target, event);
}

//_________________________________________________________________________________________________

//Arrange the position of all splitters to have the following arrangement:
//		- Project Structure area occupies ~30% of the space
//		- Des Details occupies the rest of ~70 of the space
void FlatProjectWorkspace::positionSplitters()
{
	//Calculate the 30/70 width sizes for the main splitter
	const float cProjectStructRatio = 3;
	QSize mainSplitterSize   = m_mainSplitterWidg->size();
        int   projStructAreaWidth = (int)(mainSplitterSize.width() / cProjectStructRatio);
	int   desDetailsAreaWidth = mainSplitterSize.width() - projStructAreaWidth; // the rest of the splitter;

	//arrange the main spliter to have the above sizes
	QList<int> mainSplitterSizeList;
	mainSplitterSizeList.push_back(projStructAreaWidth);
	mainSplitterSizeList.push_back(desDetailsAreaWidth);
	m_mainSplitterWidg->setSizes(mainSplitterSizeList);
}

} //end of namespace DESpot
