#include "OControl_USB.h"
#include <iostream>
#include <cstring>

OceanOptics_lib::OceanOptics_lib()
{
	m_iSpectralmeterHandle = -100;
}

OceanOptics_lib::~OceanOptics_lib()
{

}

//使用头文件：#include "api/SeaBreezeWrapper.h"
int OceanOptics_lib::Initialize(bool bIsUSBMode, std::string ucPortNumber, std::string strDeviceName)
{
	int flag;
	int error;
	//char type[16];
	int device_count = 0;
	int i;

	for (i = 0; i < SEABREEZE_MAX_DEVICES; i++)
	{
		//        printf("\nOpening spectrometer %d.\n", i);
		flag = seabreeze_open_spectrometer(i, &error);
		//        printf("Open spectrometer result is (%d) [%s]\n", flag, get_error_string(error));
		if (0 == flag)
		{
			device_count++;
		}
		else
		{
			continue;
		}
		string sn = GetSerialNumber(i);

		if (strcmp(sn.c_str(), strDeviceName.c_str()) == 0)
		{
			m_iSpectralmeterHandle = i;
			//            printf("\nfind!!!!!!!!!!!!\n");
			break;
		}
		else
		{
			//            printf("\nClosing spectrometer %d.\n", i);
			flag = seabreeze_close_spectrometer(i, &error);
			//            printf("Close spectrometer result is (%d) [%s]\n", flag, get_error_string(error));
		}
	}

	if (m_iSpectralmeterHandle == -100)
	{
		//        printf("\nNo!!!!!!!!!!!!\n");
		return 1;
	}

	seabreeze_set_trigger_mode(m_iSpectralmeterHandle, &error, 0);


	long test = seabreeze_get_buffer_capacity_minimum(m_iSpectralmeterHandle, &error);
	seabreeze_set_buffer_capacity(m_iSpectralmeterHandle, &error, test);
	//seabreeze_set_trigger_mode(m_iSpectralmeterHandle, &error, 0);
	//seabreeze_set_trigger_mode(m_iSpectralmeterHandle, &error, 0);
	//    printf("seabreeze_set_trigger_mode: Result is [%s]\n", get_error_string(error));



		//设置初始积分时间
	long minimum_time;
	minimum_time = seabreeze_get_min_integration_time_microsec(m_iSpectralmeterHandle, &error);
	//printf("...Minimum is %ld microseconds, result is [%s]\n", minimum_time, get_error_string(error));
	bool ret = isSuccess((char*)get_error_string(error));
	if (!ret)
	{
		//        printf("\n-------------------没成功！！！！！！！！！！！！！！！！！！\n");
		return 1;
	}

	if (minimum_time < 0) {
		/* If there was an error, reset to a time that is supported widely. */
		minimum_time = 15000;
		return 1;
	}

	SetExposureTime(minimum_time / 1000);

	return 0;
}

//使用头文件：#include "api/SeaBreezeWrapper.h"
int OceanOptics_lib::Initialize()
{
	int flag;
	int error;
	//char type[16];
	int device_count = 0;
	int i;

	for (i = 0; i < SEABREEZE_MAX_DEVICES; i++)
	{
		printf("\nOpening spectrometer %d.\n", i);
		flag = seabreeze_open_spectrometer(i, &error);
		//printf("Open spectrometer result is (%d) [%s]\n", flag, get_error_string(error));
		if (0 == flag)
		{
			m_iSpectralmeterHandle = i;
			break;
		}
		else
		{
			continue;
		}
	}

	if (m_iSpectralmeterHandle == -100)
	{
		printf("\nNo!!!!!!!!!!!!\n");
		return 1;
	}

	seabreeze_set_trigger_mode(m_iSpectralmeterHandle, &error, 0);
	seabreeze_set_trigger_mode(m_iSpectralmeterHandle, &error, 0);
	seabreeze_set_trigger_mode(m_iSpectralmeterHandle, &error, 0);
	//    printf("seabreeze_set_trigger_mode: Result is [%s]\n", get_error_string(error));

		//设置初始积分时间
	long minimum_time;

	minimum_time = seabreeze_get_min_integration_time_microsec(m_iSpectralmeterHandle, &error);
	//printf("...Minimum is %ld microseconds, result is [%s]\n", minimum_time, get_error_string(error));
	bool ret = isSuccess((char*)get_error_string(error));
	if (!ret)
	{
		//        printf("\n-------------------没成功！！！！！！！！！！！！！！！！！！\n");
		return 1;
	}

	if (minimum_time < 0) {
		/* If there was an error, reset to a time that is supported widely. */
		minimum_time = 15000;
		return 1;
	}

	SetExposureTime(minimum_time / 1000);

	return 0;
}


