using RAYLASE.SPICE3;
using RAYLASE.SPICE3.ClientLib;
using System;

namespace PartSensor
{
	class Program
	{
		// insert the IP of your SP-ICE-3
		readonly string _CardIp = "192.168.2.138";
		ClientAPI _Client = new ClientAPI();

		static void Main( string[] args )
		{
			Program p = new Program();

			p._Client.Connect( p._CardIp );
			// 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.)
			p._Client.System.ResetToDefaults();
			p._Client.Laser.ArmLaser( true );
			LaserConfig lc = p._Client.Laser.GetConfig();
			lc.PowerScale = 1.0;
			p._Client.Laser.SetConfig( lc );

			p.detectPartThenMark();
		}

		/// <summary>
		/// mark a rectangle, every time the part sensor is triggered
		/// </summary>
		void detectPartThenMark()
		{
			double jumpSpeed = 4;
			double markSpeed = 1;
			int listID = 13;

			ScannerConfig scanner = _Client.Scanner.GetConfig();

			double fieldSize = scanner.FieldSize.X;
			double sizeX = 0.1 * fieldSize;
			double sizeY = 0.2 * fieldSize;

			// remove comment for encoder simulation
			//_Client.Motf.SetSimulationSpeed( encoder, 0.005, 0 );
			//_Client.Motf.SimulateEncoder( encoder, true );

			int encoderID = 0;
			bool beltMovesPositive = true;
			int beltSign = beltMovesPositive ? 1 : -1;

			QuadratureDecoderConfig qd = new QuadratureDecoderConfig();
			qd.Modules[encoderID].InvertDirection = true;
			qd.Modules[encoderID].DistancePerCount = 36;
			_Client.Motf.QuadratureDecoder.SetConfig( qd );

			MotfConfig config = new MotfConfig();
			config.MainSource.SourceType = MotfSourceType.QuadratureDecoder;
			config.PartDistance = 10000;
			config.SetDirectionFromAngle( Math.PI / 2 + ( beltMovesPositive ? 0 : Math.PI ) );
			config.CompensationSource.SourceType = MotfSourceType.QuadratureDecoder;
			config.CompensationSource.ModuleID = ( encoderID + 1 ) % 2;
			// set debounce if the sensor is sending multiple signals
			config.EnableDebounce = true;
			config.DebounceTime = 200000;
			_Client.Motf.SetConfig( config );

			CommandList list = new CommandList();
			list.AppendJumpSpeed( jumpSpeed );
			list.AppendJumpDelay( 0 );
			list.AppendMarkSpeed( markSpeed );
			list.AppendPolyDelay( 0 );
			list.AppendMarkDelay( 0 );
			list.AppendLmFrequency( 1.0 / 200 );
			list.AppendLmWidth( 200 );
			list.AppendPower( 30000 );

			list.AppendJumpAbs( -beltSign * 0.45 * fieldSize, 0 );
			// wait for the part sensor
			list.AppendMotfWaitPart();
			list.AppendMarkRel( beltSign * sizeX, 0 );
			list.AppendMarkRel( 0, sizeY );
			list.AppendMarkRel( -beltSign * sizeX, 0 );
			list.AppendMarkRel( 0, -sizeY );
			list.AppendLaserOff();
			list.AppendStopMotf( 0, 0 );

			_Client.List.Set( listID, list );

			for ( int iteration = 0; iteration < 50; iteration++ )
			{
				Console.Out.WriteLine( "Iteration {0}: Executing...", iteration + 1 );
				_Client.List.Execute( listID );

				int? doneID;
				try
				{
					bool done = _Client.List.WaitForListDone( out doneID, 300000 );
					if ( !done )
						Console.Out.WriteLine( "List did not finish within the timeout period" );
				}
				catch ( TimeoutException )
				{
					if ( iteration == 0 )
						Console.Out.WriteLine( "Could not finish the list. Has the part sensor been triggered within the time limit?" );
					throw;
				}
			}
		}
	}
}
