/*
 * AdvancedController.cpp
 *
 *  Created on: 29.10.2009
 *      Author: stefan.detter
 */

#include "GuiController.h"

#include <QMainWindow>
#include <QMessageBox>
#include <QInputDialog>
#include <QDockWidget>

#include "../License.h"

#include <QrfeReaderInterface>

#include "../update/FirmwareUpdateManager.h"

#include "../models/data/ModelData.h"

#include "../application/Application.h"
#include "../application/Reader.h"

#include "../control/ReaderControll.h"

#include "../models/data/TreeItem.h"
#include "../models/data/ReaderEntry.h"
#include "../models/data/TagEntry.h"

#include "open/OpenReaderDialog.h"
#include "about/QrfeAboutDialog.h"
#include "import/CImportResultDialog.h"

#include "settings/CSettingsDialog.h"

#include "readerSettings/CUpdateDialog.h"
#include "readerSettings/CRfePurDialog.h"
#include "readerSettings/CRfePurEngineeringDialog.h"

#include "readerSettings/app/CRfePurHidKeyboardReaderDialog.h"

#include "tagSettings/CGenericReadWriteDialog.h"

#include "tagSettings/gen2/CGen2SimpleTagDialog.h"
#include "tagSettings/gen2/CGen2TagDialog.h"
#include "tagSettings/gen2/CGen2TagEngineeringDialog.h"
#include "tagSettings/gen2/sub/specific/nxp/CGen2NxpResetReadProtectDialog.h"

#include "debug/CRfePurDebugWindow.h"

#include "../permission/Permissions.h"

#include <def.h>

GuiController::GuiController(Application* application, FirmwareUpdateManager* updateManager, ModelData* modelData, QMainWindow* window, QObject* parent)
	: QObject(parent)
	, m_window(window)
	, m_application(application)
	, m_updateManager(updateManager)
	, m_modelData(modelData)
{
	m_openReaderDialog					= new OpenReaderDialog(m_application->readerManager(), window);
	m_aboutDialog						= new QrfeAboutDialog(window);

	m_settingsDialog = new CSettingsDialog(m_window);
    connect(m_settingsDialog, 	SIGNAL(appendGlobalJob(JobType, const QList<QVariant>&)),
			this, 				SIGNAL(appendGlobalJob(JobType, const QList<QVariant>&)));

	m_updateDialog 						= new CUpdateDialog(m_updateManager, m_window);
	m_rfePurDialog 						= new CRfePurDialog(m_window);
	m_rfePurEngineeringDialog 			= new CRfePurEngineeringDialog(m_window);

    connect(m_rfePurDialog, 	SIGNAL(appendGlobalJob(JobType, const QList<QVariant>&)),
            this, 				SIGNAL(appendGlobalJob(JobType, const QList<QVariant>&)));
    connect(m_updateDialog, 	SIGNAL(appendGlobalJob(JobType, const QList<QVariant>&)),
			this, 				SIGNAL(appendGlobalJob(JobType, const QList<QVariant>&)));

	m_hidKeyboardReaderDialog 			= new CRfePurHidKeyboardReaderDialog(m_window);
	connect(m_hidKeyboardReaderDialog, 		SIGNAL(appendGlobalJob(JobType, const QList<QVariant>&)),
            this, 							SIGNAL(appendGlobalJob(JobType, const QList<QVariant>&)));
    m_genericReadWriteDialog			= new CGenericReadWriteDialog(m_window);

//	m_gen2SimpleDialog 					= new CGen2SimpleTagDialog(m_window);
	m_gen2Dialog 						= new CGen2TagDialog(m_window);
	m_gen2EngineeringDialog 			= new CGen2TagEngineeringDialog(m_window);
	m_gen2NxpResetReadProtectDialog 	= new CGen2NxpResetReadProtectDialog(m_window);

	m_purDebugWindow 					= new CRfePurDebugWindow(application, window);
	createBottomDockWidget(m_purDebugWindow);
}

GuiController::~GuiController()
{
}

void GuiController::unlockEngineeringMode()
{
	bool ok;
	QString text = QInputDialog::getText(m_window, "Unlock Engineering Mode", "Password", QLineEdit::Password, QString(), &ok);

	if(!ok)
		return;

	bool success  = Permissions::d->activatePermission(text);

	if(success)
		QMessageBox::information(m_window, "Unlock Engineering Mode", "The engineering mode was successfully unlocked.");
}


void GuiController::showAddReaderDialog()
{
	m_openReaderDialog->exec();
}

