//  MainViewController.m
//  Created by Barry Peyton on 12-02-05.
//  Copyright 2012 University of Alberta. All rights reserved.

#import "MainViewController.h"

@implementation MainViewController
@synthesize labelX,labelY,labelZ,progressY,velocityValue,directionValue,iStream,oStream;
@synthesize sliderCtl,segControl,accelerometer,result1, result2, result3;

- (void)viewDidLoad {
     
    //create accelerometer object
    self.accelerometer = [UIAccelerometer sharedAccelerometer];
    self.accelerometer.updateInterval = 0.1;
    self.accelerometer.delegate = self;

    //create segmented control object
    self.segControl = [[UISegmentedControl alloc] init];
    [segControl addTarget:self action:@selector(segmentedControlIndexChanged:) forControlEvents:UIControlEventValueChanged];

    //Set Default Direction to be Forward on Startup
    direction = TRUE;

    //Set Default Velocity to be 0
    [self.sliderCtl setValue:0.0];
    
    [super viewDidLoad];
}
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
    
    //Display Accelerometer Data on Screen
    self.labelY.text = [NSString stringWithFormat:@"%@%f", @"Y: ", acceleration.y];
    
    //Determine Direction Label (Left or Right)
    if (acceleration.y > 0) {
        self.labelZ.text = [NSString stringWithFormat:@"%@", @"Left"];
    } else if (acceleration.y < 0){
        self.labelZ.text = [NSString stringWithFormat:@"%@", @"Right"];
    }
    
    //Update Progress Bar & Rotate
    CGAffineTransform trans = CGAffineTransformMakeRotation(M_PI * 0.5 * -1);
    CGRect frame = CGRectMake(0.0, 50.0, 7.0, 20.0);
    self.sliderCtl.transform = trans;
    
    //Create Slider Speed Controller
    if (sliderCtl == nil) {
        self.sliderCtl = [[UISlider alloc] initWithFrame:frame];
        [self.sliderCtl addTarget:self action:@selector(sliderChanged:) forControlEvents:UIControlEventValueChanged];
        self.sliderCtl.backgroundColor = [UIColor clearColor];
        self.sliderCtl.minimumValue = 0.0;
        self.sliderCtl.maximumValue = 50.0;
        self.sliderCtl.continuous = YES;
    }
    
    //Update Progress Bar to Direction Value
    self.progressY.progress = ABS(acceleration.y);
    
    //Control Logic for Steering and Motor Commands
    // a    b   c   d   e   f  g   h   i   j   k   l   m     n    o   p   q   r   s  t   u   v   w   x   y  z   /////
    //N/A  -5  -4  -3  -2  -1  0   1   2   3   4   5  N/A   N/A  -5  -4  -3  -2  -1  0   1   2   3   4   5  N/A /////
    /////--------LEFT----------N-------RIGHT-------------------------REVERSE---------N------FORWARD------------//////
    
    if(running){
        
        //
        float roundedSteering = ((int)(acceleration.y * 100 + .5) / 100.0);
        roundedSteering = roundf(10 * roundedSteering) / 10;
        roundedSteering = roundedSteering*10;
        int steering = (int) roundedSteering;
        
        //Set Steering Command
        if (steering < 2 && steering >-2){
            directionValue = [NSString stringWithFormat:@"g"];
        }else if (steering >= 2 && steering < 3){
            directionValue = [NSString stringWithFormat:@"f"];
        }else if (steering >= 3 && steering < 4){
            directionValue = [NSString stringWithFormat:@"e"];
        }else if (steering >= 4 && steering < 5){
            directionValue = [NSString stringWithFormat:@"d"];
        }else if (steering >= 5 && steering < 6){
            directionValue = [NSString stringWithFormat:@"c"];
        }else if (steering >= 6 && steering < 7){
            directionValue = [NSString stringWithFormat:@"b"];
        }else if (steering <= -2 && steering > -3){
            directionValue = [NSString stringWithFormat:@"h"];
        }else if (steering <= -3 && steering > -4){
            directionValue = [NSString stringWithFormat:@"i"];
        }else if (steering <= -4 && steering > -5){
            directionValue = [NSString stringWithFormat:@"j"];
        }else if (steering <= -5 && steering > -6){
            directionValue = [NSString stringWithFormat:@"k"];
        }else if (steering <= -6 && steering > -7){
            directionValue = [NSString stringWithFormat:@"l"];
        }
        
        int velocity = self.sliderCtl.value + 0.5f;
        
        //Forward Operation
        if(direction){
            if (velocity == 0){
                //Send Motor Neutral
                velocityValue = [NSString stringWithFormat:@"t"];
            }else if (velocity <= 10 && velocity > 0){
                velocityValue = [NSString stringWithFormat:@"u"];
            }else if (velocity > 10 && velocity <= 20){
                velocityValue = [NSString stringWithFormat:@"v"];
            }else if (velocity > 20 && velocity <= 30){
                velocityValue = [NSString stringWithFormat:@"w"];
            }else if (velocity > 30 && velocity <= 40){
                velocityValue = [NSString stringWithFormat:@"x"];
            }else if (velocity > 40 && velocity <= 50){
                velocityValue = [NSString stringWithFormat:@"y"];
            }
        }//Reverse Operation
        else if(!direction){
            if (velocity == 0){
                //Send Motor Neutral
                velocityValue = [NSString stringWithFormat:@"t"];
            }else if (velocity <= 10 && velocity > 0){
                velocityValue = [NSString stringWithFormat:@"s"];
            }else if (velocity > 10 && velocity <= 20){
                velocityValue = [NSString stringWithFormat:@"r"];
            }else if (velocity > 20 && velocity <= 30){
                velocityValue = [NSString stringWithFormat:@"q"];
            }else if (velocity > 30 && velocity <= 40){
                velocityValue = [NSString stringWithFormat:@"p"];
            }else if (velocity > 40 && velocity <= 50){
                velocityValue = [NSString stringWithFormat:@"o"];
            }
        }
        
        //Send Command String via TCP Connection
        result1 = [self sendText:self withValue:@"^"];
        NSLog(@"Result is:%@", result1);
        result2 = [self sendText:self withValue:directionValue];
        NSLog(@"Result is:%@", result2);
        result3 = [self sendText:self withValue:velocityValue];
        NSLog(@"Result is:%@", result3);
    }
}