//使用头文件：#include "api/seabreezeapi/SeaBreezeAPI.h"
//int OceanOptics_lib::Initialize(bool bIsUSBMode,ZZ_U8 ucPortNumber,std::string strDeviceName)
//{
//    int number_of_devices;
//    long *device_ids;
//    int i;
//    int flag;
//    int error = 0;
//    char nameBuffer[80];
//    char *serialNumber;
//
//
////    /* Give the driver a chance to initialize itself */
////    sbapi_initialize();
//
//    printf("Probing for devices...\n"); fflush(stdout);
//    sbapi_probe_devices();
//
//    printf("Getting device count...\n"); fflush(stdout);
//    number_of_devices = sbapi_get_number_of_device_ids();
//    std::cout<<"Device count is "<< number_of_devices <<std::endl;
//    if(0 == number_of_devices) {
//        return 0;
//    }
//
//    printf("Getting device IDs...\n");
//    device_ids = (long *)calloc(number_of_devices, sizeof(long));
//    number_of_devices = sbapi_get_device_ids(device_ids, number_of_devices);
//    printf("Got %d device ID%s.\n", number_of_devices, number_of_devices == 1 ? "" : "s"); fflush(stdout);
//
//
//    for(i = 0; i < number_of_devices; i++)
//    {
//        printf("%d: Device 0x%02lX:\n", i, device_ids[i]);
////        printf("\tGetting device type...\n");
//        flag = sbapi_get_device_type(device_ids[i], &error, nameBuffer, 79);
////        printf("\t\tResult is (%d) [%s]\n", flag, sbapi_get_error_string(error));
//        if(flag > 0) {
//            printf("\tDevice type: [%s]\n", nameBuffer);
//        }
//
//        serialNumber = GetSerialNumber(device_ids[i]);
//        serialNumber = GetSerialNumber(device_ids[i]);
//
//        printf("\tSerial number tc: [%s]\n", serialNumber);
//
////        /* Open the device */
////        printf("\tAttempting to open:\n");
////        flag = sbapi_open_device(device_ids[i], &error);
////        printf("\t\tResult is (%d) [%s]\n", flag, sbapi_get_error_string(error));
////
////        // jump to the next iteration if there was a problem
////        if(flag != 0) {
////            continue;
////        }
////
////        // log deviations
////        unsupportedFeatureCount=0;
////        testFailureCount=0;
////
////        /* Test the device */
////        for(test_index = 0; test_index < __test_function_count; test_index++) {
////            /* Invoke each of the test functions against this device */
////            __test_functions[test_index](device_ids[i], &unsupportedFeatureCount, &testFailureCount);
////        }
////
////        /* Close the device */
////        printf("\tAttempting to close:\n");
////        sbapi_close_device(device_ids[i], &error);
////        printf("\t\tResult is (%d) [%s]\n", flag, sbapi_get_error_string(error));
////        printf("%d: Device 0x%02lX: \n\tNumber of unsupported features = %d\n\tNumber of test failures = %d\n", i, device_ids[i], unsupportedFeatureCount, testFailureCount);
//    }
//
//    flag = sbapi_get_device_type(device_ids[i], &error, nameBuffer, 79);
//
//    return 1;
//}

//关闭设备
void OceanOptics_lib::Close()
{
	int flag;
	int error;

	flag = seabreeze_close_spectrometer(m_iSpectralmeterHandle, &error);
	//    printf("Close spectrometer result is (%d) [%s]\n", flag, get_error_string(error));
}

