#include "MainGrabber.h"
#include "ZZ_Math_HDRONLY.h"
CMainGrabber::CMainGrabber(QObject* parent /*= nullptr*/)
{
	m_pctrlFS = NULL;
	m_pctrlGPS = NULL;
	m_dfpDataSaver = NULL;
	m_iFlagIsCapture = 0;

	connect(this, &CMainGrabber::Signal_InitSelf, this, &CMainGrabber::Initialize_Self);
}

CMainGrabber::~CMainGrabber()
{

}

void CMainGrabber::SetRunParams(OneFSContext struFSRunParams)
{
	m_struFSRunParams = struFSRunParams;
}

int CMainGrabber::SetContext(BD357Controller &pctrlGPS, DataFileProcessor &dfpDataSaver)
{
	if (&pctrlGPS == NULL)
	{
		//qDebug() << "GPS Not Initialized";
		printf("GPS Not Initialized");
		return 1;
	}

	m_pctrlGPS = &pctrlGPS;
	m_dfpDataSaver = &dfpDataSaver;

	return 0;
}

int CMainGrabber::Initialize()
{
	emit Signal_InitSelf();
	return 0;
}

int CMainGrabber::StartGrab()
{
	system("gpio write 5 1");
	m_dfpDataSaver->GenerateFilePath();
	m_pctrlFS->PerformAutoExposure();
	DataFrame dfTemp;
	m_iFlagIsCapture = 1;

	while (m_iFlagIsCapture)
	{
		QTime qtTime;
		qtTime.start();

		////////////
		system("gpio write 5 0");
		qDebug() << "system IO";
		m_pctrlFS->SingleShot(dfTemp);
		qDebug() << "SingleShot";
		RemoveBackground(dfTemp);
		CheckExposureTime(dfTemp);
		m_dfpDataSaver->WriteData(dfTemp);
		system("gpio write 5 1");
		////////////
		
		//int iMillisec = qtTime.elapsed();
 		int iSleep =m_struFSRunParams.dMinSamplingInterval - qtTime.elapsed();
 		if (iSleep>0)
 		{
 			Delay_MSec(iSleep);
 		}
 		qDebug() << "Delay_MSec"<< iSleep;
	}

	return 0;
}

int CMainGrabber::Initialize_Self()
{
	InitializeWorkers();
	SetupMsgPipelines();
	if (m_struFSRunParams.ucDeviceModel== DeviceModel::FLAME)
	{
		//do nothing
	}
	else
	{
		LoadDCT();
	}

	emit Signal_InitFinished();
	return 0;
}  

void CMainGrabber::Delay_MSec(ZZ_U16 usMS)
{
	QEventLoop qeLoop;
	QTimer::singleShot(usMS, &qeLoop, SLOT(quit()));
	qeLoop.exec();
}

int CMainGrabber::InitializeWorkers()
{
	if (m_pctrlFS == NULL)
	{
		m_pctrlFS = new CAbsFSController;
	}
	else
	{
		//???
	}
	m_pctrlFS->SetContext(m_struFSRunParams);

	m_pctrlFS->Initialize();
	while (!m_pctrlFS->m_iFlagInit)
	{
		Delay_MSec(1000);
	}
	m_pctrlFS->GetDeviceAttr(m_struDeviceAttr);
	m_dfpDataSaver->WriteWavelengthInfo(m_struDeviceAttr.fWaveLengthInNM, m_struDeviceAttr.iPixels);

	//////////////////////////////////////////////////////////////////////////20230713
	if (m_struFSRunParams.dMinSamplingInterval < m_pctrlFS->m_struDeviceAttr.iMaxIntegrationTimeInMS)
	{
		m_pctrlFS->m_struDeviceAttr.iMaxIntegrationTimeInMS = m_struFSRunParams.dMinSamplingInterval * 2;
	}
	return 0;
}

int CMainGrabber::SetupMsgPipelines()
{
	bool bRes = connect(m_pctrlGPS,&BD357Controller::Signal_StartCapture, this, &CMainGrabber::StartGrab);
	
	return 0;
}

int CMainGrabber::LoadDCT()
{
	m_vecDataFrame.clear();

	m_DCTable.SetRunParams(m_struFSRunParams);
	m_DCTable.Initialize_Part();
	m_DCTable.LoadTable();
	m_DCTable.GetDCTable(m_vecDataFrame);

	return 0;
}

