#include <iostream>
#include "cdAPI.h"
#include "H2ocam10.h"
using namespace std;

#ifndef		GETERRORID
#define		GETERRORID( x )		(cdERROR_ERRORID_MASK&x)
#endif

#define TRUE	1


/****************** Main ************************/


void main(int argc, char *argv[])
{
	cdError			err=cdOK;		// cdOK = 0
	int				i, val;
	cdUInt16		iso = cdREL_VAL_ISO_100;		// ISO rating
	cdRemoteSetTv	Tv = cdREMOTE_SET_TV2_30;		// Tv (shutter speed)
	cdCompQuality	qual = cdCOMP_QUALITY_FINE;		// Image quality (Fine, Normal, Raw)
	cdImageSize		size = cdIMAGE_SIZE_LARGE;		// Image size (Large, Medium, Small)

	cout << "H2O D60 Camera Program" << endl;

	for(i=1;i<argc;i++)
	{
		if(argv[i][0] == '/')
		{
			switch(argv[i][1])
			{
			case 's':	// Small
				size = cdIMAGE_SIZE_SMALL;
				break;

			case 'm':	// Medium
				size = cdIMAGE_SIZE_MEDIUM;
				break;

			case 'l':	// Large
				size = cdIMAGE_SIZE_LARGE;
				break;

			case 'f':	// Fine
				qual = cdCOMP_QUALITY_FINE;
				break;

			case 'n':	// Normal
				qual = cdCOMP_QUALITY_NORMAL;
				break;

			case 'r':	// RAW
				qual = cdCOMP_QUALITY_RAW;
				break;

			case 'i' :	// ISO rating
				val = atoi(argv[i]+2);
				switch(val)
				{
					case 100:
						iso = cdREL_VAL_ISO_100;
						break;
					case 200:
						iso = cdREL_VAL_ISO_200;
						break;
				}
				break;

			case 't' :	// Tv (shutter speed)
				val = atoi(argv[i]+2);
				switch(val)
				{
					case 30:
						Tv = cdREMOTE_SET_TV2_30;
						break;
					case 60:
						Tv = cdREMOTE_SET_TV2_60;
						break;
					case 125:
						Tv = cdREMOTE_SET_TV2_125;
						break;
				}
				break;

			case 'h' :
				cout << "Usage (* = default): " << endl
					<< "/s -- Small" << endl
					<< "/m -- Medium" << endl
					<< "/l -- Large*" << endl
					<< "/f -- Fine*" << endl
					<< "/n -- Normal" << endl
					<< "/j -- JPEG*" << endl
					<< "/r -- RAW" << endl
					<< "/i -- ISO (100*, 200)" << endl
					<< "/t -- Tv (30*, 60, 125)" << endl;
				return;

			default:
				cout << "Unrecognized command" << endl;
				return;
			}
		}
	}

	/* Print settings */
	cout << endl
		<< "Quality = " << "0x" << hex << qual << endl
		<< "Size = " << "0x" << hex << size << endl
		<< "ISO = " << "0x" << hex << iso << endl
		<< "Tv = " << "0x" << hex << Tv << endl << endl;
		
	/* Start CDSDK. */
	cdVersionInfo	SVersion;
	memset( &SVersion, 0, sizeof(cdVersionInfo) );
	SVersion.Size = sizeof(cdVersionInfo);
	SVersion.MajorVersion = 5;
	SVersion.MinorVersion = 0;
	err = CDStartSDK( &SVersion, 0 );
	if(err)
	{
		cout << "CDStartSDK error";
		goto camerr;
	}
	
	// Find camera
	cdHEnum		hEnumDevice;
	cdUInt32 	count=0;
	cdUInt32	index=0;
	cdSourceInfo sourceInfo[2];
    
    err = CDEnumDeviceReset(1, &hEnumDevice);
    if(err)
	{
		cout << "CDEnumDeviceReset error" << endl;
		goto camerr;
	}

    err = CDGetDeviceCount(hEnumDevice, &count);
    if(err)
	{
		cout << "CDGetDeviceCount error" << endl;
		goto camerr;
	}
	else if(count == 0)
	{
		cout << "No camera found" << endl;
	}
	else
	{	
	    for(index = 0; index<count; index++)
		{
			err = CDEnumDeviceNext(hEnumDevice, &sourceInfo[index]);
			if(err)
			{
				cout << "CDEnumDeviceNext error" << endl;
				goto camerr;
			}
		}
    }
	
	cout << "Cameras found = " << count << endl;

    err = CDEnumDeviceRelease(hEnumDevice);
    if(err)
	{
		cout << "CDEnumDeviceRelease error" << endl;
		goto camerr;
	}
	
	/* Open camera */
	cdHSource	hSource;			/* The handle of a camera */

	err = CDOpenSource(&sourceInfo[0], &hSource );
	if(err)
	{
		cout << "CDOpenSource error" << endl;
		goto camerr;
	}
	
	/* UI is locked so that information may not be changed. */
	//err = CDLockUI( hSource );
	//if(err)
	//{
	//	cout << "CDLockUI" << endl;
	//	goto camerr;
	//}
	//

	/* A camera is set as remote release control mode. */
	err = CDEnterReleaseControl( hSource, RelCallBackFunc, 0 );
	if(err)
	{
		cout << "CDEnterReleaseControl error" << endl;	
		goto camerr;
	}

	err = CDSetImageFormatAttribute( hSource, qual, size);
	if(err)
	{
		cout << "CDSetImageFormatAttribute error" << endl;
		goto camerr;
	}

	err = CDSetShootingMode( hSource, cdSHOOTING_MODE_MANUAL);
	if(err)
	{
		cout << "CDSetShootingMode error" << endl;
		goto camerr;
	}

	err = CDSetRelCamSettingData( hSource, cdREL_SET_ISO_SPEED_RATINGS, sizeof(iso), &iso); 
	if(err)
	{
		cout << "CDSetRelCamSettingData error" << endl;
		goto camerr;
	}

	err = CDSetTvValue( hSource, Tv );
	if(err)
	{
		cout << "CDSetTvValue error" << endl;
		goto camerr;
	}

	err = CDSelectReleaseDataKind( hSource, cdREL_KIND_PICT_TO_PC );
	if(err)
	{
		cout << "CDSelectReleaseDataKind error" << endl;
		goto camerr;
	}

	/* Take a picture */
	cdUInt32 NumData;
	err = CDRelease( hSource, TRUE, NULL, NULL, cdPROG_NO_REPORT, &NumData );
	if(err)
	{
		cout << "CDRelease error" << endl;
		goto camerr;
	}

	/* Save picture */
	cdReleaseImageInfo			RelImgInfo;
	cdStgMedium					MyMedium;
	char						szFileName[80];
	
	if(qual == cdCOMP_QUALITY_RAW)
	{
		strcpy(szFileName, "\\temp\\Temp.RAW");
	}
	else strcpy(szFileName, "\\temp\\Temp.JPG");
	
	MyMedium.Type = cdMEMTYPE_FILE;
	MyMedium.u.lpszFileName = szFileName;
	unsigned int x;

	cout << "NumData = " << NumData << endl;

	for(x=0; x<NumData; x++)
	{
		if( CDGetReleasedData( hSource, NULL, 0, cdPROG_NO_REPORT, &RelImgInfo,	&MyMedium ) != cdOK )
		{
			cout << "CDGetReleasedData error" << endl;
			goto camerr;
		}
	}
	
	/* Cleanup for program exit */
	CDExitReleaseControl( hSource );
	if(err)
	{
		cout << "CDExitReleaseControl" << endl;
		goto camerr;
	}

	//err = CDUnlockUI( hSource );
	//if(err)
	//{
	//	cout << "CDUnlockUI error" << endl;
	//	goto camerr;
	//}
	
	CDCloseSource( hSource );
	CDFinishSDK();
	
	
	/* End of program */ 
	cout << "End of program" << endl;
//	cin.ignore();

	return;

	
camerr:
	cout << "Component ID code = " << hex << (cdERROR_COMPONENTID_MASK & err) << endl;
	cout << "Error ID code = " << hex << (cdERROR_ERRORID_MASK & err) << endl;
	CDCloseSource( hSource );
	CDFinishSDK();
	cout << "End of program" << endl;
//	cin.ignore();
	return;
}

