/*======================================================================================

	Program:		Range Imaging Toolkit (RITK)
	Module:			ritkPluginManagerDialog.cxx
	Version:		$Revision: 1763 $
	Date:			$Date: 2011-09-25 20:22:20 +0200 (So, 25 Sep 2011) $

	Copyright (c) 2010-2011
	Pattern Recognition Lab, 
    University Erlangen-Nuremberg, Germany
    All rights reserved.

	This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
	See RITKCopyright.txt for more information.

	http://www5.informatik.uni-erlangen.de/research/software/ritk

========================================================================================*/

#include <QPluginLoader>
#include <QStringList>
#include <QDir>

#include <QLabel>
#include <QGridLayout>
#include <QPushButton>
#include <QTreeWidget>
#include <QTreeWidgetItem>
#include <QHeaderView>
#include <QDirIterator>

#include <iostream>

#include "ritkPluginManagerDialog.h"

namespace ritk
{

PluginManagerDialog::PluginManagerDialog(QWidget *parent) :
    QDialog(parent)  
{
	setupUi(this);

    this->m_treeWidgetPluginList->setAlternatingRowColors(false);
    this->m_treeWidgetPluginList->setSelectionMode(QAbstractItemView::NoSelection);
    //this->m_treeWidgetPluginList->setColumnCount(2);
	QStringList Headers;
	//Headers.append("");
	Headers.append("Module");
	Headers.append("Name");
	Headers.append("Description");
	Headers.append("Status");
	this->m_treeWidgetPluginList->setHeaderLabels(Headers);
    //this->m_treeWidgetPluginList->header()->hide();

	this->m_pushButtonClose->setDefault(true);
	this->m_pushButtonStart->setEnabled(false);
	this->m_pushButtonStop->setEnabled(false);

    connect(this->m_pushButtonClose, SIGNAL(clicked()), this, SLOT(close()));

	connect(this->m_treeWidgetPluginList, SIGNAL(itemSelectionChanged()), this, SLOT(SelectionChanged()));
	connect(this->m_treeWidgetPluginList, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(DoubleClicked(QTreeWidgetItem*, int)));
	connect(this->m_pushButtonStart, SIGNAL(clicked()), this, SLOT(StartButtonPressed()));
	connect(this->m_pushButtonStop, SIGNAL(clicked()), this, SLOT(StopButtonPressed()));
	connect(this->m_treeWidgetPluginList, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), this, SLOT(CurrentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)));
}


PluginManagerDialog::~PluginManagerDialog()
{
	this->m_treeWidgetPluginList->clear();
}


//----------------------------------------------------------------------------
void 
PluginManagerDialog::SelectionChanged()  
{
	QList<PluginManager::PluginStruct> &Plugins = *m_PluginList;
	QList<QTreeWidgetItem*> Selection = this->m_treeWidgetPluginList->selectedItems();
	// Loop through selection
	for ( int i = 0; i < Selection.size(); i++ )
	{
		// Find the correct plugin
		for ( int j = 0; j < Plugins.size(); j++ )
		{
			if ( Plugins[j].TreeItem == Selection[i] )
			{
				// Enable/disable start and stop buttong depending on the started flag
				if ( Plugins[j].Started )
				{
					this->m_pushButtonStart->setEnabled(false);
					this->m_pushButtonStop->setEnabled(true);
				}
				else
				{
					this->m_pushButtonStart->setEnabled(true);
					this->m_pushButtonStop->setEnabled(false);
				}
			}
		}
	}
}

//----------------------------------------------------------------------------
void 
PluginManagerDialog::DoubleClicked(QTreeWidgetItem* DoubleClickedItem, int)  
{
	//SelectionChanged();

	QList<PluginManager::PluginStruct> &Plugins = *m_PluginList;
	// Find the correct plugin
	for ( int j = 0; j < Plugins.size(); j++ )
	{
		if ( Plugins[j].TreeItem == DoubleClickedItem )
		{
			// Start/Stop the plugin
			if ( Plugins[j].Started )
			{
				StopButtonPressed();
			}
			else
			{
				StartButtonPressed();
			}
		}
	}
}


//----------------------------------------------------------------------------
void 
PluginManagerDialog::CurrentItemChanged(QTreeWidgetItem  *current, QTreeWidgetItem  *previous)
{
}


//----------------------------------------------------------------------------
void 
PluginManagerDialog::StartButtonPressed()
{
	QList<PluginManager::PluginStruct> &Plugins = *m_PluginList;
	QList<QTreeWidgetItem*> Selection = this->m_treeWidgetPluginList->selectedItems();
	// Loop through selection
	for ( int i = 0; i < Selection.size(); i++ )
	{
		// Find the correct plugin
		for ( int j = 0; j < Plugins.size(); j++ )
		{
			if ( Plugins[j].TreeItem == Selection[i] )
			{
				emit StartPlugin(Plugins[j]);
			}
		}
	}
}


