/*
 * ReaderControll.cpp
 *
 *  Created on: 14.10.2009
 *      Author: stefan.detter
 */

#include "ReaderControll.h"

#include <QPushButton>
#include <QCheckBox>
#include <QSpinBox>
#include <QProgressBar>
#include <QLabel>
#include <QTimer>

#include <QrfeResourceGlobal>

#include "../Settings.h"

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

ReaderControll::ReaderControll(Application* application, QPushButton* startButton, QSpinBox* timeSpinBox, QCheckBox* infinitCheckBox, QProgressBar* scanProgress, QLabel* scanLabel, QWidget* secondsWidget, QLabel* warningLabel, QObject* parent)
	: QObject(parent)
	, QrfeTraceModule("ReaderControll")
	, m_application(application)
	, m_startButton(startButton)
	, m_timeSpinBox(timeSpinBox)
	, m_infinitCheckBox(infinitCheckBox)
	, m_scanProgress(scanProgress)
	, m_scanLabel(scanLabel)
	, m_secondsWidget(secondsWidget)
	, m_warningLabel(warningLabel)
{
	m_inventoryActive = false;
	m_readerSelected = false;

	m_warningLabel->setVisible(false);

	connect(m_startButton, 					SIGNAL(clicked()),
			this, 							  SLOT(startButtonClicked()) );
	connect(m_infinitCheckBox, 				SIGNAL(toggled(bool)),
			this, 							  SLOT(infiniteToggled(bool)));

	m_scanTimer = new QTimer(this);
	m_scanTimer->setInterval(1000);
	connect(m_scanTimer, 	SIGNAL(timeout()), 	this, 	SLOT(updateGUI()) );

	m_multiplexTimer = new QTimer(this);
	m_multiplexTimer->setSingleShot(true);
	connect(m_multiplexTimer, SIGNAL(timeout()), this, 	SLOT(multiplexISR()) );

	m_multiplexReaderOn = false;
}

ReaderControll::~ReaderControll()
{
	if(m_inventoryActive)
		stopInventory();
}

void ReaderControll::activateInfiniteScan()
{

}

void ReaderControll::readerSelected(Reader* reader)
{
	bool inventoryWasActive = m_inventoryActive;
	if(inventoryWasActive)
		stopInventory();
	m_readerSelected = true;
	m_activeReader = reader->readerId();
	if(inventoryWasActive)
		startInventory();
}

void ReaderControll::readerUnselected()
{
	bool inventoryWasActive = m_inventoryActive;
	if(inventoryWasActive)
		stopInventory();
	m_readerSelected = false;
	if(inventoryWasActive)
		startInventory();
}


void ReaderControll::startButtonClicked()
{
	if(!m_inventoryActive)
	{
		m_startButton->setText("Stop Scan");
		m_startButton->setIcon(QIcon(QrfeGlobal::getButtonIconResourcePath("stop")));

		m_scanCurrentTime = 0;
		m_scanMaxTime = m_timeSpinBox->value();
		if(m_infinitCheckBox->isChecked())
			m_scanMaxTime = 0;

		updateGUI();
		if(m_scanMaxTime != 0){
			m_scanProgress->setMaximum(m_scanMaxTime);
			m_scanTimer->start();
		}
		else{
			m_scanProgress->setMaximum(1);
			m_scanTimer->start();
		}

		startInventory();
	}
	else
	{
		m_scanTimer->stop();
		m_startButton->setText("Start Scan");
		m_startButton->setIcon(QIcon(QrfeGlobal::getButtonIconResourcePath("start")));
		m_scanProgress->setValue(m_scanProgress->maximum());
		stopInventory();
	}
}


void ReaderControll::startInventory()
{
	m_inventoryActive = true;

	if(Settings::d->multiplexOn() == true && m_application->readerList().size() > 1 && m_readerSelected == false)
	{
		trc(3, "Starting multiplexed inventory Reader list size: [" + QStringList(m_application->readerList()).join("], [") + "]");
		m_multiplexReaderOn = false;
		m_multiplexCurrentReader = QString();
		m_multiplexCurrentIndex = 0;
		multiplexISR();
	}
	else if(m_readerSelected == true)
	{
		trc(3, "Starting single inventory");
		if(m_application->readerList().contains(m_activeReader))
			startInventoryOfReader(m_application->reader(m_activeReader));
	}
	else
	{
		trc(3, "Starting global inventory");
		foreach(QString id, m_application->readerList())
		{
			startInventoryOfReader(m_application->reader(id));
		}
	}
}

