#include "ReaderTool.h"
#include <QAction>
#include <QStyleFactory>
#include <QDragEnterEvent>
#include <QDragMoveEvent>
#include <QDragLeaveEvent>
#include <QUrl>
#include <QDesktopServices>
#include <QMimeData>
#include <QMessageBox>

#include <QrfeReaderManager>
#include <QrfeResourceGlobal>

#include <def.h>

#include "License.h"
#include "Settings.h"
#include "Resource.h"

#include "application/Application.h"

#include "sound/SoundManager.h"

#include "jobs/JobCenter.h"

#include "trace/TraceWindowManager.h" 
#include "trace/ErrorTraceManager.h"

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

#include "models/treeModel/TagTreeControl.h"
#include "models/infoTable/InformationTableController.h"

#include "export/ExportController.h"
#include "tools/ToolController.h"
#include "permission/Permissions.h"

#include "gui/GuiController.h"

#include "handler/readHandler/beep/TagReadBeep.h"
#include "handler/readHandler/rssiTimeTrack/TimeTrackController.h"

#include "gui/import/CImportResultDialog.h"

ReaderTool::ReaderTool(QWidget *parent)
	: QMainWindow(parent)
	, QrfeTraceModule("Reader Tool")
{
	ui.setupUi(this);
	setAcceptDrops(true);
	setAutoFillBackground(true);

	m_application						= 0;

	m_actionHelp						= 0;

    m_jobCenter							= 0;

    m_traceWindowManager				= 0;
	m_errorTraceManager					= 0;

	m_manager							= 0;
	m_readerController					= 0;
	m_updateManager						= 0;

	m_tagTreeControl					= 0;
	m_informationTableController		= 0;
	m_guiController						= 0;
	m_exportController					= 0;
	m_timeTrackController				= 0;
	m_toolController					= 0;

	m_tagReadBeep						= 0;


	this->setWindowTitle(APPLICATION_NAME);


	ui.actionPURDebugWindow->setVisible(false);

	connect(Permissions::d, 		SIGNAL(permissionsChanged()),
			this, 					  SLOT(permissionsChanged()) );
}

ReaderTool::~ReaderTool()
{
	if(m_timeTrackController)			delete m_timeTrackController;
	if(m_exportController)				delete m_exportController;
	if(m_guiController)					delete m_guiController;
	if(m_informationTableController)	delete m_informationTableController;
	if(m_tagTreeControl)				delete m_tagTreeControl;
	if(m_readerController)				delete m_readerController;
	if(m_tagReadBeep)					delete m_tagReadBeep;
	if(m_jobCenter)						delete m_jobCenter;
	if(m_manager)						delete m_manager;
	if(m_traceWindowManager)			delete m_traceWindowManager;
	if(m_toolController)				delete m_toolController;
	if(m_updateManager) 				delete m_updateManager;
	if(m_errorTraceManager)				delete m_errorTraceManager;
	if(m_actionHelp)					delete m_actionHelp;

	if(SoundManager::d)					delete SoundManager::d;
	if(Resource::d)						delete Resource::d;
}

