/***************************************************************************
 *	TmsStateGui.cpp	TMS Cycle parameters State display
 *			T.Barnaby,	BEAM Ltd,	2007-11-13
 ***************************************************************************
 */
#include <qmenubar.h>
#include <qmessagebox.h>
#include <qlabel.h>
#include <qinputdialog.h>
#include <qimage.h>

#include <TmsStateGui.h>
#include <BFile.h>
#include <unistd.h>
#include <math.h>

const int	nGraphs = 7;

#define	FILE_DUMP	0

TmsStateGui::TmsStateGui(QWidget* p) : QVBox(p){
	opos = 0;
	orange = orangeMax = 512;
}

TmsStateGui::~TmsStateGui(){
}

void TmsStateGui::init(){
	BError		err;
	BGraph*		graph;
	int		n;
	QHBox*		cbox;
	
	ographs.resize(nGraphs);
	for(n = 0; n < nGraphs; n++){
		graph = new BGraph(this);

		graph->setPlotType(BGraph::LINES);
		graph->setGrid(16, 0);
		switch(n){
		case 0:	graph->setYLabel("FREF");	break;
		case 1:	graph->setYLabel("LO1");	break;
		case 2:	graph->setYLabel("LO2");	break;
		case 3:	graph->setYLabel("GATE");	break;
		case 4:	graph->setYLabel("BLR");	break;
		case 5:	graph->setYLabel("Mean1");	break;
		case 6:	graph->setYLabel("Mean2");	break;
		}
				
		ographs[n] = graph;
	}
	ographs[ographs.size() - 1]->setXLabel("PLL Entry");

	cbox = new QHBox(this);

	ozoomIn = new QPushButton("Zoom In", cbox);
	ozoomIn->setFixedWidth(80);
	ozoomOut = new QPushButton("Zoom Out", cbox);
	ozoomOut->setFixedWidth(80);

	oscrollBar = new QScrollBar(Qt::Horizontal, cbox);
	oscrollBar->setMinValue(0);
	oscrollBar->setMaxValue(0);
	oscrollBar->setPageStep(orange);

	oinfoBox = new QGrid(2, Horizontal, this);


	new QLabel("State", oinfoBox);
	ostate = new QSpinBox(oinfoBox);
	ostate->setMaxValue(0);
	ostate->setMinValue(0);

	new QLabel("State Info", oinfoBox);
	ostateInfo = new QLineEdit(oinfoBox);

	new QLabel("Next State", oinfoBox);
	ostateField0 = new QLineEdit(oinfoBox);

	new QLabel("Switch Bits", oinfoBox);
	ostateField1 = new QLineEdit(oinfoBox);

	connect(ostate, SIGNAL(valueChanged(int)), this, SLOT(updateState()));
	connect(oscrollBar, SIGNAL(valueChanged(int)), this, SLOT(scroll()));
	connect(ozoomOut, SIGNAL(clicked()), this, SLOT(zoomOut()));
	connect(ozoomIn, SIGNAL(clicked()), this, SLOT(zoomIn()));
}

BError	TmsStateGui::view(Tms::CycleParamEdit& cycleParam, int reset){
	BError	err;
	
	ocycleParam = cycleParam;
	if(reset)
		ostate->setValue(0);
	update();
	
	return err;
}

void TmsStateGui::setState(int num){
	ostate->setValue(num);
	update();
}

void	TmsStateGui::updateState(){
	update();
	emit stateChanged(ostate->value());
}

void	TmsStateGui::update(){
	int			state;
	int			s;
	BArray<float>		data[nGraphs];
	Tms::TmsPhase		p;
	Tms::TmsState		sf;
	int			n;
	BString			str;
#if FILE_DUMP
	BFile			file("data.txt", "w");
#endif
	
	if(ocycleParam.cycleType == "")
		return;

	ostate->setMaxValue(ocycleParam.stateTable.size() - 1);

	state = ostate->value();
	
	str.printf("Period: %d, Harmonic: %d, NumBunches: %d, BunchMask: 0x%x, State: 0x%08.8x",
		ocycleParam.stateTable[state].period, ocycleParam.stateTable[state].harmonic,
		ocycleParam.stateTable[state].numBunches, ocycleParam.stateTable[state].bunchMask, ocycleParam.stateTable[state].state);

	ostateInfo->clear();
	ostateInfo->setText(str.retStr());

	sf.value = ocycleParam.stateTable[state].state;

	str.printf("Delay: %d HChange: %d, Injection: %d, CalStart: %d, CalStop: %d, CycleStop: %d",
		sf.delay, sf.hchange, sf.injection, sf.calStart, sf.calStop, sf.cycleStop); 

	ostateField0->clear();
	ostateField0->setText(str.retStr());
	
	str.printf("pllReference1: %d, pllLO1FromAddress: %d, pllReference2: %d, pllLO2FromAddress: %d, pllFeedbackSelect: %d, aquireData: %d",
		sf.pllReference1, sf.pllLO1FromAddress, sf.pllReference2, sf.pllLO2FromAddress, sf.pllFeedbackSelect, sf.acquireData); 

	ostateField1->clear();
	ostateField1->setText(str.retStr());
	
	for(n = 0; n < nGraphs; n++){
		data[n].resize(512);
	}
	
	for(s = 0; s < 512; s++){
		p.value = ocycleParam.stateTable[state].phaseTable[s];
		
		if(s < 256)
			data[0][s] = 1;
		if(p.lo1)
			data[1][s] = 1;
		if(p.lo2)
			data[2][s] = 1;
		if(p.gate)
			data[3][s] = 1;
		if(p.blr)
			data[4][s] = 1;
		if(p.meanFilter1)
			data[5][s] = 1;
		if(p.meanFilter2)
			data[6][s] = 1;
		
#if FILE_DUMP
		file.printf("%f %f %f %f %f %f %f\n", data[0][s], data[1][s], data[2][s], data[3][s], data[4][s], data[5][s], data[6][s]); 
#endif
	}

	for(n = 0; n < nGraphs; n++){
		ographs[n]->setData(data[n]);
	}
}

void TmsStateGui::scroll(){
	unsigned int	i;
	
	opos = oscrollBar->value();
	
	for(i = 0; i < ographs.size(); i++){
		ographs[i]->setXRange(opos, opos + orange - 1);
	}
}

void TmsStateGui::zoomIn(){
	zoom(1);
}

void TmsStateGui::zoomOut(){
	zoom(0);
}

void TmsStateGui::zoom(int in){
	unsigned int 	i;

	if(in)
		orange = orange / 2;
	else
		orange = orange * 2;
	
	if(orange < 16)
		orange = 16;
	if(orange > orangeMax)
		orange = orangeMax;
	
	if(opos + orange > orangeMax)
		opos = orangeMax - orange;
			
	for(i = 0; i < ographs.size(); i++){
		ographs[i]->setXRange(opos, opos + orange - 1);
	}	

	oscrollBar->setPageStep(orange);
	oscrollBar->setMaxValue(orangeMax - orange);
	oscrollBar->setValue(opos);
}