void ReaderControll::stopInventory()
{
	m_inventoryActive = false;

	if(Settings::d->multiplexOn() == true && m_application->readerList().size() > 1 && m_readerSelected == false)
	{
		trc(3, "Stopping multiplexed inventory." );
		m_multiplexTimer->start(1);
	}
	else if(m_readerSelected == true)
	{
		trc(3, "Stopping single inventory");
		if(m_application->readerList().contains(m_activeReader))
			stopInventoryOfReader(m_application->reader(m_activeReader));
	}
	else
	{
		trc(3, "Stopping global inventory");
		foreach(QString id, m_application->readerList())
		{
			stopInventoryOfReader(m_application->reader(id));
		}
	}
}


void ReaderControll::multiplexISR()
{
	if(m_multiplexReaderOn == true)
	{
		if( m_application->readerList().contains(m_multiplexCurrentReader) )
		{
			trc(3, "Multiplex - Stopping reader: " + m_multiplexCurrentReader);

			/* notify the read rate calculator that a new round started */
            pauseInventoryOfReader(m_application->reader(m_multiplexCurrentReader) );
			trc(3, "Multiplex - Stopped reader.");
			m_multiplexReaderOn = false;
			m_multiplexCurrentIndex++;
		}
	}

	if(m_multiplexReaderOn == false && m_inventoryActive)
	{
		if((int)m_multiplexCurrentIndex >= m_application->readerList().size())
			m_multiplexCurrentIndex = 0;

		m_multiplexCurrentReader = m_application->readerList().at(m_multiplexCurrentIndex);

		trc(3, "Multiplex - Starting reader: " + m_multiplexCurrentReader);

        if(!m_multiplexStartedReader.contains(m_multiplexCurrentReader)){
            startInventoryOfReader( m_application->reader(m_multiplexCurrentReader) );
            m_multiplexStartedReader.insert(m_multiplexCurrentReader);
        }
        else
            continueInventoryOfReader( m_application->reader(m_multiplexCurrentReader) );

		trc(3, "Multiplex - Started reader.");
		m_multiplexReaderOn = true;
		m_multiplexTimer->start(Settings::d->multiplexTime());
	}

    if(!m_inventoryActive)
    {
        trc(3, "Stopping global inventory");
        foreach(QString id, m_application->readerList())
        {
            stopInventoryOfReader(m_application->reader(id));
        }
        m_multiplexStartedReader.clear();
    }
}



void ReaderControll::updateGUI()
{
	if(m_scanMaxTime == 0)
	{
		m_scanProgress->setValue(0);
		m_scanLabel->setText("Infinite");

		m_scanLabel->setText(QString::number(m_scanCurrentTime) + "s");
		m_scanCurrentTime++;
	}
	else
	{
		m_scanProgress->setValue(m_scanCurrentTime);
		m_scanLabel->setText(QString::number(m_scanCurrentTime) + "s");

		if(m_scanCurrentTime == m_scanMaxTime){
			startButtonClicked();
		}

		m_scanCurrentTime++;
	}
}

void ReaderControll::infiniteToggled(bool status)
{
	if(status)
	{
		m_secondsWidget->setVisible(false);
		m_warningLabel->setVisible(true);
	}
	else
	{
		m_warningLabel->setVisible(false);
		m_secondsWidget->setVisible(true);
	}
}

bool ReaderControll::inventoryActive()
{
	return m_inventoryActive;
}

void ReaderControll::startInventoryOfReader(Reader* reader)
{
	return reader->startPipe();
}

void ReaderControll::stopInventoryOfReader(Reader* reader)
{
	return reader->stopPipe();
}

void ReaderControll::pauseInventoryOfReader(Reader* reader)
{
    return reader->pausePipe();
}

void ReaderControll::continueInventoryOfReader(Reader* reader)
{
    return reader->continuePipe();
}
