#import "PhidgetStepperController.h"

CPhidgetStepperHandle stepper;
int globalIndex = 0;

int accelMultiplier = 1;
int velMultiplier = 1;
int microSteps = 1;

struct stepperInfo
{
	int positionTrackBar;
	long long positionBox;
	double velocityTrackBar;
	double accelerationTrackBar;
};

struct stepperInfo steppers[8];

@implementation PhidgetStepperController

- (IBAction)setAcceleration:(id)sender
{
	CPhidgetStepper_setAcceleration(stepper, globalIndex, [sender doubleValue]);
	[accelerationSetField setTitleWithMnemonic:[NSString stringWithFormat:@"%d", [sender intValue]]];
}

- (IBAction)setPosition:(id)sender
{
	CPhidgetStepper_setMotorPosition(stepper, globalIndex, (long long)[sender intValue]);
	[positionSetTextBox setTitleWithMnemonic:[NSString stringWithFormat:@"%d", [sender intValue]]];
}

- (IBAction)setPositionBox:(id)sender
{
	long long posn;
	const char *posnString = [[sender stringValue] UTF8String];
	posn = strtoll(posnString, NULL, 10);
	CPhidgetStepper_setMotorPosition(stepper, globalIndex, posn);
}

- (IBAction)setStepper:(id)sender
{
	const char *stepperString = [[sender stringValue] UTF8String];
	[self fillInfo:globalIndex];
	globalIndex = strtol(stepperString+8, NULL, 10);
	[self fillForm:globalIndex];
}

- (IBAction)setVelocity:(id)sender
{
	CPhidgetStepper_setMotorSpeed(stepper, globalIndex, [sender doubleValue]);
	[velocitySetField setTitleWithMnemonic:[NSString stringWithFormat:@"%d", [sender intValue]]];
}

- (IBAction)setTorque:(id)sender
{
	CPhidgetStepper_setTorque(stepper, globalIndex, [sender doubleValue]);
	[torqueSetField setTitleWithMnemonic:[sender stringValue]];
}

int gotPositionChange(CPhidgetStepperHandle phid, void *context, int ind, long long val) {
	[(id)context PositionChange:ind:val];
	return 0;
}

int gotSpeedChange(CPhidgetStepperHandle phid, void *context, int ind, double val) {
	[(id)context SpeedChange:ind:val];
	return 0;
}

int gotCurrentChange(CPhidgetStepperHandle phid, void *context, int ind, double val) {
	[(id)context CurrentChange:ind:val];
	return 0;
}

int gotInputChange(CPhidgetStepperHandle phid, void *context, int ind, int val) {
	[(id)context InputChange:ind:val];
	return 0;
}

int gotAttach(CPhidgetHandle phid, void *context) {
	[(id)context phidgetAdded];
	return 0;
}

int gotDetach(CPhidgetHandle phid, void *context) {
	[(id)context phidgetRemoved];
	return 0;
}

- (void)phidgetAdded
{
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	int serial, version;
	const char *name;
	int numInputs, numSteppers;
	int i;
	
	CPhidget_getSerialNumber((CPhidgetHandle)stepper, &serial);
	CPhidget_getDeviceVersion((CPhidgetHandle)stepper, &version);
	CPhidget_getDeviceName((CPhidgetHandle)stepper, &name);
	CPhidgetStepper_getNumInputs(stepper, &numInputs);
	CPhidgetStepper_getNumMotors(stepper, &numSteppers);
	
	[connectedField setTitleWithMnemonic:[NSString stringWithCString:name]];
	[serialField setTitleWithMnemonic:[NSString stringWithFormat:@"%d", serial]];
	[versionField setTitleWithMnemonic:[NSString stringWithFormat:@"%d", version]];
	[numberOfInputsField setTitleWithMnemonic:[NSString stringWithFormat:@"%d", numInputs]];
	[numberOfSteppersField setTitleWithMnemonic:[NSString stringWithFormat:@"%d", numSteppers]];
	
	if(!strncmp(name+8,"Bipolar",7))
	{
		accelMultiplier = 100;
		velMultiplier=4;
		microSteps = 16;
	}
	else if(!strncmp(name+8,"Unipolar",8))
	{
		accelMultiplier = 50;
		velMultiplier=1;
		microSteps = 2;
	}
	
	[positionTrackBar setMaxValue:2500*microSteps];
	[positionTrackBar setMinValue:-2500*microSteps];
	//[positionSetTrackBar setMaxValue:64];
	//[positionSetTrackBar setMinValue:-64];
	[positionSetTrackBar setMaxValue:2500*microSteps];
	[positionSetTrackBar setMinValue:-2500*microSteps];
	[velocityTrackBar setMaxValue:255*velMultiplier];
	[velocityTrackBar setMinValue:-255*velMultiplier];
	[velocitySetTrackBar setMaxValue:255*velMultiplier];
	[accelerationSetTrackBar setMaxValue:63*accelMultiplier];
	
	for(i=0;i<numSteppers;i++)
	{
		CPhidgetStepper_setMotorPosition(stepper, i, 0);
		CPhidgetStepper_setAcceleration(stepper, i, 10*accelMultiplier);
		CPhidgetStepper_setMotorSpeed(stepper, i, 25*velMultiplier);

		steppers[i].positionBox = 0;
		steppers[i].positionTrackBar = 0;
		steppers[i].velocityTrackBar = 25*velMultiplier;
		steppers[i].accelerationTrackBar = 10*accelMultiplier;	}

	[self fillForm:0];

	[pool release];
}

