#include "ContinuousCaptureQt.h"
#include <common/STLHelper.h>
#include <QDebug>
#include <QStyleFactory>
#include <QMessageBox>

//-----------------------------------------------------------------------------
ContinuousCaptureQt::ContinuousCaptureQt( QWidget* parent ) : QMainWindow( parent ),
    pCaptureThread_( 0 ), pImageCanvas_( 0 ), devMgr_(), pThread_( 0 ), lock_(), pFI_( 0 ), pAC_( 0 )
//-----------------------------------------------------------------------------
{
    this->setStyle( QStyleFactory::create( "Fusion" ) );
    ui_.setupUi( this );
    ui_.icon_label->setPixmap( QPixmap( QString::fromUtf8( ":/bulb-off.png" ) ) );
    ui_.sliderExposureTime->setVisible( false );
    ui_.label_exposureSlider->setVisible( false );
    pImageCanvas_ = new ImageCanvas( ui_.label_image );
    populateCombobox();
}
//-----------------------------------------------------------------------------
ContinuousCaptureQt::~ContinuousCaptureQt()
//-----------------------------------------------------------------------------
{
    cleanUp();
    DeleteElement( pImageCanvas_ );
}

//-----------------------------------------------------------------------------
void ContinuousCaptureQt::cleanUp( Device* pDev /* = 0 */ )
//-----------------------------------------------------------------------------
{
    QMutexLocker lockedScope( &lock_ );
    if( pCaptureThread_ )
    {
        pCaptureThread_->terminate();
        if( pThread_ )
        {
            pThread_->terminate();
            pThread_->wait();
        }
    }
    if( pDev && pDev->isOpen() )
    {
        pDev->close();
    }
    pImageCanvas_->SetImage( 0 );
    DeleteElement( pCaptureThread_ );
    DeleteElement( pThread_ );
    DeleteElement( pFI_ );
    DeleteElement( pAC_ );
}

//-----------------------------------------------------------------------------
void ContinuousCaptureQt::closeEvent( QCloseEvent* pEvent )
//-----------------------------------------------------------------------------
{
    cleanUp( getDevice( ui_.comboBox->currentIndex() ) );
    pEvent->accept();
}

//-----------------------------------------------------------------------------
void ContinuousCaptureQt::closeSelectedDevice( void )
//-----------------------------------------------------------------------------
{
    try
    {
        cleanUp( getDevice( ui_.comboBox->currentIndex() ) );
        ui_.label_StatusMessage->setText( "" );
        ui_.close_button->setEnabled( false );
        ui_.comboBox->setEnabled( true );
        ui_.open_button->setEnabled( true );
        ui_.acquisition_button->setEnabled( false );
        ui_.icon_label->setPixmap( QPixmap( QString::fromUtf8( ":/bulb-off.png" ) ) );
    }
    catch( const ImpactAcquireException& e )
    {
        QString msg;
        QTextStream( &msg ) << "Error while closing device! Error message: " << QString::fromStdString( e.getErrorCodeAsString() ) << "\nError Code: " << e.getErrorCode();
        QMessageBox::warning( this, "Error", msg, QMessageBox::Ok, QMessageBox::Ok );
        ui_.close_button->setEnabled( false );
        ui_.text_label->setText( "ERROR CLOSING THE DEVICE" );
    }
}

//-----------------------------------------------------------------------------
void ContinuousCaptureQt::errorString( QString msg )
//-----------------------------------------------------------------------------
{
    ui_.label_StatusMessage->setText( msg );
    qDebug() << "Error! - " << msg;
}

//-----------------------------------------------------------------------------
void ContinuousCaptureQt::openSelectedDevice( void )
//-----------------------------------------------------------------------------
{
    try
    {
        Device* pDev = getDevice( ui_.comboBox->currentIndex() );
        conditionalSetProperty( pDev->interfaceLayout, dilGenICam );
        pDev->open();
        pFI_ = new FunctionInterface( pDev );
        if( pDev->interfaceLayout.isValid() && ( pDev->interfaceLayout.read() == dilGenICam ) )
        {
            pAC_ = new GenICam::AcquisitionControl( pDev );
        }
        setupExposureTimeSlider();
        ui_.comboBox->setEnabled( false );
        ui_.open_button->setEnabled( false );
        ui_.close_button->setEnabled( true );
        ui_.acquisition_button->setEnabled( true );
        ui_.icon_label->setPixmap( QPixmap( QString::fromUtf8( ":/bulb-on.png" ) ) );
    }
    catch( const ImpactAcquireException& e )
    {
        QString msg;
        QTextStream( &msg ) << "Error while opening device! Error message: " << QString::fromStdString( e.getErrorCodeAsString() ) << "\nError Code: " << e.getErrorCode();
        QMessageBox::warning( this, "Error", msg, QMessageBox::Ok, QMessageBox::Ok );
        ui_.open_button->setEnabled( false );
        ui_.comboBox->setEnabled( true );
        ui_.text_label->setText( "ERROR OPENING THE DEVICE" );
    }
}

