/***************************************************************************
                          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/AMC/share/amc/TypeMask.xbm"
#define TYPE0FILENAME "/home/amc/AMC/share/amc/Type0Mirror.xbm"
#define TYPE1FILENAME "/home/amc/AMC/share/amc/Type1Mirror.xbm"
#define TYPE2FILENAME "/home/amc/AMC/share/amc/Type2Mirror.xbm"
#define TYPE3FILENAME "/home/amc/AMC/share/amc/Type3Mirror.xbm"
#define TYPE4FILENAME "/home/amc/AMC/share/amc/Type4Mirror.xbm"
#define TYPE5FILENAME "/home/amc/AMC/share/amc/Type5Mirror.xbm"
#define TYPE6FILENAME "/home/amc/AMC/share/amc/Type6Mirror.xbm"

#define TYPE1LFILENAME "/home/amc/AMC/share/amc/Type1MirrorLas.xpm"
#define TYPE2LFILENAME "/home/amc/AMC/share/amc/Type2MirrorLas.xpm"
#define TYPE3LFILENAME "/home/amc/AMC/share/amc/Type3MirrorLas.xpm"
#define TYPE4LFILENAME "/home/amc/AMC/share/amc/Type4MirrorLas.xpm"
#define TYPE5LFILENAME "/home/amc/AMC/share/amc/Type5MirrorLas.xpm"
#define TYPE6LFILENAME "/home/amc/AMC/share/amc/Type6MirrorLas.xpm"

#define TYPE1LMFILENAME "/home/amc/AMC/share/amc/Type1MirrorLas.xbm"
#define TYPE2LMFILENAME "/home/amc/AMC/share/amc/Type2MirrorLas.xbm"
#define TYPE3LMFILENAME "/home/amc/AMC/share/amc/Type3MirrorLas.xbm"
#define TYPE4LMFILENAME "/home/amc/AMC/share/amc/Type4MirrorLas.xbm"
#define TYPE5LMFILENAME "/home/amc/AMC/share/amc/Type5MirrorLas.xbm"
#define TYPE6LMFILENAME "/home/amc/AMC/share/amc/Type6MirrorLas.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 );
	
	m_pixType[0] = new QPixmap( TYPE0FILENAME );
	m_pixType[1] = new QPixmap( TYPE1FILENAME );
	m_pixType[2] = new QPixmap( TYPE2FILENAME );
	m_pixType[3] = new QPixmap( TYPE3FILENAME );
	m_pixType[4] = new QPixmap( TYPE4FILENAME );
	m_pixType[5] = new QPixmap( TYPE5FILENAME );
	m_pixType[6] = new QPixmap( TYPE6FILENAME );

	m_pixType[7] = new QPixmap( TYPE1LFILENAME );
	m_pixType[8] = new QPixmap( TYPE2LFILENAME );
	m_pixType[9] = new QPixmap( TYPE3LFILENAME );
	m_pixType[10] = new QPixmap( TYPE4LFILENAME );
	m_pixType[11] = new QPixmap( TYPE5LFILENAME );
	m_pixType[12] = new QPixmap( TYPE6LFILENAME );

	m_bitMask[0] = new QBitmap( TYPE1LMFILENAME );
	m_bitMask[1] = new QBitmap( TYPE2LMFILENAME );
	m_bitMask[2] = new QBitmap( TYPE3LMFILENAME );
	m_bitMask[3] = new QBitmap( TYPE4LMFILENAME );
	m_bitMask[4] = new QBitmap( TYPE5LMFILENAME );
	m_bitMask[5] = new QBitmap( TYPE6LMFILENAME );

  m_pixType[7]->setMask( *m_bitMask[0]);
  m_pixType[8]->setMask( *m_bitMask[1]);
  m_pixType[9]->setMask( *m_bitMask[2]);
  m_pixType[10]->setMask( *m_bitMask[3]);
  m_pixType[11]->setMask( *m_bitMask[4]);
  m_pixType[12]->setMask( *m_bitMask[5]);

	// Check if we found the files with the pixmaps
	for(int i=0; i<13; i++)
	{
		if( m_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/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->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( *m_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 );

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

}

MirrorSelector::~MirrorSelector()
{
	for(int i=0; i<13; i++)
	{
		delete m_pixType[i];
    m_pixType[i] = NULL;
  }
	for(int i=0; i<6; i++)
	{
		delete m_bitMask[i];
    m_bitMask[i] = NULL;
  }
}

/** 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 );
	QButton* pButton = m_mirrorButton[j+8][i+8];
	if( m_pSelectedButton )
		m_pSelectedButton->setBackgroundMode( QWidget::PaletteBackground );

	pButton->setBackgroundMode( QWidget::PaletteMid );
	m_pSelectedButton = pButton;
	emit panelSelectedSignal( pPanel );

}

/**
 * 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;
	
}


/** 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() );
}

/**
 * Change the icon to show that the laser is on or off.
 */
void MirrorSelector::toggelLaser( AMCMirrorPanel* p_pPanel, bool p_zOn )
{
	AMCPushButton* pButton = m_mirrorButton[p_pPanel->j()+8][p_pPanel->i()+8];

 	int type = p_pPanel->type();
	if( p_zOn )
		type += 6; 		
	pButton->setPixmap( *m_pixType[type] );
}
