#include <QtGui>
#include "rxdata.h"
#include "SysConfig.h"
#include "CanData.h"
#include "fcan_view.h"

RxData::RxData(QWidget *parent)
	: QWidget(parent)
{
	ui.setupUi(this);
	hide();

	pSysConfig = NULL;
	pHardware = NULL;
	pRxDataFilter = NULL;
	pInformation = NULL;
	pCanData = NULL;
	pCanDataMng = NULL;
	pFcanView = NULL;

	//	QTimer Create
	ReadTimer = new QTimer(this);
    connect( ReadTimer,SIGNAL(timeout()),this,SLOT(timRead()));
	//	QTimer Create
	DisplayTimer = new QTimer(this);
    connect( DisplayTimer,SIGNAL(timeout()),this,SLOT(timDisplay()));
	// btnRxStartStop
	connect( ui.btnRxStartStop,SIGNAL(clicked()),this,SLOT(btnRxStartStop_Click()));
	// btnRxDataFind
	connect( ui.btnRxDataFind,SIGNAL(clicked()),this,SLOT(btnRxDataFind_Click()));
	// chbViewReport
	connect( ui.chbViewReport,SIGNAL(toggled(bool)),this,SLOT(chbViewReport_Toggled()));

	ui.btnRxStartStop->setEnabled(true);
	ui.btnRxStartStop->setText("Read Message");
	ui.btnRxDataFind->setEnabled(true);

	MessageCountNow = 0;
	DisplayMessageCountNow = 0;
	RcvMessageCountMax = 0;
	RcvCountMax_str = "0";
	TimeGetFlag = 0;
	DefaultTimeMillis = 0;
	DefaultTimeMicros = 0;
	RxDataTimeMillis = 0;
	RxDataTimeMicros = 0;

}

RxData::~RxData()
{

}
////////////////////////////////////////
// Pointer Setting
////////////////////////////////////////
void RxData::SysConfigSet( SysConfig * sysconfig )
{
	pSysConfig = sysconfig;
}
void RxData::HardwareSet( Hardware * hardware )
{
	pHardware = hardware;
}
void RxData::RxDataFilterSet( RxDataFilter * rxdatafilter )
{
	pRxDataFilter = rxdatafilter;
}
void RxData::InformationSet( Information * information )
{
	pInformation = information;
}
void RxData::CanDataSet( CanData * candata )
{
	pCanData = candata;
}
void RxData::CanDataMngSet( CanDataMng * candatamng )
{
	pCanDataMng = candatamng;
}
void RxData::FcanViewSet( FCAN_View * fcanview )
{
	pFcanView = fcanview;
}
////////////////////////////////////////
// RxData Function
////////////////////////////////////////
// Close
void RxData::closeEvent(QCloseEvent * pEvent)
{
	ReadTimer->stop();
	DisplayTimer->stop();
	pFcanView->ViewWindow[2] = false;
}

// ReSize
void RxData::resizeEvent(QResizeEvent * /* event */)
{
	ui.txtRxData->resize((width()-19),(height() - 129));
}

