#import "AppController.h"

@implementation AppController

-(void)awakeFromNib
{
	[self startDiscovery:self];
	[self startServer:self];
	
	[self willChangeValueForKey:@"statusMessage"];
	statusMessage = @"Please press 1 button and 2 button simultaneously to connect Wiimote.";
	[self didChangeValueForKey:@"statusMessage"];
	
	packet = [[WiiFlashPacket alloc] init];
	isWriting = NO;
	timer = [NSTimer scheduledTimerWithTimeInterval:1.0	target:self selector:@selector(getCalibData:) userInfo:nil repeats:YES];
}

- (IBAction)startDiscovery:(id)sender
{
	discovery = [[WiiRemoteDiscovery alloc] init];
	[discovery setDelegate:self];
	[discovery start];
}

- (IBAction)startServer:(id)sender
{
	AsyncSocket *sock = [[AsyncSocket alloc] initWithDelegate:self];
	NSError *err = nil;
	[sock acceptOnPort:19028 error:&err];
}

- (void)sendWiimoteStatus:(NSTimer *)aTimer {
	AsyncSocket *sock = [aTimer userInfo];
	NSLog(@"sendWiimoteStatus: %d", [sock isConnected]);
	if ([sock isConnected] && !isWriting) {
		isWriting = YES;
		[sock writeData:[packet currentStateAsData] withTimeout:-1 tag:0xff];
	}
}

- (void)getCalibData:(NSTimer *)aTimer {
	if ([wii available]) {
		WiiAccCalibData calibData = [wii accCalibData:WiiRemoteAccelerationSensor];
		if (calibData.accX_1g > 0) {
			[timer invalidate];
			[packet setCalibData:calibData forType:WiiRemoteAccelerationSensor];
			NSLog(@"%u, %u, %u, %u, %u, %u",
				calibData.accX_zero, calibData.accY_zero, calibData.accZ_zero, calibData.accX_1g, calibData.accY_1g, calibData.accZ_1g);
		}
	}
}


#pragma mark -
#pragma mark AsyncSocket Delegate

-(void) onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket
{
	NSLog(@"onSocket:didAcceptNewSocket");
}

-(void) onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
{
	NSLog(@"onSocket:didConnectToHost");
	socket = [sock retain];
	[sock readDataWithTimeout:-1 tag:0];
}

-(void) onSocket:(AsyncSocket *)sock didReadData:(NSData*)data withTag:(long)tag
{
	NSLog(@"onSocket:didReadData:%d", [data length]);
	char *ptr = (char *)[data bytes];
	
	
	int n = [data length];
	int i;
	for (i=0; i<n; i++) {
		//NSLog(@"0x%02x", *(ptr + i));
	}

	switch (ptr[1]) {
		case 0x6c:
			[wii setLEDEnabled1:ptr[2] & 0x01 enabled2:ptr[2] & 0x02 enabled3:ptr[2] & 0x04 enabled4:ptr[2] & 0x08];
			break;
	}



	//[sock writeData:data withTimeout:-1 tag:0];
	[sock readDataWithTimeout:-1 tag:0];
}