bool ReaderTool::init ( QStringList arguments )
{
	if(!License::d->init(this))
	{
		return false;
	}

	showSplashMessage("Load resources");
	Resource::initInstance();

	showSplashMessage("Init Sound Manager");
	SoundManager::initInstance();

	m_errorTraceManager 				= new ErrorTraceManager(this);

	showSplashMessage("Creating Trace Window Manager");
	m_traceWindowManager				= new TraceWindowManager(ui.traceDockWidget, ui.trcTableView, ui.traceClearButton, ui.traceExportButton, this);

	showSplashMessage("Creating Reader Manager");
	m_manager							= new QrfeReaderManager(this);
	connect(Settings::d, 						SIGNAL(automaticallyAttachChanged (bool)),
			m_manager, 							  SLOT(attachUsbReaderAutomatically(bool)) );
	m_manager->attachUsbReaderAutomatically(Settings::d->attachReaderAutomatically());

	showSplashMessage("Creating Application Controller");
	m_application 						= new Application(m_manager, this);

	showSplashMessage("Creating Reader Controller");
	m_readerController					= new ReaderControll(m_application, ui.startButton, ui.scanSpinBox, ui.infiniteBox, ui.scanProgressBar, ui.scanLabel, ui.secondsWidget, ui.warningLabel, this);

	showSplashMessage("Creating Update Manager");
	m_updateManager						= new FirmwareUpdateManager(this, this);

	showSplashMessage("Creating Main Tree View");
	m_tagTreeControl					= new TagTreeControl(m_application, ui.treeView, ui.clearTagsButton, ui.backButton, ui.selectedReaderLabel,	ui.selectedReaderPixmapLabel, this, this);
	connect(m_tagTreeControl,					SIGNAL(readerSelected(Reader*)),
			m_readerController,					  SLOT(readerSelected(Reader*)) );
	connect(m_tagTreeControl,					SIGNAL(readerUnselected()),
			m_readerController,					  SLOT(readerUnselected()) );

	showSplashMessage("Creating Information Table");
	m_informationTableController		= new InformationTableController(m_tagTreeControl, ui.informationTableView, ui.advancedInformationButton, this);

	showSplashMessage("Creating Gui Controller");
    m_guiController						= new GuiController(m_application, m_updateManager, (ModelData*)m_tagTreeControl->rootItem(), this, this);

	showSplashMessage("Creating Export Dialogs");
	m_exportController					= new ExportController (m_tagTreeControl, this, this);

	showSplashMessage("Creating Global Tag Handler");
	m_timeTrackController				= new TimeTrackController(this, m_application, this);
	m_tagReadBeep 						= new TagReadBeep(this, m_application, this);

	showSplashMessage("Creating Demo Controller");
    m_toolController 					= new ToolController((ModelData*)m_tagTreeControl->rootItem(), m_readerController, this, this);
	ui.menuTools->addActions(m_toolController->getToolActions());
	ui.menuDemos->addActions(m_toolController->getDemoActions());
	connect(m_toolController, 					SIGNAL(customToolsChanged()),
			this, 								  SLOT(customToolsChanged()) );
	connect(m_toolController, 					SIGNAL(demosChanged()),
			this, 								  SLOT(demosChanged()) );

	showSplashMessage("Creating Job Center");
	m_jobCenter							= new JobCenter(m_manager, m_guiController, m_readerController,
														m_updateManager, m_traceWindowManager, m_toolController, this, this);

	connect(m_application,						SIGNAL(appendGlobalJob(JobType, const QList<QVariant>&)),
			m_jobCenter,						  SLOT(appendJop(JobType, const QList<QVariant>&)));
	connect(m_guiController,					SIGNAL(appendGlobalJob(JobType, const QList<QVariant>&)),
			m_jobCenter,						  SLOT(appendJop(JobType, const QList<QVariant>&)));
	connect(m_tagTreeControl,					SIGNAL(appendGlobalJob(JobType, const QList<QVariant>&)),
			m_jobCenter,						  SLOT(appendJop(JobType, const QList<QVariant>&)));
	connect(m_informationTableController,		SIGNAL(appendGlobalJob(JobType, const QList<QVariant>&)),
			m_jobCenter,						  SLOT(appendJop(JobType, const QList<QVariant>&)));
	connect(m_updateManager,					SIGNAL(appendGlobalJob(JobType, const QList<QVariant>&)),
			m_jobCenter,						  SLOT(appendJop(JobType, const QList<QVariant>&)));
	connect(m_toolController,					SIGNAL(appendGlobalJob(JobType, const QList<QVariant>&)),
			m_jobCenter,						  SLOT(appendJop(JobType, const QList<QVariant>&)));


	connect(ui.actionAdd,						SIGNAL(triggered()),
			m_guiController,					  SLOT(showAddReaderDialog()));
	connect(ui.actionRemove_Offline_Reader,		SIGNAL(triggered()),
			m_tagTreeControl,					  SLOT(removeOfflineReader()));
	connect(ui.actionPreferences,				SIGNAL(triggered()),
			m_guiController,					  SLOT(showApplicationSettings()));
	connect(ui.actionAbout,						SIGNAL(triggered()),
			m_guiController,					  SLOT(showAboutDialog()));
	connect(ui.actionAbout_Qt, 					SIGNAL(triggered()),
			qApp, 								  SLOT(aboutQt()));
	connect(ui.actionExport_Data,				SIGNAL(triggered()),
			m_exportController,					  SLOT(exportRequest()));
	connect(ui.actionQuick_Export_Data,			SIGNAL(triggered()),
			m_exportController,					  SLOT(quickExportRequest()));
	connect(ui.actionRecord_Data,				SIGNAL(toggled(bool)),
			m_timeTrackController,				  SLOT(doTracking(bool)));
	connect(ui.actionEngineering,				SIGNAL(triggered()),
			m_guiController,					  SLOT(unlockEngineeringMode()));
	connect(ui.actionInfiniteScan,				SIGNAL(triggered()),
			m_readerController,				  	  SLOT(activateInfiniteScan()));
	connect(ui.actionManageLicenses,			SIGNAL(triggered()),
			License::d,							  SLOT(manageLicense()));


	connect(m_tagTreeControl,					SIGNAL(addReaderDialogRequested()),
			m_guiController,					  SLOT(showAddReaderDialog()));

	connect(ui.actionPURDebugWindow,			SIGNAL(toggled(bool)),
			m_guiController,				  	  SLOT(showPurDebugWindow(bool)));

	showSplashMessage("Initializing Image Repository");
	m_updateManager->init();

#ifdef RF_EMBEDDED
	showSplashMessage("Prepare Help Menu");
	prepareHelpMenu();
#endif

	showSplashMessage("Processing Arguments");
	processArguments(arguments);

	m_manager->checkForNewDevice();
	showSplashMessage("Initializing Done");

	return true;
}