/////////////////////////////////////////////////////////////////////////////
// Call back function

cdUInt32 cdSTDCALL	CamCallBackFunc(	cdEventID		EventID,
											const cdVoid*	pData,
											cdUInt32		DataSize,
											cdContext		Context )
{
	
	/* A security level is checked. */
	switch( cdEVENT_SEVERITY(EventID) )
	{
		case cdEVENT_SEVERITY_SHUTDOWN:
			break;
		case cdEVENT_SEVERITY_NONE:
		case cdEVENT_SEVERITY_WARNING:
			break;
	}
	
	return	cdOK;
}

/**/
cdUInt32 cdSTDCALL	RelCallBackFunc(	cdReleaseEventID	EventID,
											const void *		pData,
											cdUInt32 			DataSize,
											cdContext			Context )
{
	cdError			err=cdOK;
	
	switch( EventID )
	{
		case cdRELEASE_EVENT_RESET_HW_ERROR:
			cout << "cdRELEASE_EVENT_RESET_HW_ERROR" << endl;
			break;
		case cdRELEASE_EVENT_CHANGED_BY_UI:
			cout << "cdRELEASE_EVENT_CHANGED_BY_UI" << endl;
			break;
		case cdRELEASE_EVENT_RELEASE_START:
			cout << "cdRELEASE_EVENT_RELEASE_START" << endl;
			break;
		case cdRESEASE_EVENT_RELEASE_COMPLETE:
			cout << "RESEASE_EVENT_RELEASE_COMPLETE" << endl;
			break;
		case cdRELEASE_EVENT_CAM_RELEASE_ON:
			cout << "cdRELEASE_EVENT_CAM_RELEASE_ON" << endl;
			break;
	}
	
	return	err;
}