-(void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag
{
	NSLog(@"onSocket:didWriteDataWithTag: 0x%02x", tag);
	isWriting = NO;
}

-(void) onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err
{
	[socket release];
	socket = nil;
	if (err != nil)
		NSLog (@"Socket will disconnect. Error domain %@, code %d (%@).",
			   [err domain], [err code], [err localizedDescription]);
	else
		NSLog (@"Socket will disconnect. No error.");
}


#pragma mark -
#pragma mark WiiRemoteDiscovery Delegate

- (void) WiiRemoteDiscovered:(WiiRemote*)wiimote {
	wii = wiimote;
	[wii setDelegate:self];
	NSLog(@"===== Connected to WiiRemote =====");
	NSLog(@"%d", [self respondsToSelector:@selector(dumpCalibData:)]);

	//[wii setLEDEnabled1:YES enabled2:NO enabled3:YES enabled4:NO];
	[wii setLEDEnabled1:NO enabled2:NO enabled3:NO enabled4:NO];
	[wii setMotionSensorEnabled:YES];
	[wii setIRSensorEnabled:YES];

//	[wii setIRSensorEnabled:YES];
	[discovery stop];

	[self willChangeValueForKey:@"statusMessage"];
	statusMessage = @"Successfully connected!";
	[self didChangeValueForKey:@"statusMessage"];
}

- (void) WiiRemoteDiscoveryError:(int)code {
	NSLog(@"%@", [NSString stringWithFormat:@"===== WiiRemoteDiscovery error (%d) =====", code]);
}

- (void) wiiRemoteDisconnected:(IOBluetoothDevice*)device {
	[wii release];
	wii = nil;
	[discovery start];
}


#pragma mark -
#pragma mark WiiRemote Delegate

- (void) buttonChanged:(WiiButtonType)type isPressed:(BOOL)isPressed wiiRemote:(WiiRemote*)wiiRemote
{
	NSLog(@"buttonChanged: %02X(%02x) %@", type, table[type], isPressed ? @"pressed" : @"released");
	[packet setButtonState:type isPressed:isPressed];
	if ([socket isConnected]) {
		[socket writeData:[packet currentStateAsData] withTimeout:-1 tag:0];
	}
	
	switch (type) {
		case WiiRemoteAButton:
			[self willChangeValueForKey:@"buttonAPressed"];
			buttonAPressed = isPressed;
			[self didChangeValueForKey:@"buttonAPressed"];
			break;
		
		case WiiRemoteBButton:
			[self willChangeValueForKey:@"buttonBPressed"];
			buttonBPressed = isPressed;
			[self didChangeValueForKey:@"buttonBPressed"];
			break;

		case WiiRemoteOneButton:
			[self willChangeValueForKey:@"button1Pressed"];
			button1Pressed = isPressed;
			[self didChangeValueForKey:@"button1Pressed"];
			break;
		
		case WiiRemoteTwoButton:
			[self willChangeValueForKey:@"button2Pressed"];
			button2Pressed = isPressed;
			[self didChangeValueForKey:@"button2Pressed"];
			break;
		
		case WiiRemoteMinusButton:
			[self willChangeValueForKey:@"buttonMinusPressed"];
			buttonMinusPressed = isPressed;
			[self didChangeValueForKey:@"buttonMinusPressed"];
			break;
		
		case WiiRemoteHomeButton:
			[self willChangeValueForKey:@"buttonHomePressed"];
			buttonHomePressed = isPressed;
			[self didChangeValueForKey:@"buttonHomePressed"];
			break;
		
		case WiiRemotePlusButton:
			[self willChangeValueForKey:@"buttonPlusPressed"];
			buttonPlusPressed = isPressed;
			[self didChangeValueForKey:@"buttonPlusPressed"];
			break;
		
		case WiiRemoteUpButton:
			[self willChangeValueForKey:@"buttonUpPressed"];
			buttonUpPressed = isPressed;
			[self didChangeValueForKey:@"buttonUpPressed"];
			break;
		
		case WiiRemoteDownButton:
			[self willChangeValueForKey:@"buttonDownPressed"];
			buttonDownPressed = isPressed;
			[self didChangeValueForKey:@"buttonDownPressed"];
			break;
		
		case WiiRemoteLeftButton:
			[self willChangeValueForKey:@"buttonLeftPressed"];
			buttonLeftPressed = isPressed;
			[self didChangeValueForKey:@"buttonLeftPressed"];
			break;
		
		case WiiRemoteRightButton:
			[self willChangeValueForKey:@"buttonRightPressed"];
			buttonRightPressed = isPressed;
			[self didChangeValueForKey:@"buttonRightPressed"];
			break;
		
	}
}

- (void) accelerationChanged:(WiiAccelerationSensorType)type accX:(unsigned char)accX accY:(unsigned char)accY accZ:(unsigned char)accZ wiiRemote:(WiiRemote*)wiiRemote
{
	//NSLog(@"accelerationChanged: x:%u, y:%u, z:%u", accX, accY, accZ);
	[packet setAcceleration:type accX:accX accY:accY accZ:accZ];
	if ([socket isConnected]) {
		[socket writeData:[packet currentStateAsData] withTimeout:-1 tag:0];
	}

	[self willChangeValueForKey:@"accelerationX"];
	accelerationX = accX;
	[self didChangeValueForKey:@"accelerationX"];
	
	[self willChangeValueForKey:@"accelerationY"];
	accelerationY = accY;
	[self didChangeValueForKey:@"accelerationY"];

	[self willChangeValueForKey:@"accelerationZ"];
	accelerationZ = accZ;
	[self didChangeValueForKey:@"accelerationZ"];
}

- (void) irPointMovedX:(float)px Y:(float)py wiiRemote:(WiiRemote*)wiiRemote
{
	//NSLog(@"irPointMovedX: %.2f,%.2f", px, py);
}

- (void) rawIRData: (IRData[4])irData wiiRemote:(WiiRemote*)wiiRemote
{
	[packet setIRRawData:irData];
	if ([socket isConnected]) {
		[socket writeData:[packet currentStateAsData] withTimeout:-1 tag:0];
	}
	[irView drawSensor:irData];
}


#pragma mark -
#pragma mark Binding



#pragma mark -
#pragma mark Application Deleagte

- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication
{
	return YES;
}

- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{
	[wii setDelegate:nil];
	[wii closeConnection];
	[wii release];
	
	return NSTerminateNow;
}

@end
