#include "Header_Files/oceanOpticsFiberImager.h"

OceanOpticsFiberImager::OceanOpticsFiberImager(double * nonlinearityCoeffs, int numberOfCoeffs)
{
	m_FiberSpectrometer = NULL;

    m_nonlinearityCoeffs = nonlinearityCoeffs;
    m_iNumberOfNonlinearityCoeffs = numberOfCoeffs;
}

OceanOpticsFiberImager::~OceanOpticsFiberImager()
{

}

void OceanOpticsFiberImager::connectFiberSpectrometer(QString& SN, QString& pixelCount, QString& wavelengthInfo)
{
	using namespace std;

	m_FiberSpectrometer = new OceanOptics_lib();

	m_FiberSpectrometer->Initialize();

    getDeviceInfo(m_deviceInfo);
//	m_FiberSpectrometer->GetDeviceInfo(m_deviceInfo);

    getDeviceAttribute(m_deviceAttribute);
//	m_FiberSpectrometer->GetDeviceAttribute(m_deviceAttribute);

	SN = QString::fromStdString(m_deviceInfo.strSN);
	pixelCount = QString::number(m_deviceAttribute.iPixels);
	wavelengthInfo = QString::number(m_deviceAttribute.fWaveLengthInNM[0]) + "--" + QString::number(m_deviceAttribute.fWaveLengthInNM[m_deviceAttribute.iPixels - 1]);

	m_FiberSpectrometer->SetDeviceTemperature(-10);


	//设置dn值的最大值（和位深相关）
	string qepro = "QEP";
	string flame = "FLMS";
	if (m_deviceInfo.strSN.find(qepro) != string::npos)
	{
		m_MaxValueOfFiberSpectrometer = 200000;
	}
	else if (m_deviceInfo.strSN.find(flame) != string::npos)
	{
		m_MaxValueOfFiberSpectrometer = 65535;
	}
	else//没有找到匹配的仪器来设置   dn值的最大值
	{

	}
}

void OceanOpticsFiberImager::disconnectFiberSpectrometer()
{
	m_FiberSpectrometer->Close();
}

void OceanOpticsFiberImager::getDeviceAttribute(DeviceAttribute& deviceAttribute)
{
	m_FiberSpectrometer->GetDeviceAttribute(deviceAttribute);
}

void OceanOpticsFiberImager::getDeviceInfo(DeviceInfo& deviceInfo)
{
	m_FiberSpectrometer->GetDeviceInfo(deviceInfo);
}

void OceanOpticsFiberImager::setExposureTime(int iExposureTimeInMS)
{
	m_FiberSpectrometer->SetExposureTime(iExposureTimeInMS);
}

void OceanOpticsFiberImager::getExposureTime(int &iExposureTimeInMS)
{
	m_FiberSpectrometer->GetExposureTime(iExposureTimeInMS);
}

void OceanOpticsFiberImager::getDeviceTemperature(float &fTemperature)
{
	m_FiberSpectrometer->GetDeviceTemperature(fTemperature);
}

void OceanOpticsFiberImager::singleShot(DataFrame &dfData)
{
	m_FiberSpectrometer->SingleShot(dfData);

    if(m_iNumberOfNonlinearityCoeffs==0)//如果非线性校正参数为0个，那么就不做非线性校正
    {
        return;
    }

    //做非线性校正
    for (int i = 0; i < m_deviceAttribute.iPixels; i++)
    {
        dfData.lData[i] = dfData.lData[i] / (m_nonlinearityCoeffs[0]
                                   + m_nonlinearityCoeffs[1] * dfData.lData[i]
                                   + m_nonlinearityCoeffs[2] * pow(dfData.lData[i], 2)
                                   + m_nonlinearityCoeffs[3] * pow(dfData.lData[i], 3)
                                   + m_nonlinearityCoeffs[4] * pow(dfData.lData[i], 4)
                                   + m_nonlinearityCoeffs[5] * pow(dfData.lData[i], 5)
                                   + m_nonlinearityCoeffs[6] * pow(dfData.lData[i], 6)
                                   + m_nonlinearityCoeffs[7] * pow(dfData.lData[i], 7)
        );
    }
}

void OceanOpticsFiberImager::getNonlinearityCoeffs(coeffsFrame &coeffs)
{
    printf("This is OceanOpticsFiberImager.\n");

    m_FiberSpectrometer->test_nonlinearity_coeffs_feature();
}

void OceanOpticsFiberImager::recordDark(QString path)
{
	//获取设备信息
	DeviceAttribute attribute;
	DeviceInfo deviceInfo;
	getDeviceAttribute(attribute);
	getDeviceInfo(deviceInfo);

	//采集暗帧
	singleShot(m_DarkData);

//    //输出到csv
//	QDateTime curDateTime = QDateTime::currentDateTime();
//	QString currentTime = curDateTime.toString("yyyy_MM_dd_hh_mm_ss");
//
//	QString fileName = path + "/" + currentTime + "_" + QString::fromStdString(deviceInfo.strSN) + "_darkSpectral.csv";
//	std::ofstream outfile(fileName.toStdString().c_str());
//
//	for (int i = 0; i < attribute.iPixels; i++)
//	{
//        if (i==0)
//        {
//            outfile << m_DarkData.usExposureTimeInMS << std::endl;//
//        }
//		outfile << attribute.fWaveLengthInNM[i] << "," << m_DarkData.lData[i] << std::endl;
//	}
//
//	outfile.close();
}