- (void)sliderChanged:(id)sender{
    //if slider value changes update label
    int velocity = self.sliderCtl.value + 0.5f;
    self.labelX.text = [NSString stringWithFormat:@"%@%d", @"Current Speed: ", velocity];
}

-(void) segmentedControlIndexChanged:(id)sender{
    //if segment control changes negate acceleration to invoke reverse
    
    self.sliderCtl.value = 0;
    int velocity = self.sliderCtl.value;
    self.labelX.text = [NSString stringWithFormat:@"%@%d", @"Current Speed: ", velocity];
    
    switch (((UISegmentedControl*) sender).selectedSegmentIndex) {
        case 0:
            NSLog(@"Segment Value is Forward");
            direction = TRUE;
            break;
        case 1:
            NSLog(@"Segment Value is Reverse");
            direction = FALSE;
            //Account for Switching into Reverse with ESC issue we resolved
            //Send Command String via TCP Connection
            result1 = [self sendText:self withValue:@"^"];
            NSLog(@"Result is:%@", result1);
            result2 = [self sendText:self withValue:directionValue];
            NSLog(@"Result is:%@", result2);
            result3 = [self sendText:self withValue:@"s"];
            NSLog(@"Result is:%@", result3);
            //Send Command String via TCP Connection
            result1 = [self sendText:self withValue:@"^"];
            NSLog(@"Result is:%@", result1);
            result2 = [self sendText:self withValue:directionValue];
            NSLog(@"Result is:%@", result2);
            result3 = [self sendText:self withValue:@"t"];
            NSLog(@"Result is:%@", result3);
            break;
        default:
            break;
    }
}

