/***************************************************************************
                          amcprogdlg.cpp  -  description
                             -------------------
    begin                : Sun Apr 6 2003
    copyright            : (C) 2003 by Martin Merck
    email                : merck@astro.uni-wuerzburg.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include "amcprogdlg.h"
#include "activemirrorcontrol.h"
#include "amclog.h"
#include "amcmirrorpanel.h"
#include "amcstate.h"
#include "errortestthreadcontroller.h"
#include "heatstate.h"
#include "magicmirror.h"
#include "threadevent.h"
#include "threadcontroller.h"
#include <qlabel.h>
#include <qprogressbar.h>
#include <qlineedit.h>
#include <qdatetime.h>
#include <unistd.h>

extern AMCLog*			g_pLog;
extern MagicMirror* g_theMirror;
extern AMCState*    g_pAMCState;
extern HEATState*   g_pHEATState;

AMCProgDlg::AMCProgDlg( int p_iType, QWidget *parent, const char *name, bool modal )
	: AMCProgDlgBase( parent, name, modal ),
		m_iType( p_iType ), m_iNumErrors( 0 ), m_zTrue( false ), m_zParallel( true )
{
	ProgressBar->setTotalSteps( g_theMirror->getNumPanels() );

	for( int i=0; i<17; i++)
		for( int j=0; j<17; j++)
			m_arrErrors[i][j] = 0;

	for( int i=0; i<8; i++)
		m_portErrors[i] = 0;

  if( m_iType == LASER_ADJUST_THREAD_CTRL)
	{
		double dAlt, dAz;
		((ActiveMirrorControl*) parent)->getZdAz( dAlt, dAz );
		
		QDateTime theDT = QDateTime::currentDateTime();
		QDate theDate = theDT.date();
		QTime theTime = theDT.time();

		QString qsFileName;
		qsFileName.sprintf( "/home/amc/data/AMC_%04d_%02d_%02d_%02d_%02d_%02d__(%02d_%03d).info",
    	                  theDate.year(), theDate.month(), theDate.day(),
                        theTime.hour(), theTime.minute(), theTime.second(),
				  							(int) dAlt, (int) dAz );
		m_pFile = new QFile( qsFileName );

		if( m_pFile->open( IO_WriteOnly ) )
		{
			m_pStream = new QTextStream( m_pFile );
		}
  }

  if( m_iType == ERROR_TEST_THREAD_CTRL)
	{
		ActiveMirrorControl* pAMC = (ActiveMirrorControl*) parent;
		ProgressBar->setTotalSteps( pAMC->getNumLoops() * 8 );

		QDateTime theDT = QDateTime::currentDateTime();
		QDate theDate = theDT.date();
		QTime theTime = theDT.time();

		QString qsFileName;
		qsFileName.sprintf( "/home/amc/data/AMC_%04d_%02d_%02d_%02d_%02d_%02d.errtest",
    	                  theDate.year(), theDate.month(), theDate.day(),
                        theTime.hour(), theTime.minute(), theTime.second() );
		m_pFile = new QFile( qsFileName );

		if( m_pFile->open( IO_WriteOnly ) )
		{
			m_pStream = new QTextStream( m_pFile );
		}
  }
}

AMCProgDlg::~AMCProgDlg(){

  if ( m_iType == ERROR_TEST_THREAD_CTRL )
	{
		for( int j=16; j>=0; j--)
		{
			for( int i=0; i<17 ; i++ )
			{
				if( g_theMirror->panelAt(i,j)->isInstalled() )
				{
					m_portErrors[ g_theMirror->panelAt(i,j)->port()-1 ] += m_arrErrors[i][j];
					*m_pStream << std::setw(4) << m_arrErrors[i][j] << "  ";
        }
				else
				{
					if( m_arrErrors[i][j] != 0)
					{
						qDebug("WARNING: %d Errors in uninstalled panel (%d,%d)", m_arrErrors[i][j], i, j );
					}
					*m_pStream << "      ";
				}
			}
			*m_pStream << std::endl;
		}
		*m_pStream << std::endl;
		for( int i=0; i<8; i++)
		{
			*m_pStream << "Port " << std::setw(1) << i+1 << ": " << std::setw(6) << m_portErrors[i] << std::endl;
		}
		*m_pStream << std::endl;
	}

  if ( ( m_iType == LASER_ADJUST_THREAD_CTRL)
     ||
       ( m_iType == ERROR_TEST_THREAD_CTRL) )
	{
	  m_pFile->close();
  	delete m_pStream;
  	delete m_pFile;
	}
}

void AMCProgDlg::setText( const QString& p_qsText )
{
	ProgressLabel->setText( p_qsText );
}

void AMCProgDlg::customEvent(QCustomEvent *e)
{
  if ( e->type() == THREAD_EVENT )
	{
		ThreadEvent* te = (ThreadEvent*)e;
    qDebug(te->getMessage());
	  if( m_iType == LASER_ADJUST_THREAD_CTRL)
      *m_pStream << te->getMessage() << endl;
	}

  if ( e->type() == THREAD_ERROR_EVENT )
	{
		ThreadErrorEvent* tee = (ThreadErrorEvent*)e;
		QString msg;
		msg.sprintf("%d", ++m_iNumErrors);
		NumErrors->setText( msg );
		g_pLog->logError( tee->getMessage(), tee->getError() );
	  if( m_iType == LASER_ADJUST_THREAD_CTRL)
      *m_pStream << tee->getMessage() << tee->getError().formatError(7) << endl;
	  if( m_iType == ERROR_TEST_THREAD_CTRL)
		{
      int i,j;
			tee->getError().getPanel(i, j);
			m_arrErrors[i+8][j+8]++;
//      scanf( tee->getError().getErrorText(), "%*s (%d,%d)", &i, &j);
      *m_pStream << tee->getError().formatError(0) << endl;
//			qDebug("Error in Panel (%d,%d)", i, j);
		}
	}

  if ( e->type() == PROGRESS_EVENT )
		ProgressBar->setProgress( ProgressBar->progress()+1 );

  if ( e->type() == THREAD_END_EVENT )
		this->accept();
}

void AMCProgDlg::run()
{
  qDebug("AMCProgDlg PID: %d - PPID: %d", getpid(), getppid() );
  QTime t;
  t.start();                          // start clock

	for(int i=0; i<8; i++)
	{
		qDebug("Starting ThreadController of Type: %d number %d", m_iType, i);
		if( ! m_zParallel )
			m_pTController[i] = ThreadController::getController( m_iType, g_theMirror->panelList(), this );
		else
			m_pTController[i] = ThreadController::getController( m_iType, g_theMirror->panelForPort(i), this );
		m_pTController[i]->setBool( m_zTrue );
		// Set the number of Loops for the ErrorTestThreadController
		if( m_iType == ERROR_TEST_THREAD_CTRL )
		{
			int iLoops = ((ActiveMirrorControl*) parentWidget())->getNumLoops();
      ((ErrorTestThreadController*) m_pTController[i])->setNumLoops( iLoops );
		}
		m_pTController[i]->start();

		// If we do not want to execute in parallel we must exit the loop here.
		if( ! m_zParallel )
			break;
	}

	if( m_zParallel )
	{
		for(int i=0; i<8; i++)
		{
			m_pTController[i]->wait();
			delete m_pTController[i];
		}
	}
	else
	{
		m_pTController[0]->wait();
			delete m_pTController[0];
	}		

	QString qsMsg;
	qsMsg.sprintf( "Total Time: %dms", t.elapsed() );
	QThread::postEvent( this, new ThreadEvent( qsMsg ) );
	QThread::postEvent( this, new QCustomEvent( THREAD_END_EVENT ) );

  bool zOk;
  int iNumErr = NumErrors->text().toInt( &zOk );
	if( zOk == true )
    g_pAMCState->setErrorPanels( iNumErr );

}
/** No descriptions */
void AMCProgDlg::reject()
{
	if( m_zParallel )
	{
		for(int i=0; i<8; i++)
			m_pTController[i]->stop();
	}
	else
	{
		m_pTController[0]->stop();
	}
}