void OceanOpticsFiberImager::recordTarget(int recordTimes, QString path)
{
	//获取设备信息
	DeviceAttribute attribute;
	DeviceInfo deviceInfo;
	getDeviceAttribute(attribute);
	getDeviceInfo(deviceInfo);

	
	DataFrame integratingSphereData_tmp;

	for (int i = 0; i < recordTimes; i++)
	{
		singleShot(integratingSphereData_tmp);

		if (i == 0)//将integratingSphereData_tmp中的曝光时间、温度等信息传给m_IntegratingSphereData
		{
			m_IntegratingSphereData = integratingSphereData_tmp;
		}
		else
		{
			for (int i = 0; i < attribute.iPixels; i++)
			{
				m_IntegratingSphereData.lData[i] += integratingSphereData_tmp.lData[i];
			}
		}
		
	}

	for (int i = 0; i < attribute.iPixels; i++)
	{
		m_IntegratingSphereData.lData[i] = m_IntegratingSphereData.lData[i] / recordTimes;
	}


//    //输出到csv
//	QDateTime curDateTime = QDateTime::currentDateTime();
//	QString currentTime = curDateTime.toString("yyyy_MM_dd_hh_mm_ss");
//
//	QString fileName = path + "/" + currentTime + "_" + QString::fromStdString(deviceInfo.strSN) + "_integratingSphereSpectral.csv";
//	std::ofstream outfile(fileName.toStdString().c_str());
//
//	for (int i = 0; i < attribute.iPixels; i++)//
//	{
//        if (i==0)
//        {
//            outfile << m_IntegratingSphereData.usExposureTimeInMS << std::endl;
//        }
//		outfile << attribute.fWaveLengthInNM[i] << "," << m_IntegratingSphereData.lData[i] << std::endl;
//	}
//
//	outfile.close();
}

void OceanOpticsFiberImager::autoExpose()
{
	DeviceAttribute attribute;
	getDeviceAttribute(attribute);

	int iterations = 0;//记录自动曝光已经迭代的次数
	int maxIterations = 10;//允许最大的迭代次数

	ZZ_U32 thresholdValue = m_MaxValueOfFiberSpectrometer * 0.8;//最佳线性区间为80%
	ZZ_U16 range = 10000;

	//设置初始曝光时间
	int exposureTimeInMS = 200;
	setExposureTime(exposureTimeInMS);
	emit sendExposureTimeSignal(exposureTimeInMS);

	DataFrame integratingSphereData_tmp;
	while (true)
	{
		if (iterations > maxIterations)//是否超过允许的最大迭代次数
		{
			break;
		}

		singleShot(integratingSphereData_tmp);
        ZZ_S32 maxValue = GetMaxValue(integratingSphereData_tmp.lData, attribute.iPixels);

		if (maxValue < thresholdValue && maxValue < (thresholdValue - range))//曝光时间过小
		{
			double scale = 1 + ((double)(thresholdValue - maxValue) / (double)thresholdValue);

			int exposureTime;
			m_FiberSpectrometer->GetExposureTime(exposureTime);
			m_FiberSpectrometer->SetExposureTime(exposureTime * scale);

			emit sendExposureTimeSignal(exposureTime);

            ZZ_S32 m = GetMaxValue(integratingSphereData_tmp.lData, attribute.iPixels);

			std::cout << "自动曝光-----------" << "最大值为" << m << std::endl;
		}
		else if (maxValue > thresholdValue && maxValue > (thresholdValue + range))//曝光时间过大
		{
			double scale = 1 - ((double)(maxValue - thresholdValue) / (double)thresholdValue);

			int exposureTime;
			m_FiberSpectrometer->GetExposureTime(exposureTime);
			m_FiberSpectrometer->SetExposureTime(exposureTime * scale);

			emit sendExposureTimeSignal(exposureTime);

            ZZ_S32 m = GetMaxValue(integratingSphereData_tmp.lData, attribute.iPixels);

			std::cout << "自动曝光-----------" << "最大值为" << m << std::endl;
		}
		else//找到最佳曝光时间，跳出while循环
		{
			break;
		}

		iterations++;
	}

}

ZZ_S32 OceanOpticsFiberImager::GetMaxValue(ZZ_S32 * dark, int number)
{
    ZZ_S32 max = 0;
	for (size_t i = 0; i < number; i++)
	{
		if (dark[i] > max)
		{
			max = dark[i];
		}
	}
	//std::cout << "本帧最大值为" << max << std::endl;
	return max;
}