void GuiController::showAboutDialog()
{
	m_aboutDialog->exec();
}

void GuiController::showSettings ( const TreeItem* t )
{
	switch(t->itemType())
	{
		case TreeItem::ROOT:
		{
			showApplicationSettings();
			break;
		}
		case TreeItem::READER:
		{
			ReaderEntry* r = (ReaderEntry*) t;

			Reader* reader = r->reader();
			showReaderSettings(reader);

			break;
		}

		case TreeItem::TAG:
		{
			TagEntry* tag = (TagEntry*) t;
			ReaderEntry* r = (ReaderEntry*) tag->parent();

			uint antennaId = tag->antennaId();
			QString tagId = tag->tagId();
			Reader* reader = r->reader();

			showTagSettings(reader, tagId, antennaId);

			break;
		}

		default:
			break;

	}

}

void GuiController::showApplicationSettings()
{
	m_settingsDialog->exec();
}

void GuiController::showReaderSettings(QString readerId, bool fullFunction)
{
	Reader* reader = m_application->reader(readerId);
	if(reader == 0)
		return;
	showReaderSettings(reader, fullFunction);
}

void GuiController::showReaderAppSettings(QString readerId)
{
	Reader* reader = m_application->reader(readerId);
	if(reader == 0)
		return;
	showReaderAppSettings(reader);
}

void GuiController::showReaderEngineering(QString readerId)
{
	Reader* reader = m_application->reader(readerId);
	if(reader == 0)
		return;
	showReaderEngineering(reader);
}

void GuiController::showTagSettings(QString readerId, QString tagId, uint antennaId)
{
	Reader* reader = m_application->reader(readerId);
	if(reader == 0)
		return;
	showTagSettings(reader, tagId,antennaId);
}

void GuiController::showTagEngineering(QString readerId, QString tagId, uint antennaId)
{
	Reader* reader = m_application->reader(readerId);
	if(reader == 0)
		return;
	showTagEngineering(reader, tagId, antennaId);
}


void GuiController::showPurDebugWindow(bool show)
{
	if(show)
	{
		if(m_bottomDockWidgets[m_purDebugWindow]->isVisible())
			return;

		m_window->addDockWidget(Qt::BottomDockWidgetArea, m_bottomDockWidgets[m_purDebugWindow]);
		m_bottomDockWidgets[m_purDebugWindow]->show();
		showBottomDockWidgetTabbed(m_bottomDockWidgets[m_purDebugWindow]);
	}
	else
	{
		if(!m_bottomDockWidgets[m_purDebugWindow]->isVisible())
			return;

		m_window->removeDockWidget(m_bottomDockWidgets[m_purDebugWindow]);
	}
}


void GuiController::showReaderSettings (Reader* reader, bool fullFunction)
{
	if(reader->currentState() == QrfeGlobal::STATE_OFFLINE)
	{
		QMessageBox::critical(m_window, "Reader Settings", "It is not possible to show settings of an offline reader.");
		return;
	}

	if(reader->currentAction() == QrfeGlobal::ACTION_SCANNING)
	{
		QMessageBox::critical(m_window, "Reader Settings", "You must stop the scan before you can change the settings of a reader.");
		return;
	}

	if(reader->readerCaps() & QrfeGlobal::UPDATE_DIALOG)
	{
		m_updateDialog->exec(reader->readerInterface());
		return;
	}

	if(reader->readerCaps() & QrfeGlobal::READER_SETTINGS)
	{
		if(reader->readerModule() == QrfeGlobal::VERSION_RFE_PUR_RM1 ||
           reader->readerModule() == QrfeGlobal::VERSION_RFE_PUR_RM2 ){

			m_rfePurDialog->exec(reader->readerInterface(), fullFunction);
			return;
		}
	}

	QMessageBox::information(m_window, "Reader Settings", "The advanced reader settings for this type of reader are not available at present.");
}

void GuiController::showReaderAppSettings (Reader* reader)
{
	if(reader->currentState() == QrfeGlobal::STATE_OFFLINE)
	{
		QMessageBox::critical(m_window, "Reader Application Settings", "It is not possible to show settings of an offline reader.");
		return;
	}

	if(reader->currentAction() == QrfeGlobal::ACTION_SCANNING)
	{
		QMessageBox::critical(m_window, "Reader Application Settings", "You must stop the scan before you can change the settings of a reader.");
		return;
	}

    if((reader->readerTypeExact() & 0xFF000000) >= 0x80000000)
	{
		switch((uchar)reader->readerTypeExact())
		{
        case QrfeGlobal::PUR_APP_HID_KEYBOARD:
			m_hidKeyboardReaderDialog->exec(reader->readerInterface());
			return;
        }
	}

	QMessageBox::information(m_window, "Reader Application Settings", "The reader application settings for this type of reader are not available at present.");}