// btnReadStartStop
void RxData::btnRxStartStop_Click()
{
	QMessageBox msgBox;
	int qt_ret;
	int lp;
	TPCANMsg CANMsg;
	TPCANTimestamp CANTimeStamp;
	TPCANStatus stsResult;
	QString qt_str;
	DWORD MessageCount = 0;
	DWORD TimerCount = 0;
	DWORD FilterCount = 0;
	DWORD FilterFlag = 0;

	// Read Message Select
	if( ui.btnRxStartStop->text() == "Read Message" ){
		ui.btnRxStartStop->setText("Stop Message");
		if( pHardware->HardwareInitSet == 1 ){
			ui.btnRxDataFind->setEnabled(false);
			ui.txtRxDataTime->setEnabled(false);
			ui.txtRxDataFile->setEnabled(false);
			ui.chbViewReport->setEnabled(false);
			ui.txtDisplayTime->setEnabled(false);
			pFcanView->statusBar_message("    >>>> During the reception");

			MessageCountNow = 0;
			DisplayMessageCountNow = 0;

			// HardwareReset
			pHardware->ResetSet();
			// Buffer Clear
			pCanDataMng->clear();
			// RxCanData Clear
			// TimeStanp Clear
			// RxData Window Clear
			ui.txtRxData->setText("");
			ui.txtRxData->append(" Time[ms.us] | Type |  CobID   |  NodeID  | DLC | DATA ");
			TimeGetFlag = 0;

			// RcvCount
			RcvCountMax_str = ui.txtRcvFrameCount->text();
			RcvMessageCountMax = (DWORD)RcvCountMax_str.toUInt(0,10);

			// Timer Start
			qt_str = ui.txtRxDataTime->text();
			TimerCount = (DWORD)qt_str.toUInt(0,16);
			ReadTimer->start(TimerCount);
			// DisplayTimer Start
			if( ui.chbViewReport->isChecked() ){
				qt_str = ui.txtDisplayTime->text();
				TimerCount = (DWORD)qt_str.toUInt(0,16);
				DisplayTimer->start(TimerCount);
			}
		} else {
			msgBox.setText("Error: Hardware Not Initialize!");
			qt_ret = msgBox.exec();
		}
	} else {
	// Stop Message Select
		ui.btnRxStartStop->setText("Read Message");
	}

}
// btnReadFileFind
void RxData::btnRxDataFind_Click()
{
	QString fileName = QFileDialog::getSaveFileName(
														this,
					   									tr("Open Data file"),	// title
//														QDir::homePath(),		// 表示するときのカレントpath
														QDir::currentPath(),	// 表示するときのカレントpath
														tr("All Files (*)"));	// filter
	ui.txtRxDataFile->setText(fileName);

}
void RxData::RxDataFileWrite(DWORD Count)
{
	CanData CanDataVec;
	QString qt_str;
	QString qt_writedata;
	DWORD MessageCount = 0;
	DWORD MessageDataLength = 0;
	DWORD DataCount;

	// Recive Message File Write Start
	// File Name
	qt_str = ui.txtRxDataFile->text();
	QFile RxFile(qt_str);

	if(!RxFile.open(QIODevice::WriteOnly)) {
		pInformation->Information_set("");
		pInformation->Information_append("OutPut File Not Open");
	} else {
		QTextStream outputfile(&RxFile);
		for(MessageCount = 0; MessageCount < Count; ++MessageCount ){
			// Get Buffer
			if(pCanDataMng->get(MessageCount,CanDataVec)){
				break;
			}
			// Time
			qt_writedata = "R,";
			qt_writedata = qt_writedata + qt_str.sprintf("%d", CanDataVec.mtime) + ".";
			qt_writedata = qt_writedata + qt_str.sprintf("%03d", CanDataVec.utime) + ",";
			// Cob ID
			qt_writedata = qt_writedata + qt_str.sprintf("%08X", CanDataVec.func) + ",";
			// ID
			qt_writedata = qt_writedata + qt_str.sprintf("%08X", CanDataVec.id) + ",";
			// Length
			if( CanDataVec.len == 0x9 ){
				qt_writedata = qt_writedata + qt_str.sprintf("%02X", CanDataVec.data[0]);
				MessageDataLength = CanDataVec.data[0];
			} else {
				qt_writedata = qt_writedata + qt_str.sprintf("%02X", CanDataVec.len);
				MessageDataLength = CanDataVec.len;
			}
			// Data
			if( CanDataVec.len == 0x9 ){
				qt_writedata = qt_writedata + ",RTR";
			} else {
				for(DataCount = 0; DataCount < MessageDataLength; DataCount=DataCount+1 ){
					qt_writedata = qt_writedata + "," + qt_str.sprintf("%02X", CanDataVec.data[DataCount]);
				}
			}
			qt_writedata = qt_writedata + "\n";
			// File Write
			outputfile << qt_writedata;
		}
		RxFile.close();
	}

	pInformation->Information_append("Message was successfully Filr Write");

}
void RxData::ProcessMessage(TPCANMsg MyMsg, TPCANTimestamp MyTimeStamp)
{
	CanData CanDataVec;
	int i;
	int RxTmp;
	DWORD MessageDataLength = 0;


	// Recive Time
	RxDataTime(MyTimeStamp);
	CanDataVec.mtime = (DWORD)RxDataTimeMillis;
	CanDataVec.utime = (WORD)RxDataTimeMicros;

	// Recive Type / Recive CobId / Recive Id
	if(( MyMsg.MSGTYPE & 0x02 ) == PCAN_MESSAGE_STANDARD ){
		// Recive Type
		CanDataVec.type = 0;
		// Recive CobId
		RxTmp = MyMsg.ID;
		RxTmp = RxTmp & pFcanView->StdCobIDMask;
		CanDataVec.func = RxTmp;
		// Recive Id
		RxTmp = MyMsg.ID;
		RxTmp = RxTmp & pFcanView->StdNodeIDMask;
		CanDataVec.id = RxTmp;
	} else if(( MyMsg.MSGTYPE & 0x02 ) == PCAN_MESSAGE_EXTENDED ){
		// Recive Type
		CanDataVec.type = 1;
		// Recive CobId
		RxTmp = MyMsg.ID;
		RxTmp = RxTmp & pFcanView->ExtCobIDMask;
		CanDataVec.func = RxTmp;
		// Recive Id
		RxTmp = MyMsg.ID;
		RxTmp = RxTmp & pFcanView->ExtNodeIDMask;
		CanDataVec.id = RxTmp;
	} else {
		CanDataVec.type = 2;
		// Recive CobId
		RxTmp = MyMsg.ID;
		RxTmp = RxTmp & pFcanView->ExtCobIDMask;
		CanDataVec.func = RxTmp;
		// Recive Id
		RxTmp = MyMsg.ID;
		RxTmp = RxTmp & pFcanView->ExtNodeIDMask;
		CanDataVec.id = RxTmp;
	}

	// Recive Length
	if(( MyMsg.MSGTYPE & 0x01 ) == PCAN_MESSAGE_RTR ){
		CanDataVec.len = 0x09;
	} else {
		CanDataVec.len = MyMsg.LEN;
	}
	MessageDataLength = MyMsg.LEN;

	// Recive Data
	if(( MyMsg.MSGTYPE & 0x01 ) == PCAN_MESSAGE_RTR ){
		for(i=0; i<MessageDataLength; i=i+1) {
			if( i == 0 ){
				CanDataVec.data[0] = MyMsg.LEN;
			} else {
				CanDataVec.data[i] = 0x00;
			}
		}
	} else {
		for(i=0; i<MessageDataLength; i=i+1) {
			CanDataVec.data[i] = MyMsg.DATA[i];
		}
	}

	// Buffer Write
	pCanDataMng->set(CanDataVec);

}