//-----------------------------------------------------------------------------
void ContinuousCaptureQt::populateCombobox( void )
//-----------------------------------------------------------------------------
{
    QStringList comboBoxEntries;
    for( unsigned int i = 0; i < devMgr_.deviceCount(); i++ )
    {
        Device* pDev = devMgr_.getDevice( i );
        QString entry;
        QTextStream( &entry ) << "[" << i << "] - " << QString::fromStdString( pDev->serial.readS() ) << " - " << QString::fromStdString( pDev->product.readS() );
        comboBoxEntries.append( entry );
    }
    ui_.comboBox->addItems( comboBoxEntries );
}

//-----------------------------------------------------------------------------
void ContinuousCaptureQt::requestReady( void )
//-----------------------------------------------------------------------------
{
    QMutexLocker lockedScope( &lock_ );
    if( pThread_ && pThread_->isRunning() )
    {
        const int requestNumber = pCaptureThread_->getPendingRequestNr();
        if( requestNumber != INVALID_ID )
        {
            pImageCanvas_->SetImage( pFI_->getRequest( requestNumber ) );
        }
    }
}

//-----------------------------------------------------------------------------
void ContinuousCaptureQt::setExposureTime( int value )
//-----------------------------------------------------------------------------
{
    if( pAC_ )
    {
        pAC_->exposureTime.write( value );
        qDebug() << "Set Exposure Time Value to " << value << " - New Value: " << pAC_->exposureTime.read();
    }
}

//-----------------------------------------------------------------------------
void ContinuousCaptureQt::setupExposureTimeSlider( void )
//-----------------------------------------------------------------------------
{
    if( pAC_ )
    {
        conditionalSetEnumPropertyByString( pAC_->exposureAuto, "Off" );
        if( pAC_->exposureTime.isValid() )
        {
            if( pAC_->exposureTime.hasMaxValue() )
            {
                ui_.sliderExposureTime->setMaximum( 100000 );
            }
            if( pAC_->exposureTime.hasMinValue() )
            {
                ui_.sliderExposureTime->setMinimum( static_cast< int >( pAC_->exposureTime.getMinValue() ) );
            }
        }
        ui_.sliderExposureTime->setSingleStep( 100 );
        ui_.sliderExposureTime->setSliderPosition( static_cast< int >( pAC_->exposureTime.read() ) );
        ui_.sliderExposureTime->setVisible( true );
        ui_.label_exposureSlider->setVisible( true );
    }
    else
    {
        ui_.sliderExposureTime->setVisible( false );
        ui_.label_exposureSlider->setVisible( false );
    }
}

//-----------------------------------------------------------------------------
void ContinuousCaptureQt::startAcquisition( void )
//-----------------------------------------------------------------------------
{
    pCaptureThread_ = new CaptureThread( getDevice( ui_.comboBox->currentIndex() ), false, pFI_ );

    pThread_ = new QThread;
    pCaptureThread_->moveToThread( pThread_ );

    // Signal emitted in case of acquisition errors
    connect( pCaptureThread_, SIGNAL( error( QString ) ), this, SLOT( errorString( QString ) ) );

    connect( pCaptureThread_, SIGNAL( finished() ), pThread_, SLOT( quit() ) );
    connect( pCaptureThread_, SIGNAL( finished() ), pCaptureThread_, SLOT( deleteLater() ) );

    // signal emitted in case of an acquired image ready to be displayed
    connect( pCaptureThread_, SIGNAL( requestReady() ), this, SLOT( requestReady() ) );

    // start signal for the capture thread
    connect( pThread_, SIGNAL( started() ), pCaptureThread_, SLOT( process() ) );

    // termination signal of the capture thread

    // update signal for the statistics label
    connect( pCaptureThread_, SIGNAL( updateStatistics( const QString& ) ), this, SLOT( updateStatistics( const QString& ) ) );

    // update signal for the exposure time slider
    connect( ui_.sliderExposureTime, SIGNAL( valueChanged( int ) ), this, SLOT( setExposureTime( int ) ) );

    pThread_->start();

    if( pThread_->isRunning() == true )
    {
        ui_.acquisition_button->setEnabled( false );
    }
}

//-----------------------------------------------------------------------------
void ContinuousCaptureQt::userSelectedDeviceInComboBox( void )
//-----------------------------------------------------------------------------
{
    ui_.open_button->setEnabled( true );
    ui_.text_label->setText( "Please select a Device:" );
}