void ReaderTool::setVisible ( bool visible )
{
	QMainWindow::setVisible(visible);
}


void ReaderTool::helpRequested()
{
#ifdef RF_EMBEDDED
	trc(1, "Opening " + QApplication::applicationDirPath() + "/doc/EN_UM - Reader-Suite - User Manual.pdf");
	if(!QDesktopServices::openUrl( QUrl("file:///" + QApplication::applicationDirPath() + "/doc/EN_UM - Reader-Suite - User Manual.pdf", QUrl::TolerantMode)))
		QMessageBox::warning(this, tr("User Manual"), tr("Could not open User Manual. Please ensure that a PDF reader is installed!") );
#endif
}

void ReaderTool::helpRequestedUSB()
{
#ifdef RF_EMBEDDED
	trc(1, "Opening " + QApplication::applicationDirPath() + "/doc/EN_UM - USB Reader - Installing Driver.pdf");
	if(!QDesktopServices::openUrl( QUrl("file:///" + QApplication::applicationDirPath() + "/doc/EN_UM - USB Reader - Installing Driver.pdf", QUrl::TolerantMode)))
		QMessageBox::warning(this, tr("User Manual"), tr("Could not open User Manual. Please ensure that a PDF reader is installed!") );
#endif
}

void ReaderTool::permissionsChanged()
{
	if(Permissions::d->readerAdvancedSettings())
	{
		ui.actionPURDebugWindow->setVisible(true);
	}
}

void ReaderTool::customToolsChanged()
{
	ui.menuCustomTools->clear();
	ui.menuCustomTools->addActions(m_toolController->getCustomToolsActions());
}

void ReaderTool::demosChanged()
{
	ui.menuDemos->clear();
	ui.menuDemos->addActions(m_toolController->getDemoActions());
}


void ReaderTool::dragEnterEvent(QDragEnterEvent *event)
{
	setBackgroundRole(QPalette::Highlight);
	event->acceptProposedAction();
}

void ReaderTool::dragMoveEvent(QDragMoveEvent *event)
{
	event->acceptProposedAction();
}

void ReaderTool::dragLeaveEvent(QDragLeaveEvent *event)
{
	setBackgroundRole(QPalette::NoRole);
	event->accept();
}

