#if _MSC_VER > 1500 
#include <stdint.h>
#else 
#include "stdint.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

#ifdef _USE_WIN_API
/*ifndef _USE_LINUX_API*/
#include <Windows.h>
#endif

#include "bcap_client.h"

/* *** Please change IP to the target RC8 *** */ 
#define TARGET_RC8_IP	"192.168.0.1"

/*
  This program will START Pro1 task and then STOP it. 
*/

#define TASK_CMD_START	0
#define TASK_CMD_STOP	1

/*
  Refer to 
   \ORiN2\CAO\ProviderLib\DENSO\RC8\Doc\RC8_ProvGuide_en.pdf
  about the details of RC8 command parameters.
*/
// Start mode definiton
// 1: One cycle execution, 2: Continuous execution, 3: Step forward
#define START_MODE_ONE_CYCLE	1
#define START_MODE_CONTINUOS	2
#define START_MODE_STEP_FORWARD	3

// Stop mode definiton
// 0: Default stop, 1: Instant stop, 2: Step stop, 3: Cycle stop, 4: Initialized stop
#define STOP_MODE_DEFAULT		0
#define STOP_MODE_INSTANT		1
#define STOP_MODE_STEP			2
#define STOP_MODE_CYCLE			3
#define STOP_MODE_INITIALIZED	4

// Controller Mode Switch definition
#define CTRLSW_MODE_MANUAL		1
#define CTRLSW_MODE_TEACH		2
#define CTRLSW_MODE_AUTO		3

HRESULT control_task(wchar_t *taskname, int32_t taskcommand, int32_t taskmode)
{
	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);

		/* Check the control mode switch. It should be AUTO. */
		if(SUCCEEDED(hr)){
			uint32_t hMode;

			bstr1 = SysAllocString(L"@Mode");	// Name
			bstr2 = SysAllocString(L"");		// Option

			/* Get mode switch variable handle */
			hr = bCap_ControllerGetVariable(fd, hCtrl, bstr1, bstr2, &hMode);

			SysFreeString(bstr1);
			SysFreeString(bstr2);

			if(SUCCEEDED(hr)){
				VARIANT vMode;

				VariantInit(&vMode);

				bCap_VariableGetValue(fd, hMode, &vMode);
				VariantChangeType(&vMode, &vMode, 0, VT_I4);
				// vMode.vt == VT_I4
				if (vMode.lVal != CTRLSW_MODE_AUTO) {
					printf("Change RC8-MODE to AUTO !!\n");
					hr = E_FAIL;
				}

				/* Release variable handle of @Mode */
				bCap_VariableRelease(fd, &hMode);
			}
		}

		if(SUCCEEDED(hr)){
			uint32_t hTask;

			bstr1 = SysAllocString(taskname);	// Name
			bstr2 = SysAllocString(L"");		// Option

			/* Get task handle */
			hr = bCap_ControllerGetTask(fd, hCtrl, bstr1, bstr2, &hTask);

			SysFreeString(bstr1);
			SysFreeString(bstr2);

			if(SUCCEEDED(hr)){

				bstr1 = SysAllocString(L"");		// Option
				switch(taskcommand) {
				case TASK_CMD_START:
					hr = bCap_TaskStart(fd, hTask, taskmode, bstr1);
					break;
				case TASK_CMD_STOP:
					hr = bCap_TaskStop(fd, hTask, taskmode, bstr1);
					break;
				}
				SysFreeString(bstr1);
	
				/* Release task handle */
				bCap_TaskRelease(fd, &hTask);
			}

			/* Disconnect RC8 */
			bCap_ControllerDisconnect(fd, &hCtrl);
		}

		/* Send SERVICE_STOP packet */
		bCap_ServiceStop(fd);

		/* Close connection */
		bCap_Close_Client(&fd);
	}

	return hr;
};

int main()
{
	HRESULT hr;

	printf("Enter any key to start pro1 task.\n");
	getch();

	hr = control_task(L"pro1", TASK_CMD_START, START_MODE_ONE_CYCLE);
	if (SUCCEEDED(hr)) {

		printf("Enter any key to stop pro1 task.\n");
		getch();

		hr = control_task(L"pro1", TASK_CMD_STOP, STOP_MODE_INITIALIZED);
	}

	if (FAILED(hr)) {
		printf("Failed !!\n");
		getch();
		return -1;
	}

	return 0;
}
