/***************************************************************************
                          mirrorselector.cpp  -  description
                             -------------------
    begin                : Sat Nov 23 2002
    copyright            : (C) 2002 by Martin Merck
    email                : merck@astro.uni-wuerzburg.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is part of the MAGIC control software for the AMC.       *
 *   The software is only intended for use in the MAGIC telescope project  *
 *   All rights remain with the author.					   *
 ***************************************************************************/

#include "mirrorselector.h"

#include <stdio.h>
#include <stdlib.h>
#include <klocale.h>
#include <qfile.h>
#include <qbitmap.h>
#include <qtextstream.h>
#include <qpopupmenu.h>
#include <qmessagebox.h>
#include <qlayout.h>
#include <qlist.h>
#include <qtooltip.h>
#include <qwhatsthis.h>
#include "amcpushbutton.h"
#include "amcmirrorpanel.h"
#include "amcserialport.h"
#include "amcprogdlg.h"
#include "adjustmirrordlg.h"
#include "magicmirror.h"
#include "threadcontroller.h"

#define MASKFILENAME  "/home/amc/share/amc/TypeMask.xbm"
#define TYPE0FILENAME "/home/amc/share/amc/Type0Mirror.xbm"
#define TYPE1FILENAME "/home/amc/share/amc/Type1Mirror.xbm"
#define TYPE2FILENAME "/home/amc/share/amc/Type2Mirror.xbm"
#define TYPE3FILENAME "/home/amc/share/amc/Type3Mirror.xbm"
#define TYPE4FILENAME "/home/amc/share/amc/Type4Mirror.xbm"
#define TYPE5FILENAME "/home/amc/share/amc/Type5Mirror.xbm"
#define TYPE6FILENAME "/home/amc/share/amc/Type6Mirror.xbm"

#define MAX(a,b) ((a>b) ? a : b )

extern AMCSerialPort*	g_pPort[];
extern MagicMirror*		g_theMirror;

MirrorSelector::MirrorSelector(QWidget *parent, const char *name ) : QButtonGroup(parent,name)
{

	QBitmap theMask( MASKFILENAME );
	
	QPixmap* pixType[7];
	pixType[0] = new QPixmap( TYPE0FILENAME );
	pixType[1] = new QPixmap( TYPE1FILENAME );
	pixType[2] = new QPixmap( TYPE2FILENAME );
	pixType[3] = new QPixmap( TYPE3FILENAME );
	pixType[4] = new QPixmap( TYPE4FILENAME );
	pixType[5] = new QPixmap( TYPE5FILENAME );
	pixType[6] = new QPixmap( TYPE6FILENAME );
	// Check if we found the files with the pixmaps
	for(int i=0; i<7; i++)
	{
		if( pixType[i]->isNull() )
		{
	
	   	QMessageBox::critical( this,
   		   				"Can't open PIXMAP files for buttons",
								"The programm didn't find the files \'Type?Mirror.xbm\'\n"
								"We expect this file in the directory \'/home/amc/share/amc\'\n",
								"Quit" );
			exit(-1);									
		}
	}	
	
//	readPanelDescription();	
//	initPanelPositions();					
	
  resize( 500, 500 );
  setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1,
   							(QSizePolicy::SizeType)1,
   							sizePolicy().hasHeightForWidth() ) );
  setSizeIncrement( QSize( 0, 0 ) );

	
	// create the context menu.
	m_contextMenu = new QPopupMenu( this );
	m_contextMenu->insertItem( "Save positions", this, SLOT( savePositionsSlot() ) );

  this->setTitle( i18n( "Select a panel" ) );
  this->setColumnLayout(0, Qt::Vertical );
  this->layout()->setSpacing( 0 );
  this->layout()->setMargin( 6 );
	
	m_mirrorGroupLayout = new QGridLayout( this->layout() );
  m_mirrorGroupLayout->setAlignment( Qt::AlignTop );
  m_mirrorGroupLayout->setSpacing( 0 );
	m_mirrorGroupLayout->setMargin( 4 );

	QString str;
  int i,j;
  for( i=8; i>=-8; i--)
  {
	  for( j=-8; j<=8; j++)
	  {
	  	if( i<0 && j>=0)
	  		str.sprintf("Mirror_p%dn%d_Button",j,-i);
	   	if( i>=0 && j>=0)
	   		str.sprintf("Mirror_p%dp%d_Button",j,i);
	   	if( i<0 && j<0)
	   		str.sprintf("Mirror_n%dn%d_Button",-j,-i);
	   	if( i>=0 && j<0)
	   		str.sprintf("Mirror_n%dp%d_Button",-j,i);
																	
	    AMCPushButton* pButton = new AMCPushButton( this, str );
	    m_mirrorButton[i+8][j+8] = pButton;
	    pButton->setFlat( true );
	    pButton->setFlat( true );
	    pButton->setMinimumSize( QSize( 30, 30 ) );
	    pButton->setMaximumSize( QSize( 50, 50 ) );
	    pButton->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)0,
	                                         (QSizePolicy::SizeType)0,
	                                         true ) );