-(void) connect {
    //Close TCP/IP Connection
    //Create read & write stream and set IP Address and Port parameters
    CFReadStreamRef readStream = NULL;
    CFWriteStreamRef writeStream = NULL;
    CFStringRef host = CFSTR("169.254.1.1");
    UInt32 port = 2000;
    
    //Create Socket Connection with given HOST Address
    CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, host, port, &readStream, &writeStream);
    if (readStream && writeStream) {
        CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
        CFWriteStreamSetProperty(writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
        
        iStream = (__bridge NSInputStream *)readStream;
        [iStream setDelegate:self];
        [iStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        [iStream open];
        
        oStream = (__bridge NSOutputStream *)writeStream;
        [oStream setDelegate:self];
        [oStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        [oStream open];         
    }
    if (readStream) CFRelease(readStream);
    if (writeStream) CFRelease(writeStream);
    
    //Start sending data 
    running = TRUE;
}

-(void) disconnect {
    //Close TCP/IP Connection
	[iStream close];
    [oStream close];
    [iStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [oStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [iStream setDelegate:nil];
    [oStream setDelegate:nil];
    iStream = nil;
    oStream = nil;
    //Stop Sending Data
    running = FALSE;
}

- (IBAction)connectCommand:(id)sender {
	if( iStream != nil ) return;
	[self connect];
}

- (IBAction) disconnectCommand: (id) sender {
	if( iStream == nil ) return;
	[self disconnect];
}


- (NSString *)sendText:(id)sender withValue: (NSString *) value {
    //Encode Data to be sent
    NSData * dataToSend = [value dataUsingEncoding:NSASCIIStringEncoding];
    
    //If an output stream exists send data until the value is empty
    if (oStream) {
        int remainingToWrite = [dataToSend length];
        NSLog(@"Length of data: %d", remainingToWrite);
        void * marker = (void *)[dataToSend bytes];
        while (0 < remainingToWrite) {
            int actuallyWritten = 0;
            actuallyWritten = [oStream write:marker maxLength:remainingToWrite];
            remainingToWrite -= actuallyWritten;
            marker += actuallyWritten;
        }
    }
    return value;
    
}

- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent
{
    
    //Handle Events in regards to Stream Issues
	NSString *io;
	if (theStream == iStream) io = @">>";
	else io = @"<<";
	
	NSString *event;
	switch (streamEvent)
	{
		case NSStreamEventNone:
			event = @"NSStreamEventNone - Can not connect to the host!";
			break;
		case NSStreamEventOpenCompleted:
			event = @"NSStreamEventOpenCompleted";
			break;
		case NSStreamEventHasBytesAvailable:
			event = @"NSStreamEventHasBytesAvailable";
			if (theStream == iStream)
			{
				//read data
				uint8_t buffer[1024];
				int len;
				while ([iStream hasBytesAvailable])
				{
					len = [iStream read:buffer maxLength:sizeof(buffer)];
					if (len > 0)
					{
						NSString *input = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];
						if (nil != input)
						{
							//do something with data
							NSLog(@"%@",input);
						}
					}
				}
			}
			break;
		case NSStreamEventHasSpaceAvailable:
			event = @"NSStreamEventHasSpaceAvailable";
			break;
		case NSStreamEventErrorOccurred:
			event = @"NSStreamEventErrorOccurred";
			break;
		case NSStreamEventEndEncountered:
			event = @"NSStreamEventEndEncountered";
			[self disconnect];
			break;
		default:
			event = @"** Unknown";
	}
	
	NSLog(@"%@ : %@", io, event);
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    //allow application to not rotate and be locked in one orientation
    if (interfaceOrientation == UIInterfaceOrientationLandscapeRight){
        return YES;
    }else {
        return NO;
    }
    
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

- (void)viewDidUnload {
    self.labelX = nil;
    self.labelY = nil;
    self.labelZ = nil;
    self.progressY = nil;
    self.sliderCtl = nil;
    self.segControl = nil;
    self.accelerometer = nil;
}

@end