void GuiController::showReaderEngineering (Reader* reader)
{
	if(reader->currentState() == QrfeGlobal::STATE_OFFLINE)
	{
		QMessageBox::critical(m_window, "Engineering", "It is not possible to show settings of an offline reader.");
		return;
	}

	if(reader->currentAction() == QrfeGlobal::ACTION_SCANNING)
	{
		QMessageBox::critical(m_window, "Engineering", "You must stop the scan before you can change the settings of a reader.");
		return;
	}

	if(reader->readerModule() == QrfeGlobal::VERSION_RFE_PUR_RM1 ||
       reader->readerModule() == QrfeGlobal::VERSION_RFE_PUR_RM2){

		if(reader->currentSystem() == QrfeGlobal::FIRMWARE){
			m_rfePurEngineeringDialog->exec(reader->readerInterface());
			return;
		}
	}
	QMessageBox::information(m_window, "Engineering", "The engineering dialog for this type of reader are not available at present.");
}

void GuiController::showTagSettings (Reader* reader, QString tagId, uint antennaId)
{
	if(reader->currentState() == QrfeGlobal::STATE_OFFLINE)
	{
		QMessageBox::critical(m_window, "Advanced Settings", "It is not possible to show settings of a tag connected to an offline reader.");
		return;
	}

	if(reader->readerType() == QrfeGlobal::TYPE_PASSIVE)
	{
		if(reader->currentAction() == QrfeGlobal::ACTION_SCANNING)
		{
			QMessageBox::critical(m_window, "Advanced Settings", "You must stop the scan before you can change the settings of a tag.");
			return;
		}

		if(reader->tagType() == QrfeGlobal::TAG_GEN2)
		{
			m_gen2Dialog->exec(reader->readerInterface(), tagId, antennaId);
			return;
		}
		else if(reader->tagType() == QrfeGlobal::TAG_GEN2_NXP_READPROTECTED)
		{
			m_gen2NxpResetReadProtectDialog->exec(reader->readerInterface(), tagId, antennaId);
			return;
		}
		else
		{
			m_genericReadWriteDialog->exec(reader->readerInterface(), tagId, antennaId);
			return;
		}
	}

	QMessageBox::information(m_window, "Advanced Tag Settings", "The advanced tag settings are not available at present.");
}

void GuiController::showTagEngineering (Reader* reader, QString tagId, uint antennaId)
{
	if(reader->currentState() == QrfeGlobal::STATE_OFFLINE)
	{
		QMessageBox::critical(m_window, "Engineering", "It is not possible to show settings of a tag connected to an offline reader.");
		return;
	}

	if(reader->currentAction() == QrfeGlobal::ACTION_SCANNING)
	{
		QMessageBox::critical(m_window, "Engineering", "You must stop the scan before you can change the settings of a tag.");
		return;
	}

	if(reader->readerType() == QrfeGlobal::TYPE_PASSIVE)
	{
		if(reader->tagType() == QrfeGlobal::TAG_GEN2)
		{
			m_gen2EngineeringDialog->exec(reader->readerInterface(), tagId, antennaId);
			return;
		}
	}

	QMessageBox::information(m_window, "Engineering", "The engineering mode is not available for this tag at present.");
}

void GuiController::createBottomDockWidget(QWidget* w)
{
	QDockWidget* dock;
	dock = new QDockWidget(w->windowTitle(), m_window);
	dock->setAllowedAreas(Qt::BottomDockWidgetArea);
	dock->setWidget(m_purDebugWindow);
	dock->setVisible(false);
	m_bottomDockWidgets.insert(w, dock);
}

void GuiController::showBottomDockWidgetTabbed(QDockWidget* w)
{
	QList<QDockWidget*> docks = m_window->findChildren<QDockWidget*>();
	QList<QDockWidget*> bottomDocks;
	foreach(QDockWidget* d, docks)
	{
		if(d->isVisible() && m_window->dockWidgetArea(d) == Qt::BottomDockWidgetArea && d != w )
		{
			bottomDocks << d;
		}
	}
	if(bottomDocks.size() > 0)
		m_window->tabifyDockWidget(bottomDocks.at(0), w);
}
