#include "stdafx.h"
#include "ClientAPI.h"
#include <string>
#include <ctime>
#include <iostream>
#include <chrono>

// insert the IP of your SP-ICE-3
#define CARD_IP "192.168.2.138"

static rlResult configureFont( rlHandle handle );
static rlResult markText( rlHandle handle, char* text );
static rlResult markDate( rlHandle handle );
static rlResult markCounter( rlHandle handle, const char* counterName );
static int printLastError( void );

int main()
{
	// establish a connection with the card
	rlHandle handle = rlConnect( CARD_IP, 49374 );
	if ( handle < 0 )
		return printLastError();

	rlResult status;

	// Reset the card to its default settings:
	// This restores the following settings to the values that were last saved on the card:
	// - scanner configuration (such as field size, field correction, etc.)
	// - laser configuration (such as gate/LM timing parameters, power target, etc.)
	// - process variables (such as jump speed, settling times, mark speed, etc.)
	if ( ( status = rlSystemResetToDefaults( handle ) ) != rlSUCCESS )
		goto Cleanup;

	// Set the laser power to 100%
	rlLaserConfig lc;
	if ( ( status = rlLaserGetConfig( handle, &lc ) ) != rlSUCCESS ) goto Cleanup;
	lc.PowerScale = 1;
	if ( ( status = rlLaserSetConfig( handle, &lc ) ) != rlSUCCESS ) goto Cleanup;

	// Enable the laser so it responds to commands that turn on the laser.
	// Note that this does not fire the laser until e.g. LaserOn or Mark command is executed.
	if ( ( status = rlLaserArmLaser( handle, true ) ) != rlSUCCESS ) goto Cleanup;

	// define the needed characters
	if ( ( status = configureFont( handle ) ) != rlSUCCESS ) goto Cleanup;

	time_t rawtime;
	struct tm * timeinfo;
	char timeBuffer[80];

	time( &rawtime );
	timeinfo = localtime( &rawtime );

	strftime( timeBuffer, 80, "%d-%m-%Y %I:%M:%S", timeinfo );

	if ( ( status = rlVariableMarkCounterCreate( handle, "counter", 0 ) ) != rlSUCCESS ) goto Cleanup;

	if ( ( status = markText( handle, timeBuffer ) ) != rlSUCCESS )
		goto Cleanup;
	if ( ( status = markDate( handle ) ) != rlSUCCESS )
		goto Cleanup;
	if ( ( status = markCounter( handle, "counter" ) ) != rlSUCCESS )
		goto Cleanup;

Cleanup:
	// print any errors
	if ( status != rlSUCCESS )
		printLastError();

	// disconnect from the card
	printf( "Disconnecting from card...\n" );
	if ( rlDisconnect( handle ) != rlSUCCESS )
		return printLastError();

	printf( "Exiting with status = %d\n", status );
	return status;
}

