#include "stdafx.h"
#include "Cam_Lib.h"
#include <windows.h>

extern Cameras* cams;



/* Constructors */
Camera::Camera(){
	freq = 1;
	opened = FALSE;
	stream_ready = FALSE;
	img_process.disp_Options[0]=false;
	img_process.disp_Options[1]=false;
	img_process.disp_Options[2]=false;
	img_process.disp_Options[3]=false;
}

/* Methods*/
int Camera::Camera_getinfo(int j){
	int in = 0;
	if(j == 1){
		if((in+=PvCameraOpen(get_Camera_info()->UniqueId,ePvAccessMaster,&handle))==ePvErrSuccess){
			in+= PvAttrUint32Get(handle,"Width",&roi.roi_width);
			in+= PvAttrUint32Get(handle,"Height",&roi.roi_height);
			in+= PvAttrUint32Get(handle,"RegionX",&roi.roi_regX);
			in+= PvAttrUint32Get(handle,"RegionY",&roi.roi_regY);
			in+= PvAttrUint32Get(handle,"ExposureValue",&exposure_time);
			in+= PvAttrUint32Get(handle,"GainValue",&gain_value);
			in+= PvAttrUint32Get(handle,"BinningX",&roi.binningX);
			in+= PvAttrUint32Get(handle,"BinningY",&roi.binningY);
			in+= PvAttrFloat32Get(handle,"FrameRate",&cmode.framerate);
			in+= PvAttrUint32Get(handle,"AcquisitionFrameCount",&cmode.framect);
			exposure_mode = pvGetExposureMode();
			gain_mode = pvGetGainMode();
			exposure_mode = pvGetExposureMode();
			gain_mode = pvGetGainMode();
			pvGetAcqMode();
			pvGetTrigMode();
			PvCameraClose(handle);
		}
	}
	handle = NULL;
	return in;
}
UINT32 Camera::Camera_getExpo(void){
	PvAttrUint32Get(handle,"ExposureValue",&exposure_time);
	return exposure_time;
}
UINT32 Camera::Camera_getGain(void){
	PvAttrUint32Get(handle,"GainValue",&gain_value);
	return gain_value;
}

int Camera::set_handle(tPvHandle newhandle){
	handle=newhandle;
	return 1;
}