// Read Messages
TPCANStatus RxData::Read_Message(TPCANMsg* CANMsg, TPCANTimestamp* CANTimeStamp)
{
	TPCANStatus stsResult;

	stsResult = pHardware->timRead(CANMsg, CANTimeStamp);
	return stsResult;

}
// Read Messages Time 
void RxData::RxDataTime(TPCANTimestamp MyTimeStamp)
{
	int MicroFlag;

	if( TimeGetFlag == 0 ){
		DefaultTimeMillis = (DWORD)MyTimeStamp.millis;
		DefaultTimeMicros = MyTimeStamp.micros;
		RxDataTimeMillis = 0;
		RxDataTimeMicros = 0;
		TimeGetFlag = 1;
	} else {
		// Micro
		if( MyTimeStamp.micros < DefaultTimeMicros ){
			RxDataTimeMicros = 1000 - DefaultTimeMicros + MyTimeStamp.micros;
			MicroFlag = 1;
		} else {
			RxDataTimeMicros = MyTimeStamp.micros - DefaultTimeMicros;
			MicroFlag = 0;
		}
		// Millis
		if( MicroFlag == 0 ){
			RxDataTimeMillis = MyTimeStamp.millis - DefaultTimeMillis;
		} else {
			RxDataTimeMillis = MyTimeStamp.millis - DefaultTimeMillis - 1;
		}
	}

}
// chbViewReport
void RxData::chbViewReport_Toggled()
{

	if( ui.chbViewReport->isChecked() ){
		ui.txtDisplayTime->setEnabled(true);
	} else {
		DisplayTimer->stop();
		ui.txtDisplayTime->setEnabled(false);
	}
}
// timRead
void RxData::timRead()
{
	TPCANMsg CANMsg;
	TPCANTimestamp CANTimeStamp;
	TPCANStatus stsResult;
	QString qt_str;
	DWORD ReadCount = 0;
	DWORD MessageCount = 0;
	DWORD FilterCount = 0;
	DWORD FilterFlag = 0;

	MessageCount = MessageCountNow;

	// Recive Message Start
	if(( ui.btnRxStartStop->text() == "Stop Message" )
		&& ( MessageCount < RcvMessageCountMax )){
		for( ReadCount = 0; ReadCount < 100; ){
			stsResult = Read_Message(&CANMsg,&CANTimeStamp);
			if (stsResult == PCAN_ERROR_OK) {
				// We show the received message
				//
				FilterFlag = 0;
				for( FilterCount = 0; FilterCount < 10; ++FilterCount ){
					if( pRxDataFilter->SoftSet[FilterCount] == 1
						&& pRxDataFilter->SoftMinValue[FilterCount] <= CANMsg.ID
						&& CANMsg.ID <= pRxDataFilter->SoftMaxValue[FilterCount] ){
						FilterFlag = 1;
					}
				}
				if( FilterFlag == 1 ){
					ProcessMessage(CANMsg, CANTimeStamp);
					MessageCount = MessageCount + 1;
					MessageCountNow = MessageCount;
					FilterFlag = 0;
					ReadCount = ReadCount + 1;
				}
			} else if (stsResult == PCAN_ERROR_QRCVEMPTY) {
				// Receive queue is empty
				ReadCount = 100;
			} else {
				// If an error occurred, an information message is included
				//
				// For Hardware Error Message Output
			}
			qApp->processEvents();
			if( MessageCountNow == RcvMessageCountMax ){
				ReadCount = 100;
			}
		}
		qt_str.setNum(MessageCountNow,10);
		ui.txtRcvFrameCount->setText(qt_str);
	} else {
		// Timer Stop
		ReadTimer->stop();

		// Recive Message File Write
		RxDataFileWrite(MessageCountNow);

		RcvMessageCountMax = 0;
		MessageCountNow = 0;

		ui.btnRxDataFind->setEnabled(true);
		ui.txtRxDataTime->setEnabled(true);
		ui.txtRxDataFile->setEnabled(true);
		ui.chbViewReport->setEnabled(true);
		ui.txtDisplayTime->setEnabled(true);
		ui.btnRxStartStop->setText("Read Message");

		pFcanView->statusBar_message("");

		pInformation->Information_set("");
		pInformation->Information_append("Message was successfully RECIVE");
	}

}
// timDisplay
void RxData::timDisplay()
{
	CanData CanDataVec;
	DWORD MessageCount = 0;
	DWORD lp;
	int i;
	QString qt_str;
	QString report_box;
	QString report_time;
	QString report_type;
	QString report_cob;
	QString report_id;
	QString report_len;
	QString report_data;

	MessageCount = pCanDataMng->num();

	if(( ui.btnRxStartStop->text() == "Read Message" )
		&& ( DisplayMessageCountNow == MessageCount )){
		// Timer Stop
		DisplayTimer->stop();
		ui.txtRcvFrameCount->setText(RcvCountMax_str);
	} else {
		if( DisplayMessageCountNow < MessageCount ){
			report_box = "";
			for( lp=0; lp<100; ){
				// Buffer Read
				pCanDataMng->get(DisplayMessageCountNow,CanDataVec);
				// Display Data
			    qt_str.sprintf("%8d", (DWORD)CanDataVec.mtime);
				report_time = qt_str;
				qt_str.sprintf("%03d |", (WORD)CanDataVec.utime);
				report_time = report_time + "." + qt_str;
				if( CanDataVec.type == 0 ){
					report_type = " STD  |";
					report_cob.sprintf("   %03X    |", CanDataVec.func);
					report_id.sprintf("   %03X    |", CanDataVec.id);
				} else if( CanDataVec.type == 1 ){
					report_type = " EXT  |";
					report_cob.sprintf(" %08X |", CanDataVec.func);
					report_id.sprintf(" %08X |", CanDataVec.id);
				} else {
					report_type = " Non  |";
					report_cob.sprintf(" %08X |", CanDataVec.func);
					report_id.sprintf(" %08X |", CanDataVec.id);
				}
				if( CanDataVec.len == 0x9 ){
					report_len = " 00  |";
					report_data = " RTR ";
				} else {
					report_len.sprintf(" %02d  |", CanDataVec.len);
					report_data = "";
					for( i=0; i<CanDataVec.len; i=i+1 ){
						qt_str.sprintf(" %02X", CanDataVec.data[i]);
						report_data = report_data + qt_str;
					}
				}
				// ViewReport
				DisplayMessageCountNow = DisplayMessageCountNow + 1;
				qApp->processEvents();
				if( DisplayMessageCountNow == MessageCount ){
					lp = 100;
					report_box = report_box + report_time + report_type + report_cob + report_id + report_len + report_data;
				} else {
//					lp = lp +1;
					report_box = report_box + report_time + report_type + report_cob + report_id + report_len + report_data + "\n";
				}
			}
			ui.txtRxData->append(report_box);
		}
	}

}