int CMainGrabber::CheckExposureTime(DataFrame dfTemp)
{
	using namespace ZZ_MATH;
	double dExpTimeMS;
	int    idExpTimeMS;

	m_pctrlFS->GetExposureTime(idExpTimeMS);

	qDebug() << "GetExposureTime" << idExpTimeMS;

	dExpTimeMS = idExpTimeMS;

	HeapSort(dfTemp.lData, m_struDeviceAttr.iPixels);

	double dSum = 0; 
	int iCount = m_struDeviceAttr.iPixels / 200;
	for (int i = 0; i < iCount; i++)
	{
		dSum += dfTemp.lData[i];
	}
	double dTemp = dSum / iCount;

	if (dTemp >= m_struFSRunParams.lDepth * 0.99)
	{
		dExpTimeMS = dExpTimeMS /2;
	}

	else if (m_struFSRunParams.lDepth*m_struFSRunParams.fMaxFactor >= dTemp && dTemp >= m_struFSRunParams.lDepth * m_struFSRunParams.fMinFactor)
	{
		qDebug() << "SetExposureTime" << dExpTimeMS;
		return 0;
	}

	else
	{
		double dFactor;
		dFactor = dTemp / (m_struFSRunParams.lDepth * m_struFSRunParams.fMaxFactor);
		dExpTimeMS = (float)(dExpTimeMS / dFactor);
	}

	if ((dExpTimeMS <= m_struDeviceAttr.iMinIntegrationTimeInMS)|| (dExpTimeMS > m_struDeviceAttr.iMaxIntegrationTimeInMS - 1))
	{
		if ((dExpTimeMS <= m_struDeviceAttr.iMinIntegrationTimeInMS))
		{
			dExpTimeMS = m_struDeviceAttr.iMinIntegrationTimeInMS;
			qDebug() << "SetExposureTime out of range-Min";
			return 1;
		}
		if ((dExpTimeMS > m_struDeviceAttr.iMaxIntegrationTimeInMS - 1))
		{
			dExpTimeMS = m_struDeviceAttr.iMaxIntegrationTimeInMS - 1;
			qDebug() << "SetExposureTime out of range-Max";
			return 2;
		}
	}
	


	m_pctrlFS->SetExposureTime((int)dExpTimeMS);

	qDebug() << "SetExposureTime" << dExpTimeMS;
	return 0;
}

int CMainGrabber::RemoveBackground(DataFrame& dfTemp)
{
	//海洋光学扣暗电流：前几个像素作为暗电流
	if (m_struFSRunParams.ucDeviceModel==DeviceModel::FLAME)
	{
		double dBackground = 0;
		for (int i=0;i< m_pctrlFS->m_vecDarkPixleIndices.size();i++)
		{
			dBackground += dfTemp.lData[m_pctrlFS->m_vecDarkPixleIndices[i]];
		}
		dBackground = dBackground / m_pctrlFS->m_vecDarkPixleIndices.size();

		for (int i = 0; i < m_struDeviceAttr.iPixels; i++)
		{
			dfTemp.lData[i] = dfTemp.lData[i] - dBackground;
		}

		qDebug() << "FLAME Real Time Background" << dBackground;
	}
	else
	{
		int iA = dfTemp.usExposureTimeInMS / 10;
		int iB = dfTemp.usExposureTimeInMS % 10;

		qDebug() << "iA" << iA;
		qDebug() << "iB" << iB;

		if (iA == 0)
		{
			m_dfBackground = m_vecDataFrame[iB-1];
		}
		else
		{
			if (iA > 100)
			{
				m_dfBackground = m_vecDataFrame[m_vecDataFrame.size() - 1];
			}
			else if (iA <= 9 && iA >= 1)
			{
				m_dfBackground = m_vecDataFrame[8 + iA];
			}
			else
			{
				int iAA = dfTemp.usExposureTimeInMS / 100;
				int iBB = dfTemp.usExposureTimeInMS % 100;

				DataFrame dfTempX1, dfTempX2;
				dfTempX1 = m_vecDataFrame[17 + iAA];
				dfTempX2 = m_vecDataFrame[18 + iAA];

				for (int i = 0; i < m_struDeviceAttr.iPixels; i++)
				{
					m_dfBackground.lData[i] = dfTempX1.lData[i] + (dfTempX2.lData[i] - dfTempX1.lData[i]) * (double)iBB / (double)100;
				}
			}
		}

		for (int i = 0; i < m_struDeviceAttr.iPixels; i++)
		{
			dfTemp.lData[i] = dfTemp.lData[i] - m_dfBackground.lData[i];
		}
		return 0;
	}
	
}