int Camera::Camera_Start(){
	int stat;
	if((stat = PvCameraOpen(get_Camera_info()->UniqueId,ePvAccessMaster,&handle))==ePvErrSuccess){
		opened = TRUE;
		if((stat =PvAttrEnumSet(handle,"FrameStartTriggerMode",cmode.frametrigarr))==ePvErrSuccess)
			if((stat =PvAttrEnumSet(handle,"AcquisitionMode",cmode.acqarr))==ePvErrSuccess)
				return 1;
	}
	return 0;
}
int Camera::set_resolution(){
	int check=ePvErrSuccess;
	check  = PvAttrUint32Set(handle ,"Width",roi.roi_width);
	check += PvAttrUint32Set(handle,"Height",roi.roi_height);	
	check += PvAttrUint32Set(handle,"RegionX",roi.roi_regX);
	check += PvAttrUint32Set(handle,"RegionY",roi.roi_regY);
	check += PvAttrUint32Set(handle,"BinningX",roi.binningX);
	check += PvAttrUint32Set(handle,"BinningY",roi.binningY);
	check += PvAttrUint32Get(handle, "TotalBytesPerFrame",&bytesPerFrame);
	check += PvAttrUint32Get(handle, "TotalBytesPerFrame",&img_frame.ImageBufferSize);
	img_frame.ImageBuffer = new char[bytesPerFrame];
	img_frame.AncillaryBuffer = 0;
	img_frame.AncillaryBufferSize = 0;
	if(check!=0)
		return 0;
	return 1;
}
int Camera::set_cameraMode(){
	int check = 0;

	check+= PvAttrFloat32Set(handle, "FrameRate",cmode.framerate);
	check+= PvAttrUint32Set(handle, "AcquisitionFrameCount",cmode.framect);
	check+= PvAttrEnumSet(handle, "FrameStartTriggerMode", cmode.frametrigarr);
	check+= PvAttrEnumSet(handle, "AcquisitionMode", cmode.acqarr);
	return check;
}
int Camera::set_ready(BOOL newval){
	stream_ready = newval;
	return 1;
}
int Camera::Camera_Capture(){
	tPvErr stat;
	prepare_smallimage(this, cams);

	if (((stat=PvCaptureStart(handle))==ePvErrSuccess)){ //start driver stream
		if ((stat=PvCommandRun(handle,"AcquisitionStart"))==ePvErrSuccess){
			stream_ready = true;
			roiEnbl = true;
			return 1;
		}
	}

	return stat;
}
int Camera::Camera_stream(){
	if(stream_ready == TRUE){
		stream_ready = false;			//No more frames will be queued untill this one is retireved
		int stat;
		img_frame.Context[0]= this;		//Will be used in callback function
		tPvFrameCallback CB = &Frame_Callback;
		if(img_process.disp_Options[IMG_WINDOW==TRUE]){
			namedWindow(camera_info.SerialNumber, CV_WINDOW_AUTOSIZE);
			img_process.disp_Options[WINDOW_READY]=TRUE;
		}
		if((stat=PvCaptureQueueFrame(handle,&img_frame, CB))==ePvErrSuccess){
			if((strcmp(cmode.acqarr,"SingleFrame")==0)){
				stat=PvCommandRun(handle,"AcquisitionStart");
				
			}
			else if((strcmp(cmode.acqarr,"MultiFrame")==0)){
				stat=PvCommandRun(handle,"AcquisitionStart");
				}
				return 1;
			
			OutputDebugString(L"PvCaptureQueueFrame failed");
		}
	}
		return 0;
	}

	int Camera::set_Exposition(UINT32 expo){
		if(PvAttrUint32Set(handle ,"ExposureValue",expo)!=ePvErrSuccess)
			return 0;
		exposure_time = expo;
		return 1;
	}

	int Camera::set_Gain(UINT32 gain){
		if(PvAttrUint32Set(handle ,"GainValue",gain)!=ePvErrSuccess)
			return 0;
		gain_value = gain;
		return 1;
	}
	int Camera::set_Exposition_Mode(UINT32 expo){
		switch(expo){
		case MANUAL:
			if(PvAttrEnumSet(handle ,"ExposureMode","Manual")!=ePvErrSuccess)
				return 0;
			break;
		case AUTO_CONTINOUOUS:
			if(PvAttrEnumSet(handle ,"ExposureMode","Auto")!=ePvErrSuccess)
				return 0;
			break;
		case AUTO_ONCE:
			if(PvAttrEnumSet(handle ,"ExposureMode","AutoOnce")!=ePvErrSuccess)
				return 0;
			break;
		}

		exposure_mode = expo;
		return 1;
	}
	int Camera::set_Gain_Mode(UINT32 gain){
		switch(gain){
		case MANUAL:
			if(PvAttrEnumSet(handle ,"GainMode","Manual")!=ePvErrSuccess)
				return 0;
			break;
		case AUTO_CONTINOUOUS:
			if(PvAttrEnumSet(handle ,"GainMode","Auto")!=ePvErrSuccess)
				return 0;
			break;
		case AUTO_ONCE:
			if(PvAttrEnumSet(handle ,"GainMode","AutoOnce")!=ePvErrSuccess)
				return 0;
			break;
		}
		gain_mode = gain;
		return 1;
	}
	int Camera::set_cameraInfo(tPvCameraInfoEx found_camera){
		camera_info= found_camera;
		return 1;
	}
	int Camera::Camera_close(){
		if(PvCameraClose(handle)==ePvErrSuccess){
			handle = NULL;
			return 1;
		}
		return 0;

	}
	int Camera::Camera_stopcapt(){
		if(PvCaptureEnd(handle)==ePvErrSuccess){
			frameno = 0;
			stream_ready = false;
			roiEnbl = false;
			return 1;
		}
		return 0;
	}
	int Camera::pvGetExposureMode(){
		//	int enumed;
		char mode[10]={'\0'};
		unsigned long length;
		if(PvAttrEnumGet(handle, "ExposureMode", mode,sizeof(mode),&length)!=ePvErrSuccess)
			return 666;
		switch(length){
		case 4:
			return AUTO_CONTINOUOUS;
		case 6:
			return MANUAL;
		case 8:
			return AUTO_ONCE;
		}	
		return 0;
	}
	int Camera::pvGetAcqMode(void){
		//	char mode[10];
		unsigned long length;
		if(PvAttrEnumGet(handle, "AcquisitionMode", cmode.acqarr,sizeof(cmode.acqarr),&length)!=ePvErrSuccess)
			return 666;
		switch(length){
		case 10:
			return CONTINUOUS;
		case 11:
			return SINGLEFRAME;
		}	
		return 0;
	}
	int Camera::pvGetTrigMode(void){
		//char mode[10];
		unsigned long length;
		if(PvAttrEnumGet(handle, "FrameStartTriggerMode", cmode.frametrigarr,sizeof(cmode.frametrigarr),&length)!=ePvErrSuccess)
			return 666;
		switch(length){
		case 7:
			return FREERUN;
		case 9:
			return FIXEDRATE;
		case 8:
			return SOFTWARE;
		}	
		return 0;
	}
	int Camera::pvGetGainMode(){
		//	int enumed;
		char mode[10]={'\0'};
		unsigned long length;
		if(PvAttrEnumGet(handle, "GainMode", mode,sizeof(mode),&length)!=ePvErrSuccess)
			return 666;
		switch(length){
		case 4:
			return AUTO_CONTINOUOUS;
		case 6:
			return MANUAL;
		case 8:
			return AUTO_ONCE;
		}	
		return 0;
	}
	void (PVDECL Frame_Callback)(tPvFrame* frame){

		int stat;
		Camera *temp = (Camera*)frame->Context[0];
		char str[80];
//		char int_string[5];
		char int_string2[20];
//		char int_string3[5];
		char int_time[15];


		//	System::Drawing::Bitmap ^srcBmp;
		if((stat=PvCaptureWaitForFrameDone(*temp->get_handle(),temp->get_frame(),PVINFINITE))==ePvErrSuccess)
		{
			memcpy(temp->output_Img.ptr(),(char*)temp->get_frame()->ImageBuffer,temp->get_frame()->ImageSize);

			if(temp->img_process.disp_Options[IMG_WINDOW]==TRUE&&temp->img_process.disp_Options[WINDOW_READY]==TRUE)
				imshow( temp->get_Camera_info()->SerialNumber, temp->output_Img );
			temp->img_process.disp_Options[FORM_READY]=TRUE;

			if(strcmp(temp->get_cameraModep()->acqarr,"SingleFrame")==0){
				stat=PvCommandRun(*temp->get_handle(),"AcquisitionStop");
				temp->Camera_stopcapt();
			}
			else if(strcmp(temp->get_cameraModep()->acqarr,"MultiFrame")==0){
				if(++temp->multiframe>=((temp->get_cameraModep()->framect))){
					stat=PvCommandRun(*temp->get_handle(),"AcquisitionStop");
					temp->multiframe = 0;
					temp->Camera_stopcapt();
				}
			}
			

			if(temp->img_process.disp_Options[IMG_SAVE]==true){
				SYSTEMTIME myTime;
				GetSystemTime(&myTime);
				sprintf_s(int_time, "%d_%d_%d_%d", myTime.wHour, myTime.wMinute,myTime.wSecond,myTime.wMilliseconds); //time at which capture has finished
				sprintf_s(int_string2, "imagesfrom%d",temp->get_Camera_info()->UniqueId);						//ID of camera
				sprintf_s(str, "%s\\%d_%s.bmp",int_string2,temp->frameno++,int_time);
				CreateDirectoryA(int_string2, NULL);
				bool in=imwrite(str,temp->output_Img);
			}
		}
		else
			OutputDebugString(L"PvCaptureWaitForFrameDone");
	}
	void Camera::Single_frame(void){

		int stat;
		char str[80];
//		char int_string[5];
		char int_string2[20];
//		char int_string3[5];
		char int_time[15];

		//	System::Drawing::Bitmap ^srcBmp;
		if((stat=PvCaptureWaitForFrameDone(handle,&img_frame,PVINFINITE))==ePvErrSuccess)
		{
			memcpy(output_Img.ptr(),(char*)img_frame.ImageBuffer,img_frame.ImageSize);

			if(img_process.disp_Options[IMG_WINDOW]==TRUE&&img_process.disp_Options[WINDOW_READY]==TRUE)
				imshow( camera_info.SerialNumber, output_Img );
			img_process.disp_Options[FORM_READY]=TRUE;
			if(img_process.disp_Options[IMG_SAVE]==true){

				SYSTEMTIME myTime;
				GetSystemTime(&myTime);
				sprintf_s(int_time, "%d_%d_%d_%d", myTime.wHour, myTime.wMinute,myTime.wSecond,myTime.wMilliseconds); //time at which capture has finished
				sprintf_s(int_string2, "imagesfrom%d",camera_info.UniqueId);						//ID of camera
				sprintf_s(str, "%s\\%d_%s.bmp",int_string2,frameno++,int_time);
				if(CreateDirectoryA(int_string2, NULL))
				bool hi = imwrite(str,output_Img);
			}
		}
		else
			OutputDebugString(L"PvCaptureWaitForFrameDone");
	}


	/*Other functions*/
	int Cam_found(Cameras *cams, unsigned int pocet)
	{
		int cam_assigned;
		tPvCameraInfoEx *list = new tPvCameraInfoEx[pocet];
		cam_assigned = PvCameraListEx(list,pocet,NULL,sizeof(tPvCameraInfoEx));
		for(unsigned int i = 0; i<pocet;i++){
			cams->list[i]->set_cameraInfo(list[i]);
			cams->list[i]->cam_index = i;
			cams->list[i]->frameno = 0;
			cams->list[i]->multiframe = 0;
		}

		return 1;
	}

	string Cam_fcn(unsigned long id){
		string fcn;
		switch (id){
		case 5006509:
			fcn.append("Measured track 1");
			return fcn;

		case 5006510:
			fcn.append("Cross 2");
			return fcn;

		case 5006511:
			fcn.append("Measured track 2");
			return fcn;

		case 5006512:
			fcn.append("Cross 4");
			return fcn;

		case 5006513:
			fcn.append("Cross 1");
			return fcn;

		case 5006514:
			fcn.append("Cross 3");
			return fcn;

		default:
			fcn.append("Unknown ID");
			return fcn;
		}
	}

	int PvApi_init()
	{
		if(PvInitialize())
			return 0;
		return 1;
	}

	int PvApi_unInit()
	{
		PvUnInitialize();
		return 1;
	}