//
//  UbuntuUSBCreatorAppDelegate.m
//  UbuntuUSBCreator
//
//  Created by Michael Forrest on 8 Mar 2010
//

#import "UbuntuUSBCreatorAppDelegate.h"
#import "NSTask_Extensions.h"


@implementation UbuntuUSBCreatorAppDelegate

@synthesize window;
@synthesize createButton;
@synthesize selectedIsoLabel;
@synthesize browseButton;
@synthesize targetDevice;
@synthesize progressTimer;
@synthesize ddTask;
@synthesize volumeName;
@synthesize progress;
@synthesize progressLabel;


#pragma mark Start Button
-(void) setStartButtonEnabled{
	[createButton setEnabled: [[selectedIsoLabel stringValue] hasSuffix:@".iso"] && [[targetDevice stringValue] hasPrefix:@"/Volumes/"]];
	// TODO: REMOVE THIS LINE:
	[createButton setEnabled:YES];
}

#pragma mark Volume Mounting Stuff
-(void) updateMountedDevicesList{
	[targetDevice reloadData];
	[targetDevice setStringValue:@"Please plug in a USB device"];
	[self setStartButtonEnabled];
	if([targetDevice numberOfItems] == 0) return;
	[targetDevice selectItemAtIndex:0];
	
}

- (void)volumeDidMount:(NSNotification *)notif
{
	NSLog(@"Volume mounted: %@", [[notif userInfo] valueForKey:@"NSDevicePath"]);
	[self updateMountedDevicesList];
}
- (void)volumeDidUnmount:(NSNotification *)notif
{
	NSLog(@"Volume unmounted: %@", [[notif userInfo] valueForKey:@"NSDevicePath"]);
	[self updateMountedDevicesList];
}


#pragma mark Start Application

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
	[self updateMountedDevicesList];
	
	NSWorkspace *sharedWorkspace = [NSWorkspace sharedWorkspace];
	[[sharedWorkspace notificationCenter] addObserver:self
																					 selector:@selector(volumeDidMount:)
																							 name:NSWorkspaceDidMountNotification object:nil];
	[[sharedWorkspace notificationCenter] addObserver:self
																					 selector:@selector(volumeDidUnmount:)
																							 name:NSWorkspaceDidUnmountNotification object:nil];
}

#pragma mark Find the ISO

-(IBAction) browseForISO:(id)sender{
	NSArray *fileTypes = [NSArray arrayWithObject:@"iso"];
	NSOpenPanel *oPanel = [NSOpenPanel openPanel];
	
	int result = [oPanel runModalForDirectory:NSHomeDirectory()
																	 file:nil types:fileTypes];
	if (result != NSOKButton) return;
	[selectedIsoLabel setStringValue: [oPanel filename]];
	[self setStartButtonEnabled];
}


#pragma mark Volumes Combo Box