//   	pButton->setText( str.sprintf("%d,%d",j,i) );
 		  AMCMirrorPanel* thePanel = g_theMirror->panelAt( j+8, i+8 );
 		  int type = thePanel->type();
	 		pButton->setPixmap( *pixType[type] );
	 		if( type == 0)
 	   		pButton->setEnabled( false );
			else
			{
			  QToolTip::add( pButton, str.sprintf("%d,%d",j,i) );
		 		QWhatsThis::add( pButton,
		 										 str.sprintf( "This panel is connected to port:"
		 							 			 " %d box: %02d driver %d",
		     							      thePanel->port(),
		     							      thePanel->box(),
		     							      thePanel->driver() )
		    );
				if( ! thePanel->isInstalled() )
 		   		pButton->setEnabled( false );
			}
			m_mirrorGroupLayout->addWidget( pButton, 16 -(i+8), j+8 );

		}
	}		
	connect( this, SIGNAL(clicked(int)), SLOT(buttonSelectedSlot(int)) );

}

MirrorSelector::~MirrorSelector()
{
}

/** No descriptions */
void MirrorSelector::buttonSelectedSlot( int index ){
	
	int i = (index % 17) - 8;
	int j = -1 * ((index / 17) - 8);
	AMCMirrorPanel* pPanel = g_theMirror->panelAt( i+8, j+8 );
	emit panelSelectedSignal( pPanel );

}
/** No descriptions */
/*
void MirrorSelector::saveMirrorPanels()
{
	QCString line;
	
	QFile file( POSFILENAME );
	if( file.open( IO_WriteOnly ) )
	{
		QTextStream stream( &file );
		for(int j=0; j<17; j++)
		{
			line.sprintf("# Column %d\n",j-8);
			stream << line;
			for(int i=0; i<17; i++)
			{
				line.sprintf(" %2d %2d\t%4d\t%4d\n",
				m_Panel[i][j]->i(),
				m_Panel[i][j]->j(),
				m_Panel[i][j]->getX(),
				m_Panel[i][j]->getY() );
				stream << line;
			}
		}
					
	}
	else
	{
	   	int iRes = QMessageBox::critical( this,
   										 "Can't open panel position description file",
										 "The programm tried to open the file \'PanelPos.txt\'\n"
										 "in the directory \'/home/amc/\'.\n"
										 "The file may not have the right permissions.\n",
										 "Continue" );
	}
	file.close();
					
}
*/
/** Read he panel descriptions from the file "Panels.txt".
	This file contains for each panel a line with the following contents:
	i	j	type	port	box		driver	installed
	
	i: is the first panel index (counting from left to right)
	j: is the second panel index (counting from bottom to top)
	type: the panel type (see the file for a description of types)
	port: the serial port this box is connected to.
		  (The numbering corresponds to the numbers on the cables.
		   If only 1 Meilhaus ME8100 card is installed on linux boxes
		   we have the following correspondance to device files
		   port 1 == /dev/ttyS4 ... port 8 = /dev/ttyS11)
	box: the number of the AMC box.
	driver: The internal AMC driver to which this panel is connected.
	installed: Flag indicating if this panel is installed (0=no, 1=yes)
*/
/*
void MirrorSelector::readPanelDescription(){
	
	m_iNumPanels = 0;
	QFile file( PANELFILENAME );
	if( file.open( IO_ReadOnly ) )
	{
		QTextStream stream( &file );
		QString line;
		while( !stream.eof() )
		{
			line = stream.readLine();
			if( line[0] == '#')
				continue;
			int ii, ij, iType, iPort, iBox, iDriver, iInst;
			sscanf( line.data(),"%d %d %d %d %d %d %d",
								&ii, &ij, &iType, &iPort,
								&iBox, &iDriver, &iInst );
			m_Panel[ii+8][ij+8] = new AMCMirrorPanel( ii, ij, iType, iPort, iBox, iDriver );
			m_Panel[ii+8][ij+8]->setInstalled(iInst != 0);
			if(iInst != 0)
				m_iNumPanels++;
		}
	}
	else
	{
	   	int iRes = QMessageBox::critical( this,
   										 "Can't open panel description file",
										 "The programm didn't find the file \'Panels.txt\'\n"
										 "We expect this file in the directory \'/home/amc/\'\n",
										 "Quit" );
		exit(-1);									
	}

	file.close();
}
*/
/** Here we read the stored panel positions from the file PanelPos.txt
	We then go through all panels, center them and go to the stored position.
 */