/// create Font
/// only digits space dash and colon are defined in this example
/// Every character is defined with relative commands from the anchor point in the lower left corner
/// and finishes at the anchor point of the next char
static rlResult configureFont( rlHandle handle )
{
	rlResult result;

	rlCommandListHandle c0 = rlListAllocate( handle );
	if ( ( result = rlListAppendJumpRel2D( c0, 500, 1000 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c0, 0, -500 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c0, 0, -500 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c0, -500, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c0, 0, 500 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c0, 0, 500 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c0, 500, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendJumpRel2D( c0, 500, -1000 ) ) != rlSUCCESS ) return result;

	rlCommandListHandle c1 = rlListAllocate( handle );
	if ( ( result = rlListAppendJumpRel2D( c1, 500, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c1, 0, 1000 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendJumpRel2D( c1, 500, -1000 ) ) != rlSUCCESS ) return result;

	rlCommandListHandle c2 = rlListAllocate( handle );
	if ( ( result = rlListAppendJumpRel2D( c2, 0, 1000 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c2, 500, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c2, 0, -500 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c2, -500, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c2, 0, -500 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c2, 500, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendJumpRel2D( c2, 500, 0 ) ) != rlSUCCESS ) return result;

	rlCommandListHandle c3 = rlListAllocate( handle );
	if ( ( result = rlListAppendJumpRel2D( c3, 0, 1000 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c3, 500, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c3, 0, -500 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c3, -500, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendJumpRel2D( c3, 500, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c3, 0, -500 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c3, -500, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendJumpRel2D( c3, 1000, 0 ) ) != rlSUCCESS ) return result;

	rlCommandListHandle c4 = rlListAllocate( handle );
	if ( ( result = rlListAppendJumpRel2D( c4, 0, 1000 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c4, 0, -500 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c4, 500, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendJumpRel2D( c4, 0, 500 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c4, 0, -1000 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendJumpRel2D( c4, 500, 0 ) ) != rlSUCCESS ) return result;

	rlCommandListHandle c5 = rlListAllocate( handle );
	if ( ( result = rlListAppendJumpRel2D( c5, 500, 1000 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c5, -500, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c5, 0, -500 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c5, 500, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c5, 0, -500 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c5, -500, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendJumpRel2D( c5, 1000, 0 ) ) != rlSUCCESS ) return result;

	rlCommandListHandle c6 = rlListAllocate( handle );
	if ( ( result = rlListAppendJumpRel2D( c6, 500, 1000 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c6, -500, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c6, 0, -500 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c6, 0, -500 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c6, 500, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c6, 0, 500 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c6, -500, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendJumpRel2D( c6, 1000, -500 ) ) != rlSUCCESS ) return result;

	rlCommandListHandle c7 = rlListAllocate( handle );
	if ( ( result = rlListAppendJumpRel2D( c7, 0, 1000 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c7, 500, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c7, 0, -500 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c7, 0, -500 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendJumpRel2D( c7, 500, 0 ) ) != rlSUCCESS ) return result;

	rlCommandListHandle c8 = rlListAllocate( handle );
	if ( ( result = rlListAppendJumpRel2D( c8, 500, 1000 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c8, -500, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c8, 0, -500 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c8, 500, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c8, 0, 500 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendJumpRel2D( c8, 0, -500 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c8, 0, -500 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c8, -500, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c8, 0, 500 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendJumpRel2D( c8, 1000, -500 ) ) != rlSUCCESS ) return result;

	rlCommandListHandle c9 = rlListAllocate( handle );
	if ( ( result = rlListAppendJumpRel2D( c9, 500, 1000 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c9, -500, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c9, 0, -500 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c9, 500, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c9, 0, 500 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendJumpRel2D( c9, 0, -500 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c9, 0, -500 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( c9, -500, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendJumpRel2D( c9, 1000, 0 ) ) != rlSUCCESS ) return result;

	rlCommandListHandle colon = rlListAllocate( handle );
	if ( ( result = rlListAppendJumpRel2D( colon, 0, 200 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( colon, 200, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( colon, 0, 200 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( colon, -200, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( colon, 0, -200 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendJumpRel2D( colon, 0, 400 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( colon, 200, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( colon, 0, 200 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( colon, -200, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( colon, 0, -200 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendJumpRel2D( colon, 500, -600 ) ) != rlSUCCESS ) return result;

	rlCommandListHandle space = rlListAllocate( handle );
	if ( ( result = rlListAppendJumpRel2D( space, 500, 0 ) ) != rlSUCCESS ) return result;

	rlCommandListHandle dash = rlListAllocate( handle );
	if ( ( result = rlListAppendJumpRel2D( dash, 0, 500 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkRel2D( dash, 500, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendJumpRel2D( dash, 500, -500 ) ) != rlSUCCESS ) return result;

	rlFontHandle font = rlFontAllocate( handle, 0 );

	rlFontAddChar( handle, ' ', space );
	if ( ( result = rlFontAddChar( font, '0', c0 ) ) != rlSUCCESS )	return result;
	if ( ( result = rlFontAddChar( font, '1', c1 ) ) != rlSUCCESS )	return result;
	if ( ( result = rlFontAddChar( font, '2', c2 ) ) != rlSUCCESS )	return result;
	if ( ( result = rlFontAddChar( font, '3', c3 ) ) != rlSUCCESS )	return result;
	if ( ( result = rlFontAddChar( font, '4', c4 ) ) != rlSUCCESS )	return result;
	if ( ( result = rlFontAddChar( font, '5', c5 ) ) != rlSUCCESS )	return result;
	if ( ( result = rlFontAddChar( font, '6', c6 ) ) != rlSUCCESS )	return result;
	if ( ( result = rlFontAddChar( font, '7', c7 ) ) != rlSUCCESS )	return result;
	if ( ( result = rlFontAddChar( font, '8', c8 ) ) != rlSUCCESS )	return result;
	if ( ( result = rlFontAddChar( font, '9', c9 ) ) != rlSUCCESS )	return result;
	if ( ( result = rlFontAddChar( font, ':', colon ) ) != rlSUCCESS )	return result;
	if ( ( result = rlFontAddChar( font, '-', dash ) ) != rlSUCCESS )	return result;
	if ( ( result = rlFontAddChar( font, ' ', space ) ) != rlSUCCESS )	return result;

	if ( ( result = rlFontSet( handle, font ) ) != rlSUCCESS ) return result;
	if ( ( result = rlFontSetActive( handle, 0 ) ) != rlSUCCESS ) return result;

	return rlSUCCESS;
}

/// <summary>
/// Mark the specified text
/// Every used character has to be defined in the font
/// </summary>
/// <param name="text">text to mark</param>
static rlResult markText( rlHandle handle, char* text )
{
	rlResult result;

	rlCommandListHandle list = rlListAllocate( handle );
	if ( ( result = rlListAppendPower( list, 25000 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendJumpSpeed( list, 3.0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkSpeed( list, 0.2 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendJumpAbs2D( list, -10000, -2000 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkText( list, text ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendLaserOff( list ) ) != rlSUCCESS ) return result;

	int listIndex = 0;

	// close the list causing its contents to be transferred to the card
	printf( "Closing list: index=%d...\n", listIndex );
	if ( ( result = rlListSet( handle, listIndex, list, false, -1 ) ) != rlSUCCESS ) return result;

	// run the list, and wait until its execution has completed
	printf( "Executing list: index=%d...\n", listIndex );
	if ( ( result = rlListExecute( handle, listIndex ) ) != rlSUCCESS ) return result;

	int timeoutMs = 30000;
	bool done = false;
	int32_t listID;
	printf( "Waiting until list execution is done: index=%d...\n", listIndex );
	if ( ( result = rlListWaitForListDone( handle, timeoutMs, &done, &listID ) ) != rlSUCCESS ) return result;
	if ( !done )
	{
		printf( "Timeout: execution has not completed after %d ms!", timeoutMs );
		return rlERROR;
	}
	printf( "Execution done: index=%d...\n", listIndex );

	// delete list on the card: this frees the card's memory occupied by the list
	printf( "Deleting list: index=%d...\n", listIndex );
	if ( ( result = rlListDelete( handle, listIndex, true ) ) != rlSUCCESS ) return result;

	// release the local list: this frees the PC's memory occupied by the card
	if ( ( result = rlListReleaseHandle( list ) ) != rlSUCCESS ) return result;

	return result;
}

/// mark the system time of the SPICE3 card with the font created in configureFont()
static rlResult markDate( rlHandle handle )
{
	rlResult result;

	rlVariableMarkCounterSetMarkTimeFormat( handle, "%H:%M:%S %Y-%m-%D" );

	rlCommandListHandle list = rlListAllocate( handle );
	if ( ( result = rlListAppendPower( list, 25000 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendJumpSpeed( list, 3.0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkSpeed( list, 0.2 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendJumpAbs2D( list, -10000, 0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkTime( list ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendLaserOff( list ) ) != rlSUCCESS ) return result;

	int listIndex = 0;

	// close the list causing its contents to be transferred to the card
	printf( "Closing list: index=%d...\n", listIndex );
	if ( ( result = rlListSet( handle, listIndex, list, false, -1 ) ) != rlSUCCESS ) return result;

	// run the list, and wait until its execution has completed
	printf( "Executing list: index=%d...\n", listIndex );
	if ( ( result = rlListExecute( handle, listIndex ) ) != rlSUCCESS ) return result;

	int timeoutMs = 30000;
	bool done = false;
	int32_t listID;
	printf( "Waiting until list execution is done: index=%d...\n", listIndex );
	if ( ( result = rlListWaitForListDone( handle, timeoutMs, &done, &listID ) ) != rlSUCCESS ) return result;
	if ( !done )
	{
		printf( "Timeout: execution has not completed after %d ms!", timeoutMs );
		return rlERROR;
	}
	printf( "Execution done: index=%d...\n", listIndex );

	// delete list on the card: this frees the card's memory occupied by the list
	printf( "Deleting list: index=%d...\n", listIndex );
	if ( ( result = rlListDelete( handle, listIndex, true ) ) != rlSUCCESS ) return result;

	// release the local list: this frees the PC's memory occupied by the card
	if ( ( result = rlListReleaseHandle( list ) ) != rlSUCCESS ) return result;

	return result;
}

/// mark counter with the font created in configureFont()
static rlResult markCounter( rlHandle handle, const char* counterName )
{
	rlResult result;

	rlCommandListHandle list = rlListAllocate( handle );
	if ( ( result = rlListAppendPower( list, 25000 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendJumpSpeed( list, 3.0 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkSpeed( list, 0.2 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendJumpAbs2D( list, -10000, 2000 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendMarkCounter( list, counterName, 3 ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendIncrementCounter( list, counterName ) ) != rlSUCCESS ) return result;
	if ( ( result = rlListAppendLaserOff( list ) ) != rlSUCCESS ) return result;

	int32_t counter;
	if ( ( result = rlVariableMarkCounterGetValue( handle, counterName, &counter ) ) != rlSUCCESS ) return result;
	printf( "Current mark counter value: %d\n", counter );

	int listIndex = 0;

	// close the list causing its contents to be transferred to the card
	printf( "Closing list: index=%d...\n", listIndex );
	if ( ( result = rlListSet( handle, listIndex, list, false, -1 ) ) != rlSUCCESS ) return result;

	// run the list, and wait until its execution has completed
	printf( "Executing list: index=%d...\n", listIndex );
	if ( ( result = rlListExecute( handle, listIndex ) ) != rlSUCCESS ) return result;

	int timeoutMs = 30000;
	bool done = false;
	int32_t listID;
	printf( "Waiting until list execution is done: index=%d...\n", listIndex );
	if ( ( result = rlListWaitForListDone( handle, timeoutMs, &done, &listID ) ) != rlSUCCESS ) return result;
	if ( !done )
	{
		printf( "Timeout: execution has not completed after %d ms!", timeoutMs );
		return rlERROR;
	}
	printf( "Execution done: index=%d...\n", listIndex );

	// delete list on the card: this frees the card's memory occupied by the list
	printf( "Deleting list: index=%d...\n", listIndex );
	if ( ( result = rlListDelete( handle, listIndex, true ) ) != rlSUCCESS ) return result;

	// release the local list: this frees the PC's memory occupied by the card
	if ( ( result = rlListReleaseHandle( list ) ) != rlSUCCESS ) return result;

	return result;
}

// helper function which displays the description of the last error
static int printLastError( void )
{
	char errBuffer[1024] = { 0 };
	rlGetLastError( errBuffer, sizeof( errBuffer ) - 1 );
	printf( "%s", errBuffer );
	return rlERROR;
}