- (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(NSInteger)index{
	return [[[NSWorkspace sharedWorkspace] mountedRemovableMedia] objectAtIndex:index];
}

- (NSInteger)numberOfItemsInComboBox:(NSComboBox *)aComboBox{
	return [[[NSWorkspace sharedWorkspace] mountedRemovableMedia] count];
}
/*
 Open the Terminal (in /Applications/Utilities/ or query Terminal in Spotlight)
 Convert the .iso file to .img using the convert option of hdiutil (e.g., hdiutil convert -format UDRW -o ~/path/to/target.img ~/path/to/kubuntu.iso) Note: OS X tends to put the .dmg ending on the output file automatically.
 Run diskutil list to get the current list of devices
 Insert your flash media
 Run diskutil list again and determine the device node assigned to your flash media (e.g. /dev/disk2)
 Run diskutil unmountDisk /dev/diskN (replace N with the disk number from the last command; in the previous example,N would be 2)
 Execute sudo dd if=/path/to/downloaded.img of=/dev/rdiskN bs=1m 
		Using /dev/rdisk instead of /dev/disk may be faster. If you see the error dd: Invalid number `1m', you are using GNU dd. Use the same command but replace bs=1m with bs=1M.
		If you see the error  dd: /dev/diskN: Resource busy  make sure the disk is not in use. Start the "Disk Utility.app" and unmount (not eject) the drive.
 Run diskutil eject /dev/diskN and remove your flash media when the command completes
 Restart you Mac and press alt while the Mac is restarting to choose the USB-Stick
 
 */
#pragma mark Burn Image
- (NSTask *) createTaskWritingImage:(NSString *)imagePath toDevice:(NSString *)devicePath
{	
	NSTask *task;
	
	task = [NSTask new];
	[task setLaunchPath:@"/bin/dd"];
	[task setArguments:[NSArray arrayWithObjects:[NSString stringWithFormat:@"if=%@", imagePath],
											[NSString stringWithFormat:@"of=%@", devicePath],
											[NSString stringWithFormat:@"bs=1m"],
											nil]];
	[task setStandardError: [NSPipe pipe]];
	return task;
}
-(void) disableFurtherInputAndShowProgress{
	[createButton setEnabled:NO];
	[progress setHidden:NO];
	[progressLabel setHidden:NO];
	[browseButton setEnabled:NO];
	[targetDevice setEnabled:NO];
	[selectedIsoLabel setTextColor:[NSColor lightGrayColor]];
	
}

-(IBAction) start:(id)sender{
	if([ddTask isRunning]) return;
	// TODO: run this convert command before anything else
	// hdiutil convert -format UDRW -o ~/path/to/target.img ~/path/to/lucid.iso
	
	
	// diskutil info /Volumes/Untitled | grep "Part Of Whole" >> "Part Of Whole:            disk1"
	deviceName = @"/dev/disk1"; // TODO: parse this out correctly
	
	volumeName = [targetDevice stringValue]; 

	// TODO: unmount mounted volume
	// diskutil unmountDisk /Volumes/Untitled
	
	NSString * pathToIso = @"/Users/michaelforrest/Desktop/lucid-desktop-amd64.img.dmg";
	isoFileSize = [[[[NSFileManager defaultManager] attributesOfItemAtPath:pathToIso error:nil] valueForKey:NSFileSize] intValue];
	[NSTask launchedTaskWithLaunchPath:@"/usr/sbin/diskutil" arguments:[NSArray arrayWithObjects:@"unmountDisk",volumeName,nil]];
	
	ddTask = [self createTaskWritingImage:pathToIso toDevice:deviceName];
	[ddTask launch];
		
	progressTimer = [NSTimer scheduledTimerWithTimeInterval:1
													target:self selector:@selector(onTimerProgress:)
													userInfo:nil repeats:YES];
	[self disableFurtherInputAndShowProgress];
}
static int lastTimerProgressCall;
static int lastNumberOfBytesLoaded;

- (void)onTimerProgress:(NSTimer*)theTimer{
	if(![ddTask isRunning]) return;
	
	NSPipe *ddOut = [ddTask standardError];

	[ddTask sendSignal:SIGINFO];
	/*
	 1585+0 records in
	 1584+0 records out
	 811008 bytes transferred in 30.134459 secs (26913 bytes/sec)
	 */
	NSString * progressString = [[NSString alloc] initWithData:[[ddOut fileHandleForReading] availableData] encoding:NSASCIIStringEncoding];
	NSArray * lines = [progressString componentsSeparatedByString:@"\n"];
	if([lines count] < 1) return; // Silent fail. But possibly should be an exception.
	NSString * lastLine = [lines objectAtIndex:[lines count] -2];
	NSInteger bytesLoaded;
	[[NSScanner scannerWithString:lastLine] scanInteger:&bytesLoaded];
	
	NSLog(@"Transferred %i / %i", bytesLoaded, isoFileSize  );
	[progress setDoubleValue:[[NSNumber numberWithInt:bytesLoaded] doubleValue] / [[NSNumber numberWithInt:isoFileSize] doubleValue]];
																													 
//	lastTimerProgressCall = [NSDate date];
//	lastNumberOfBytesLoaded = bytesLoaded;
	
}

#pragma mark Quit
-(BOOL) askIfShouldQuit{
	NSAlert *alert = [[[NSAlert alloc] init] autorelease];
	[alert addButtonWithTitle:@"Quit"];
	[alert addButtonWithTitle:@"Cancel"];
	[alert setMessageText:@"Cancel writing image?"];
	[alert setInformativeText:@"You will probably need to reformat the volume."];
	[alert setAlertStyle:NSWarningAlertStyle];
	
	return [alert runModal] == NSAlertDefaultReturn;
}
-(NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender{
	//if([self askIfShouldQuit]){
		// kill process
		NSLog(@"killing");
		if ([ddTask isRunning]) {
			[ddTask terminate];
			//[NSTask launchedTaskWithLaunchPath:@"" arguments:[NSArray arrayWithObjects:nil]];
		}
		return NSTerminateNow;
	//}
	//return NSTerminateCancel;
}

#pragma mark Deallocation

- (void) dealloc {

	[progressTimer release];
	[ddTask release];
	[progressLabel release];

	[progress release];
	[volumeName release];
	[createButton release];
	[selectedIsoLabel release];
	[browseButton release];
	[targetDevice release];
	[super dealloc];
}


@end
