#if _MSC_VER > 1500 
#include <stdint.h>
#else 
#include "stdint.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <locale.h>

#ifdef _USE_WIN_API
/*ifndef _USE_LINUX_API*/
#include <Windows.h>
#endif


#define MAX_LEN	1024
void trim(char *s);

#include "bcap_client.h"

/* *** Please change IP to the target RC8 *** */ 
#define TARGET_RC8_IP	"192.168.0.1"


/*
  This program will get all global variable from the target RC8 and then put all them back. 
*/

wchar_t *wcVarLen[] = {L"@VAR_I_LEN", L"@VAR_F_LEN", L"@VAR_D_LEN", L"@VAR_V_LEN", L"@VAR_J_LEN", L"@VAR_P_LEN", L"@VAR_T_LEN", L"@VAR_S_LEN", NULL};
wchar_t *wcVarName[] = {L"I*", L"F*", L"D*", L"V*", L"J*", L"P*", L"T*", L"S*", NULL};
char *FileName[] = {"I.csv", "F.csv", "D.csv", "V.csv", "J.csv", "P.csv", "T.csv", "S.csv", NULL};

HRESULT get_variables()
{
	int fd;
	uint32_t hCtrl;
	BSTR bstr1, bstr2, bstr3, bstr4;
	HRESULT hr;

	/* Open connection. specify the IP address of bCapServer */
	printf("Open connection to tcp:%s\n", TARGET_RC8_IP);
	hr = bCap_Open_Client("tcp:" TARGET_RC8_IP, 1000, 3, &fd);

	if(SUCCEEDED(hr)){
		/* Send SERVICE_START packet */
		bCap_ServiceStart(fd, NULL);

		bstr1 = SysAllocString(L"");                    /* Name */
		bstr2 = SysAllocString(L"CaoProv.DENSO.VRC");   /* Provider */
		bstr3 = SysAllocString(L"localhost");			/* Machine */
		bstr4 = SysAllocString(L"");					/* Option */

		/* Connect RC8 */
		hr = bCap_ControllerConnect(fd, bstr1, bstr2, bstr3, bstr4, &hCtrl);

		SysFreeString(bstr1);
		SysFreeString(bstr2);
		SysFreeString(bstr3);
		SysFreeString(bstr4);

		if(SUCCEEDED(hr)){
			int n = 0;
			while(wcVarLen[n] != NULL) 
			{
				uint32_t hVarLen;

				/* Sets the locale.*/
				if (n == 7 /* S type variable */) {
					/* The string resource should be the default, which is the system-default ANSI code page obtained from the OS. */
					setlocale( LC_ALL, "" );
				} else {
					setlocale( LC_ALL, "C" ); // The default as the program startup. 
				}

				/* get size of the target varible */
				// --------------------------------------------------------
				bstr1 = SysAllocString(wcVarLen[n]);	// Name
				bstr2 = SysAllocString(L"");		// Option

				/* Get variable handle of @VAR_?_LEN */
				hr = bCap_ControllerGetVariable(fd, hCtrl, bstr1, bstr2, &hVarLen);

				SysFreeString(bstr1);
				SysFreeString(bstr2);

				if(SUCCEEDED(hr)){
					uint32_t hVar;
					VARIANT vVarLen;
					int iVarLen = 0;

					VariantInit(&vVarLen);

					bCap_VariableGetValue(fd, hVarLen, &vVarLen);
					// vVarLen.vt == VT_I4
					iVarLen = vVarLen.lVal;
					printf("%s = %d\n", wcVarLen[n], iVarLen);

					VariantClear(&vVarLen);

					/* Release variable handle of @VAR_?_LEN */
					bCap_VariableRelease(fd, &hVarLen);


					/* get handle of the target varible */
					// --------------------------------------------------------
					bstr1 = SysAllocString(wcVarName[n]);	// Name
					bstr2 = SysAllocString(L"");		// Option

					/* Get variable handle */
					hr = bCap_ControllerGetVariable(fd, hCtrl, bstr1, bstr2, &hVar);

					SysFreeString(bstr1);
					SysFreeString(bstr2);

					// --------------------------------------------------------
					if(SUCCEEDED(hr)){
						VARIANT vIndex;
						FILE* fdVar;

						fdVar = fopen(FileName[n], "w");
						if (fdVar) {
							int i;
							VARIANT vValue;

							printf("Open %s\n", FileName[n]);

							VariantInit(&vValue);

							/* put variable size */
							fprintf(fdVar, "%d\n", iVarLen);

							/* get each value of variables and then put it into the file */
							for(i=0; i<iVarLen; i++) 
							{
								/* set variable index */
								vIndex.vt = VT_I4;
								vIndex.lVal = (LONG)i;
								bCap_VariablePutID(fd, hVar, vIndex);

								/* get variable value */
								hr = bCap_VariableGetValue(fd, hVar, &vValue);

								if(SUCCEEDED(hr)){
									switch(n) {
									case 0: // I
										{
											// vValue.vt = VT_I4
											fprintf(fdVar, "%d\n", vValue.lVal);
										}
										break;
									case 1: // F
										{
											// vValue.vt = VT_R4
											fprintf(fdVar, "%f\n", vValue.fltVal);
										}
										break;
									case 2: // D
										{
											// vValue.vt = VT_R8
											fprintf(fdVar, "%lf\n", vValue.dblVal);
										}
										break;
									case 3: // V
										{
											// vValue.vt = VT_R4 | VT_ARRAY
											float *pfData, fV[3];

											SafeArrayAccessData(vValue.parray, (void **)&pfData);
											memcpy(fV, pfData, 3 * sizeof(float));
											SafeArrayUnaccessData(vValue.parray);

											fprintf(fdVar, "V(%f,%f,%f)\n" ,fV[0], fV[1], fV[2]);
										}
										break;
									case 4: // J
										{
											// vValue.vt = VT_R4 | VT_ARRAY
											float *pfData, fJ[8];

											SafeArrayAccessData(vValue.parray, (void **)&pfData);
											memcpy(fJ, pfData, 8 * sizeof(float));
											SafeArrayUnaccessData(vValue.parray);

											fprintf(fdVar, "J(%f,%f,%f,%f,%f,%f,%f,%f)\n" ,fJ[0], fJ[1], fJ[2], fJ[3], fJ[4], fJ[5], fJ[6], fJ[7]);
										}
										break;
									case 5: // P
										{
											// vValue.vt = VT_R4 | VT_ARRAY
											float *pfData, fP[7]; // x ,y ,z ,rx ,ry ,rz ,fig

											SafeArrayAccessData(vValue.parray, (void **)&pfData);
											memcpy(fP, pfData, 7 * sizeof(float));
											SafeArrayUnaccessData(vValue.parray);

											fprintf(fdVar, "P(%f,%f,%f,%f,%f,%f,%1.0f)\n" ,fP[0], fP[1], fP[2], fP[3], fP[4], fP[5], fP[6]);
										}
										break;
									case 6: // T
										{
											// vValue.vt = VT_R4 | VT_ARRAY
											float *pfData, fT[10]; // px ,py ,pz ,ox ,oy ,oz ,ax ,ay ,az ,fig

											SafeArrayAccessData(vValue.parray, (void **)&pfData);
											memcpy(fT, pfData, 10 * sizeof(float));
											SafeArrayUnaccessData(vValue.parray);

											fprintf(fdVar, "T(%f,%f,%f,%f,%f,%f,%f,%f,%f,%1.0f)\n" ,fT[0], fT[1], fT[2], fT[3], fT[4], fT[5], fT[6], fT[7], fT[8], fT[9]);
										}
										break;
									case 7: // S
										{
											// vValue.vt = VT_BSTR (UTF-16)
											char cValue[260]; // max length of S type is 256 byte
											wcstombs(cValue, vValue.bstrVal, 260);
											trim(cValue);
											fprintf(fdVar, "%s\n", cValue);
										}
										break;
									}
								}

								/* release variable allocated memory */
								VariantClear(&vValue);
							}
							fclose(fdVar);
							printf("Close %s\n", FileName[n]);
						}

						/* Release variable handle */
						bCap_VariableRelease(fd, &hVar);
					}
				}
				n++; // Next variable type
			}

			/* Disconnect RC8 */
			bCap_ControllerDisconnect(fd, &hCtrl);
		}

		/* Send SERVICE_STOP packet */
		bCap_ServiceStop(fd);

		/* Close connection */
		bCap_Close_Client(&fd);
	}

	return hr;
};