//单次数据采集
int OceanOptics_lib::SingleShot(DataFrame &dfData)
{
	if (m_iSpectralmeterHandle == -100)
	{
		printf("\nNo!!!!!!!!!!!!\n");
		return 1;
	}

	int error;
	int flag;
	int spec_length;
	double *spectrum = 0;
	bool ret;

	//    printf("\n\nGetting formatted spectrum length.\n");
	spec_length = seabreeze_get_formatted_spectrum_length(m_iSpectralmeterHandle, &error);
	//printf("Get formatted spectrum_length result is (%d) [%s]\n", spec_length, get_error_string(error));
	ret = isSuccess((char*)get_error_string(error));
	if (!ret)
	{
		return 1;
	}

	if (spec_length > 0)
	{
		spectrum = (double *)calloc((size_t)spec_length, sizeof(double));



		seabreeze_clear_buffer(m_iSpectralmeterHandle, &error);




		printf("\nGetting a formatted spectrum.\n");
		flag = seabreeze_get_formatted_spectrum(m_iSpectralmeterHandle, &error, spectrum, spec_length);
		printf("\nGetting a formatted spectrum------------------------------.\n");
		//        printf("Get formatted spectrum result is (%d) [%s]\n", flag, get_error_string(error));
		//        printf("\tPixel value 20 is %1.2f\n", spectrum[20]);
		ret = isSuccess((char*)get_error_string(error));
		if (!ret)
		{
			return 1;
		}

		for (int tmp = 0; tmp < spec_length; tmp++)
		{
			dfData.lData[tmp] = spectrum[tmp];
		}

		int exposureTimeInMS;
		GetExposureTime(exposureTimeInMS);
		dfData.usExposureTimeInMS = exposureTimeInMS;

		float temperature;
		GetDeviceTemperature(temperature);
		dfData.fTemperature = temperature;

		free(spectrum);
	}

	return 0;
}

//设置曝光时间
int OceanOptics_lib::SetExposureTime(int iExposureTimeInMS)
{
	if (m_iSpectralmeterHandle == -100)
	{
		printf("\nNo!!!!!!!!!!!!\n");
		return 1;
	}

	int error;

	seabreeze_set_integration_time_microsec(m_iSpectralmeterHandle, &error, iExposureTimeInMS * 1000);
	printf("Set integration time result is [%s]\n", get_error_string(error));
	bool ret = isSuccess((char*)get_error_string(error));
	if (!ret)
	{
		return 1;
	}

	m_iExposureTime = iExposureTimeInMS;



	//    //----------------------------------------------------------------------------------------------------------------
	//    int error;
	//    long *spectrometer_ids;
	//    int number_of_spectrometers;
	//
	//    number_of_spectrometers = sbapi_get_number_of_spectrometer_features(m_iSpectralmeterHandle, &error);
	//    printf("\t\t\tResult is %d [%s]\n", number_of_spectrometers, sbapi_get_error_string(error));
	//    spectrometer_ids = (long *)calloc(number_of_spectrometers, sizeof(long));
	//    number_of_spectrometers = sbapi_get_spectrometer_features(m_iSpectralmeterHandle, &error, spectrometer_ids, number_of_spectrometers);
	//    printf("\t\t\tResult is %d [%s]\n", number_of_spectrometers, sbapi_get_error_string(error));
	//
	//    sbapi_spectrometer_set_integration_time_micros(m_iSpectralmeterHandle, spectrometer_ids[0], &error, iExposureTimeInMS*1000);
	//    printf("\t\t\t\tResult is [%s]\n", sbapi_get_error_string(error));

	return 0;
}

//获取曝光时间设置
int OceanOptics_lib::GetExposureTime(int &iExposureTimeInMS)
{
	if (m_iSpectralmeterHandle == -100)
	{
		printf("\nNo!!!!!!!!!!!!\n");
		return 1;
	}

	iExposureTimeInMS = m_iExposureTime;

	return 0;
}

//设置目标温度
int OceanOptics_lib::SetDeviceTemperature(float fTemperature)
{
	bool ret;

	if (m_iSpectralmeterHandle == -100)
	{
		printf("\nNo!!!!!!!!!!!!\n");
		return 1;
	}

	int error;

	//    printf("\nSetting TEC temperature to -5C\n");
	seabreeze_set_tec_temperature(m_iSpectralmeterHandle, &error, fTemperature);
	//    printf("Set tec temperature result is [%s]\n", get_error_string(error));
	ret = isSuccess((char*)get_error_string(error));
	if (!ret)
	{
		return 1;
	}


	//    printf("\nSetting TEC enable to true\n");
	seabreeze_set_tec_enable(m_iSpectralmeterHandle, &error, 1);
	//    printf("Set tec enable result is [%s]\n", get_error_string(error));
	ret = isSuccess((char*)get_error_string(error));
	if (!ret)
	{
		return 1;
	}

	return 0;
}