- (void)fillInfo:(int)index
{
	const char *posnString = [[positionSetTextBox stringValue] UTF8String];
	steppers[index].positionBox = strtoll(posnString, NULL, 10);
	steppers[index].positionTrackBar = [positionSetTrackBar intValue];
	steppers[index].velocityTrackBar = [velocitySetTrackBar doubleValue];
	steppers[index].accelerationTrackBar = [accelerationSetTrackBar doubleValue];
}

- (void)fillForm:(int)index
{
	long long posn;
	double velocity;
	[velocitySetField setTitleWithMnemonic:[NSString stringWithFormat:@"%lf", steppers[index].velocityTrackBar]];
	[velocitySetTrackBar setDoubleValue:steppers[index].velocityTrackBar];
	[accelerationSetField setTitleWithMnemonic:[NSString stringWithFormat:@"%lf", steppers[index].accelerationTrackBar]];
	[accelerationSetTrackBar setDoubleValue:steppers[index].accelerationTrackBar];
	[positionSetTextBox setTitleWithMnemonic:[NSString stringWithFormat:@"%lld", steppers[index].positionBox]];
	[positionSetTrackBar setIntValue:steppers[index].positionTrackBar];
	
	CPhidgetStepper_getMotorSpeed(stepper, index, &velocity);
	CPhidgetStepper_getMotorPosition(stepper, index, &posn);
	
	velocity*=velMultiplier;
	
	[positionField setTitleWithMnemonic:[NSString stringWithFormat:@"%lld", posn]];
	[positionTrackBar setIntValue:(int)posn];
	[velocityField setTitleWithMnemonic:[NSString stringWithFormat:@"%lf", velocity]];
	[velocityTrackBar setDoubleValue:velocity];
}

- (void)phidgetRemoved
{
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	
	[connectedField setTitleWithMnemonic:@"Nothing"];
	[serialField setTitleWithMnemonic:@""];
	[versionField setTitleWithMnemonic:@""];
	[numberOfInputsField setTitleWithMnemonic:@""];
	[numberOfSteppersField setTitleWithMnemonic:@""];

	[pool release];
}

- (void)PositionChange:(int)Index:(long long)posn
{
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	if(globalIndex == Index) {
		[positionField setTitleWithMnemonic:[NSString stringWithFormat:@"%lld", posn]];
		[positionTrackBar setIntValue:(int)posn];
	}
	[pool release];
}

- (void)SpeedChange:(int)Index:(double)speed
{
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	if(globalIndex == Index) {
		[velocityField setTitleWithMnemonic:[NSString stringWithFormat:@"%0.1lf", speed]];
		[velocityTrackBar setDoubleValue:speed];
	}
	[pool release];
}

- (void)CurrentChange:(int)Index:(double)current
{
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	if(globalIndex == Index) {
		[currentField setTitleWithMnemonic:[NSString stringWithFormat:@"%lf", current]];
		[currentTrackBar setDoubleValue:current];
	}
	[pool release];
}

- (void)InputChange:(int)Index:(int)State
{
	[[inputs cellWithTag:Index] setState:State];
}

/*
* This gets run when the GUI gets displayed
*/
- (void)awakeFromNib
{
	int serial = -1;
	NSArray *args = [[NSProcessInfo processInfo] arguments];
	if([args count] > 1)
	{
		NSString *serialString = [args objectAtIndex:1];
		serial = strtol([serialString UTF8String], NULL, 10);
		if(serial == 0) serial = -1;
	}
	
	[mainWindow setDelegate:self];
	
	CPhidgetStepper_create(&stepper);
	
	CPhidget_set_OnAttach_Handler((CPhidgetHandle)stepper, gotAttach, self);
	CPhidget_set_OnDetach_Handler((CPhidgetHandle)stepper, gotDetach, self);
	CPhidgetStepper_set_OnPositionChange_Handler(stepper, gotPositionChange, self);
	CPhidgetStepper_set_OnSpeedChange_Handler(stepper, gotSpeedChange, self);
	CPhidgetStepper_set_OnCurrentChange_Handler(stepper, gotCurrentChange, self);
	CPhidgetStepper_set_OnInputChange_Handler(stepper, gotInputChange, self);
	
	CPhidget_open((CPhidgetHandle)stepper, serial);
}

- (void)windowWillClose:(NSNotification *)aNotification {
	CPhidget_close((CPhidgetHandle)stepper);
	CPhidget_delete((CPhidgetHandle)stepper);
	stepper = NULL;
	[NSApp terminate:self];
}
@end