void MirrorSelector::initPanelPositions()
{
//	readPanelPositions();
	
   	int iRes = QMessageBox::warning( this,
   									 "Lengthy operation ahead !!!",
									 "We will now center all mirror panels and realign them\n"
									 "to the stored positions. This operation is sequential\n"
									 "through all mirrors and will take 15 minutes!\n"
									 "You may choose not to center now, but this is only\n"
									 "advisable if you now the positions are correct!\n"
									 "Do you want to center?",
									 "Yes",
									 "No" );
	if (iRes == 1)
		return;
	
	QString qsMsg1("Initializing mirror panels");
	QString qsMsg2("Centering and setting stored position.");
	AMCProgDlg* pDialog = new AMCProgDlg( MOTOR_THREAD_CTRL, this, qsMsg1, true );
	pDialog->setText( qsMsg2 );
	pDialog->start();
	pDialog->exec();
	delete pDialog;

	return;
	
}


/** Read the stored panel positions from the file "PanelPos.txt"
	This file contains for each panel a line with the following contents:
	i	j	X	Y
	
	i: is the first panel index (counting from left to right)
	j: is the second panel index (counting from bottom to top)
	X: position of the X motor relative to the center position
	Y: position of the Y motor relative to the center position
 */
/*
void MirrorSelector::readPanelPositions()
{
	QFile file( POSFILENAME );
	if( file.open( IO_ReadOnly ) )
	{
		QTextStream stream( &file );
		QString line;
		while( !stream.eof() )
		{
			line = stream.readLine();
			
			// Skip comment lines
			if( line[0] == '#')
				continue;
				
			int ii, ij, iX, iY;
			sscanf( line.data(),"%d %d %d %d",
								&ii, &ij, &iX, &iY );
			m_Panel[ii+8][ij+8]->setX(iX);
			m_Panel[ii+8][ij+8]->setY(iY);
		}
	}
	else
	{
	   	int iRes = QMessageBox::critical( this,
   										 "Can't open panel position description file",
										 "The programm didn't find the file \'PanelPos.txt\'\n"
										 "We expect this file in the directory \'/home/amc/\'\n",
										 "Quit" );
		exit(-1);									
	}
	file.close();
	
	return;
}
*/

/** Save the positions to the file. */
void MirrorSelector::savePositionsSlot()
{
	qDebug("MirrorSelector::savePositionsSlot");
	g_theMirror->saveMirrorPanels();
}

/** Check to see if the right mouse button was pressed and
	show the context menu in this case.
  */
void MirrorSelector::mousePressEvent( QMouseEvent* p_pEvent )
{
	if( p_pEvent->button() == RightButton )
		m_contextMenu->exec( QCursor::pos() );
}