//获取温度设置
int OceanOptics_lib::GetDeviceTemperature(float &fTemperature)
{
	if (m_iSpectralmeterHandle == -100)
	{
		printf("\nNo!!!!!!!!!!!!\n");
		return 1;
	}

	double temp;
	int error;

	//    usleep(1000000);
	//    printf("\nGetting TEC temperature\n");
	temp = seabreeze_read_tec_temperature(m_iSpectralmeterHandle, &error);
	//    printf("Read tec temperature result is %1.2f C [%s]\n", temp, get_error_string(error));
	bool ret = isSuccess((char*)get_error_string(error));
	if (!ret)
	{
		return 1;
	}

	fTemperature = temp;

	return 0;
}

//获取设备信息
int OceanOptics_lib::GetDeviceInfo(DeviceInfo &Info)
{
	if (m_iSpectralmeterHandle == -100)
	{
		printf("\nNo!!!!!!!!!!!!\n");
		return 1;
	}

	string deviceType = GetDeviceType(m_iSpectralmeterHandle);
	string SN = GetSerialNumber(m_iSpectralmeterHandle);

	Info.strPN = deviceType;
	Info.strSN = SN;

	return 0;
}

//获取设备特征数据
int OceanOptics_lib::GetDeviceAttribute(DeviceAttribute &Attr)
{
	if (m_iSpectralmeterHandle == -100)
	{
		printf("\nNo!!!!!!!!!!!!\n");
		return 1;
	}

	int error;
	int flag;
	int spec_length;
	double *wls = 0;

	//    printf("\n\nGetting formatted spectrum length.\n");
	spec_length = seabreeze_get_formatted_spectrum_length(m_iSpectralmeterHandle, &error);
	//    printf("Get formatted spectrum length result is (%d) [%s]\n", spec_length, get_error_string(error));
	bool ret = isSuccess((char*)get_error_string(error));
	if (!ret)
	{
		return 1;
	}

	Attr.iPixels = spec_length;

	long minimum_time;
	minimum_time = seabreeze_get_min_integration_time_microsec(m_iSpectralmeterHandle, &error);
	Attr.iMinIntegrationTimeInMS = minimum_time;
	Attr.iMaxIntegrationTimeInMS = 60000;

	if (spec_length > 0) {
		wls = (double *)calloc((size_t)spec_length, sizeof(double));

		//        printf("\nGetting wavelengths.\n");
		flag = seabreeze_get_wavelengths(m_iSpectralmeterHandle, &error, wls, spec_length);
		//        printf("Get wavelengths result is (%d) [%s]\n", flag, get_error_string(error));
		//        printf("\tPixel 20 is wavelength %1.2f nm\n", wls[20]);
		bool ret = isSuccess((char*)get_error_string(error));
		if (!ret)
		{
			return 1;
		}

		for (int tmp = 0; tmp < spec_length; tmp++)
		{
			Attr.fWaveLengthInNM[tmp] = wls[tmp];
		}

		free(wls);
	}

	return 0;
}

bool OceanOptics_lib::isSuccess(char* resultStr)
{
	if (strstr(resultStr, "Success") == NULL)//在a中查找b，如果不存在，
	{
		//cout << "not found\n";//输出结果。
		return false;
	}
	else//否则存在。
	{
		//cout <<"found\n"; //输出结果。
		return true;
	}
}

const char* OceanOptics_lib::get_error_string(int error)
{
	static char buffer[32];
	seabreeze_get_error_string(error, buffer, sizeof(buffer));
	return buffer;
}

string OceanOptics_lib::GetDeviceType(int index)
{
	char type[16];
	int error;

	seabreeze_get_model(index, &error, type, sizeof(type));
	//    printf("...Result is (%s) [%s]\n", type, get_error_string(error));
	bool ret = isSuccess((char*)get_error_string(error));
	if (!ret)
	{
		return "";
	}

	type[15] = '\0';

	string deviceType = type;

	return deviceType;
}

string OceanOptics_lib::GetSerialNumber(int index)
{
	static char serial_number[32];//如果不加static，此变量会定义在stack区，函数返回后，就无用了
	int flag;
	int error;

	//    printf("\n\nGetting serial number.\n");
	flag = seabreeze_get_serial_number(index, &error, serial_number, 32);
	//    printf("Get serial number result is (%d) [%s]\n", flag, get_error_string(error));
	bool ret = isSuccess((char*)get_error_string(error));
	if (!ret)
	{
		return "";
	}

	serial_number[31] = '\0';
	if (flag > 0) {
		printf("\tSerial number: [%s]\n", serial_number);
	}

	string sn = serial_number;

	return sn;
}