//----------------------------------------------------------------------------
void
PluginManagerDialog::StopButtonPressed()
{
	QList<PluginManager::PluginStruct> &Plugins = *m_PluginList;
	QList<QTreeWidgetItem*> Selection = this->m_treeWidgetPluginList->selectedItems();
	// Loop through selection
	for ( int i = 0; i < Selection.size(); i++ )
	{
		// Find the correct plugin
		for ( int j = 0; j < Plugins.size(); j++ )
		{
			if ( Plugins[j].TreeItem == Selection[i] )
			{
				emit StopPlugin(Plugins[j]);
			}
		}
	}
}


//----------------------------------------------------------------------------
void
PluginManagerDialog::PluginStatusChanged(PluginManager::PluginStruct& Struct)
{
	this->m_treeWidgetPluginList->setCurrentItem(Struct.TreeItem);

	if ( Struct.Started )
	{
		this->m_pushButtonStart->setEnabled(false);
		this->m_pushButtonStop->setEnabled(true);
		Struct.TreeItem->setText(3,tr("Started"));
	}
	else
	{
		this->m_pushButtonStart->setEnabled(true);
		this->m_pushButtonStop->setEnabled(false);
		Struct.TreeItem->setText(3,tr("Stopped"));
	}
}


//----------------------------------------------------------------------------
void
PluginManagerDialog::PopulatePluginInformation(QString PluginDir, QList<PluginManager::PluginStruct> *Plugins)
{
	m_PluginDir = PluginDir;
	m_PluginList = Plugins;

	UpdatePluginTree();
}


//----------------------------------------------------------------------------
void 
PluginManagerDialog::UpdatePluginTree()
{

	this->m_labelPluginPath->setText(tr("Available Plugins:\n(in directory %1)").arg(QDir::toNativeSeparators(m_PluginDir)));


	this->m_treeWidgetPluginList->clear();
	this->m_treeWidgetPluginList->setSelectionMode(QAbstractItemView::SingleSelection);

	QTreeWidgetItem *ApplicationPlugins = new QTreeWidgetItem(this->m_treeWidgetPluginList);
	ApplicationPlugins->setText(0,tr("Application plugins"));
	ApplicationPlugins->setFlags(Qt::ItemIsEnabled);
	this->m_treeWidgetPluginList->setItemExpanded(ApplicationPlugins, true);

	QTreeWidgetItem *FilterPlugins = new QTreeWidgetItem(this->m_treeWidgetPluginList);
	FilterPlugins->setText(0,tr("Filter plugins"));
	FilterPlugins->setFlags(Qt::ItemIsEnabled);
	this->m_treeWidgetPluginList->setItemExpanded(FilterPlugins, true);

	QTreeWidgetItem *SourcePlugins = new QTreeWidgetItem(this->m_treeWidgetPluginList);
	SourcePlugins->setText(0,tr("Source plugins"));
	SourcePlugins->setFlags(Qt::ItemIsEnabled);
	this->m_treeWidgetPluginList->setItemExpanded(SourcePlugins, true);

	QTreeWidgetItem *ImageTypePlugins = new QTreeWidgetItem(this->m_treeWidgetPluginList);
	ImageTypePlugins->setText(0,tr("Image type plugins"));
	ImageTypePlugins->setFlags(Qt::ItemIsEnabled);
	this->m_treeWidgetPluginList->setItemExpanded(ImageTypePlugins, true);

	this->m_pushButtonStart->setEnabled(false);
	this->m_pushButtonStop->setEnabled(false);

	// Bold font for the plugin class
	QFont ClassFont = ApplicationPlugins->font(0);
	ClassFont.setBold(true);
	ApplicationPlugins->setFont(0,ClassFont);
	FilterPlugins->setFont(0,ClassFont);
	SourcePlugins->setFont(0,ClassFont);
	ImageTypePlugins->setFont(0,ClassFont);

	// Loop
	QList<PluginManager::PluginStruct> &Plugins = *m_PluginList;
	for ( int i = 0; i < Plugins.size(); i++ )
	{
		QTreeWidgetItem *Category = 0;
		if ( Plugins[i].PluginType == PluginManager::Application )
			Category = ApplicationPlugins;
		else if ( Plugins[i].PluginType == PluginManager::Filter )
			Category = FilterPlugins;
		else if ( Plugins[i].PluginType == PluginManager::Source )
			Category = SourcePlugins;
		else if ( Plugins[i].PluginType == PluginManager::ImageType )
			Category = ImageTypePlugins;
		QTreeWidgetItem *pluginItem = new QTreeWidgetItem(Category);
		pluginItem->setText(0, Plugins[i].ModuleName);
		pluginItem->setText(1, Plugins[i].PluginName);
		pluginItem->setText(2, Plugins[i].Description);
		if ( Plugins[i].Started )
			pluginItem->setText(3,tr("Started"));
		else
			pluginItem->setText(3, "Stopped");

		// Bold font for the modul name
		QFont boldFont = pluginItem->font(0);
		boldFont.setItalic(true);
		pluginItem->setFont(0, boldFont);

		// Update tree index
		Plugins[i].TreeItem = pluginItem;
	}

	// Resize tree
	this->m_treeWidgetPluginList->resizeColumnToContents(0);
	this->m_treeWidgetPluginList->resizeColumnToContents(1);
	this->m_treeWidgetPluginList->resizeColumnToContents(2);
	this->m_treeWidgetPluginList->resizeColumnToContents(3);
}

} // end namespace ritk