void ReaderTool::dropEvent(QDropEvent *event)
{
	const QMimeData *mimeData = event->mimeData();

	if (mimeData->hasUrls()) {
		QList<QUrl> urlList = mimeData->urls();
		QString report;
		uint overallCount = 0, overallSuccessfull = 0;

		Resource::d->startImport();

		foreach(QUrl url, urlList)
		{
			uint count = 0, successfull = 0;
			QString result;
			Resource::d->tryAddUrlToResource(url, result, count, successfull);

			QString file = url.path();
			if(url.path().split("/").size() > 0)
				file = url.path().split("/").last();

			report += file + "\n\t" +  result + "\n\n";
			overallCount += count;
			overallSuccessfull += successfull;
		}

		CImportResultDialog dlg(this);
		dlg.exec(QString("Import was successfull for %1 of %2 files.").arg(overallSuccessfull).arg(overallCount), report);
	} else {
		QMessageBox::critical(this, "Error", "The dropped data type is not supported.");
	}

	setBackgroundRole(QPalette::NoRole);
	event->acceptProposedAction();
}


void ReaderTool::processArguments ( const QStringList & args )
{
	foreach(QString arg, args)
	{
		if(arg.startsWith("-pass:"))
		{
			QString pass = arg.remove(0, 6);
            if(pass.startsWith('\"') && pass.endsWith('\"')){
                pass = pass.remove(0, 1);
                pass = pass.remove(pass.size()-1, 1);
            }
			Permissions::d->activatePermission(pass);
		}
		else if(arg.startsWith("-addCom:"))
		{
			QString com = arg.remove(0, 8);
			m_jobCenter->appendJop(JOB_AddReader, QList<QVariant>() << (uint)QrfeGlobal::DEVICE_Serial << com);
		}
		else if(arg.startsWith("-addTcp:"))
		{
			QString tcp = arg.remove(0, 8);
			m_jobCenter->appendJop(JOB_AddReader, QList<QVariant>() << (uint)QrfeGlobal::DEVICE_TCP << tcp);
		}
		else if(arg.startsWith("-startTool:"))
		{
			QString name = arg.remove(0, 11);
			m_jobCenter->appendJop(JOB_StartTool, QList<QVariant>() << name);
		}
		else if(arg.startsWith("-trace:"))
		{
			QString levelStr = arg.remove(0, 7);
			bool ok;
			int level = levelStr.toInt(&ok, 10);
			if(ok && Permissions::d->traceEnabled()){
				Settings::d->setTraceOn(true);
				Settings::d->setTraceLevel(level);
				m_jobCenter->appendJop(JOB_ShowHideTraceWindow, QList<QVariant>() << true << level);
			}
		}
        else if(arg.startsWith("-max"))
        {
            this->setWindowState(Qt::WindowMaximized);
        }
	}
}

void ReaderTool::prepareHelpMenu ( )
{
	m_actionHelp = new QAction(this);
    QIcon icon(QrfeGlobal::getButtonIconResourcePath("help"));
    m_actionHelp->setIcon(icon);
    m_actionHelp->setText(tr("User Manual"));
    ui.menuHelp->insertAction(ui.actionAbout_Qt, m_actionHelp);
    connect(m_actionHelp,						SIGNAL(triggered()),
			this,								  SLOT(helpRequested()));

    m_actionHelpUSB = new QAction(this);
    QIcon iconUsb(QrfeGlobal::getButtonIconResourcePath("usb"));
    m_actionHelpUSB->setIcon(iconUsb);
    m_actionHelpUSB->setText(tr("Installing USB driver"));
    ui.menuHelp->insertAction(ui.actionAbout_Qt, m_actionHelpUSB);
    connect(m_actionHelpUSB,					SIGNAL(triggered()),
			this,								  SLOT(helpRequestedUSB()));

    ui.menuHelp->insertSeparator(ui.actionAbout_Qt);
}

void ReaderTool::showSplashMessage ( const QString & message )
{
	emit showSplashMessage(message, Qt::AlignRight | Qt::AlignBottom, Qt::darkGray);
}