HRESULT put_variables()
{
	int fd;
	uint32_t hCtrl;
	BSTR bstr1, bstr2, bstr3, bstr4;
	HRESULT hr;

	/* Open connection. specify the IP address of bCapServer */
	printf("Open connection to tcp:%s\n", TARGET_RC8_IP);
	hr = bCap_Open_Client("tcp:" TARGET_RC8_IP, 1000, 3, &fd);

	if(SUCCEEDED(hr)){
		/* Send SERVICE_START packet */
		bCap_ServiceStart(fd, NULL);

		bstr1 = SysAllocString(L"");                    /* Name */
		bstr2 = SysAllocString(L"CaoProv.DENSO.VRC");   /* Provider */
		bstr3 = SysAllocString(L"localhost");			/* Machine */
		bstr4 = SysAllocString(L"");					/* Option */

		/* Connect RC8 */
		hr = bCap_ControllerConnect(fd, bstr1, bstr2, bstr3, bstr4, &hCtrl);

		SysFreeString(bstr1);
		SysFreeString(bstr2);
		SysFreeString(bstr3);
		SysFreeString(bstr4);

		if(SUCCEEDED(hr)){
			int n = 0;
			while(wcVarLen[n] != NULL) 
			{
				uint32_t hVarLen;

				/* Sets the locale.*/
				if (n == 7 /* S type variable */) {
					/* The string resource should be the default, which is the system-default ANSI code page obtained from the OS. */
					setlocale( LC_ALL, "" );
				} else {
					setlocale( LC_ALL, "C" ); // The default as the program startup. 
				}

				/* get size of the target varible */
				// --------------------------------------------------------
				bstr1 = SysAllocString(wcVarLen[n]);	// Name
				bstr2 = SysAllocString(L"");		// Option

				/* Get variable handle of @VAR_?_LEN */
				hr = bCap_ControllerGetVariable(fd, hCtrl, bstr1, bstr2, &hVarLen);

				SysFreeString(bstr1);
				SysFreeString(bstr2);

				if(SUCCEEDED(hr)){
					uint32_t hVar;
					VARIANT vVarLen;
					int iVarLen = 0;

					VariantInit(&vVarLen);

					bCap_VariableGetValue(fd, hVarLen, &vVarLen);
					// vVarLen.vt == VT_I4
					iVarLen = vVarLen.lVal;
					printf("%s = %d\n", wcVarLen[n], iVarLen);

					/* get handle of the target varible */
					// --------------------------------------------------------
					bstr1 = SysAllocString(wcVarName[n]);	// Name
					bstr2 = SysAllocString(L"");		// Option

					/* Get variable handle */
					hr = bCap_ControllerGetVariable(fd, hCtrl, bstr1, bstr2, &hVar);

					SysFreeString(bstr1);
					SysFreeString(bstr2);

					// --------------------------------------------------------
					if(SUCCEEDED(hr)){
						VARIANT vIndex;
						FILE* fdVar;

						fdVar = fopen(FileName[n], "r");
						if (fdVar) {
							int i, iVarMax;
							VARIANT vValue;
							char line[MAX_LEN], *result;
							wchar_t wcValue[MAX_LEN];

							printf("Open %s\n", FileName[n]);

							VariantInit(&vValue);

						    result = fgets(line, MAX_LEN, fdVar);
							iVarMax = atoi(result);

							/* print variable size */
							printf("%s", result);

							/* resize variable size */
							if (iVarLen != iVarMax)
							{
								vVarLen.vt = VT_I4;
								vVarLen.lVal = iVarMax;

								hr = bCap_VariablePutValue(fd, hVarLen, vVarLen);
							}
							if(SUCCEEDED(hr)){
								/* get each value of variables and then put it into the file */
								for(i=0; i<iVarMax; i++) 
								{
									/* set variable index */
									vIndex.vt = VT_I4;
									vIndex.lVal = (LONG)i;
									bCap_VariablePutID(fd, hVar, vIndex);

									result = fgets(line, MAX_LEN, fdVar);
									// MBS to wchar_t
									mbstowcs(wcValue, result, MAX_LEN);

									vValue.vt = VT_BSTR;
									vValue.bstrVal = SysAllocString(wcValue);

									/* put variable value */
									hr = bCap_VariablePutValue(fd, hVar, vValue);

									/* release variable allocated memory */
									VariantClear(&vValue);
								}
							}
							fclose(fdVar);
							printf("Close %s\n", FileName[n]);
						}

						/* Release variable handle */
						bCap_VariableRelease(fd, &hVar);
					}
				}
				/* Release variable handle of @VAR_?_LEN */
				bCap_VariableRelease(fd, &hVarLen);

				n++; // Next variable type
			}

			/* Disconnect RC8 */
			bCap_ControllerDisconnect(fd, &hCtrl);
		}

		/* Send SERVICE_STOP packet */
		bCap_ServiceStop(fd);

		/* Close connection */
		bCap_Close_Client(&fd);
	}

	return hr;
};

#include <ctype.h>
void trim(char *s) {
    int i, j;
    for( i = ((int)strlen(s))-1; i >= 0 && isspace( s[i] ); i-- ) ;
    s[i+1] = '\0';
    for( i = 0; isspace( s[i] ); i++ ) ;
    if( i > 0 ) {
        j = 0;
        while( s[i] ) s[j++] = s[i++];
        s[j] = '\0';
    }
}

int main()
{
	HRESULT hr;

	printf("Enter any key to get global variables.\n");
	getch();

	hr = get_variables();

	if (SUCCEEDED(hr)) {

		printf("Enter any key to put global variables.\n");
		getch();

		hr = put_variables();
	}

	if (FAILED(hr)) {
		printf("Failed !!\n");
		getch();
	}

	return 0;
}
