//
//  MGMSFTPPlugIn.m
//  CocoaShare
//
//  Created by Mr. Gecko on 1/26/11.
//  Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
//

#import "MGMSFTPPlugIn.h"
#import "MGMController.h"
#import "MGMAddons.h"

NSString * const MGMCopyright = @"Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/";

NSString * const MGMSFTPHost = @"MGMSFTPHost";
NSString * const MGMSFTPUser = @"MGMSFTPUser";
NSString * const MGMSFTPPath = @"MGMSFTPPath";
NSString * const MGMSFTPURL = @"MGMSFTPURL";

@implementation MGMSFTPPlugIn
- (void)dealloc {
	[self releaseView];
	[filePath release];
	[fileName release];
	[SFTPTask terminate];
	[SFTPTask release];
	[[NSNotificationCenter defaultCenter] removeObserver:self];
	[SFTPPipe release];
	[SFTPInputPipe release];
	[super dealloc];
}

- (BOOL)isAccountPlugIn {
	return YES;
}
- (NSString *)plugInName {
	return @"SFTP (SSH)";
}
- (NSView *)plugInView {
	if (view==nil) {
		if (![NSBundle loadNibNamed:@"SFTPAccountPane" owner:self]) {
			NSLog(@"Unable to load SFTP Account Pane");
		} else {
			NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
			NSString *host = [defaults objectForKey:MGMSFTPHost];
			if (host!=nil)
				[hostField setStringValue:host];
			NSString *user = [defaults objectForKey:MGMSFTPUser];
			if (user!=nil)
				[userField setStringValue:user];
			NSString *password = [[MGMController sharedController] password];
			if (password!=nil)
				[passwordField setStringValue:password];
			NSString *path = [defaults objectForKey:MGMSFTPPath];
			if (path!=nil)
				[pathField setStringValue:path];
			NSString *url = [defaults objectForKey:MGMSFTPURL];
			if (url!=nil)
				[urlField setStringValue:url];
		}
	}
	return view;
}
- (void)releaseView {
	[view release];
	view = nil;
	hostField = nil;
	userField = nil;
	passwordField = nil;
	pathField = nil;
	urlField = nil;
	loginButton = nil;
}

- (void)setCurrentPlugIn:(BOOL)isCurrent {
	if (!isCurrent) {
		NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
		[defaults removeObjectForKey:MGMSFTPHost];
		[defaults removeObjectForKey:MGMSFTPUser];
		[defaults removeObjectForKey:MGMSFTPPath];
		[defaults removeObjectForKey:MGMSFTPURL];
	}
}

- (void)lockLogin {
	[hostField setEnabled:NO];
	[userField setEnabled:NO];
	[passwordField setEnabled:NO];
	[pathField setEnabled:NO];
	[urlField setEnabled:NO];
	[loginButton setEnabled:NO];
	[loginButton setTitle:[@"Logging In" localizedFor:self]];
}
- (void)unlockLogin {
	[hostField setEnabled:YES];
	[userField setEnabled:YES];
	[passwordField setEnabled:YES];
	[pathField setEnabled:YES];
	[urlField setEnabled:YES];
	[loginButton setEnabled:YES];
	[loginButton setTitle:[@"Login" localizedFor:self]];
}
- (IBAction)login:(id)sender {
	if ([[hostField stringValue] isEqual:@""]) {
		NSAlert *alert = [[NSAlert new] autorelease];
		[alert setMessageText:[@"Host Required" localizedFor:self]];
		[alert setInformativeText:[@"Please enter your sftp host." localizedFor:self]];
		[alert runModal];
	} else if ([[userField stringValue] isEqual:@""]) {
		NSAlert *alert = [[NSAlert new] autorelease];
		[alert setMessageText:[@"UserName Required" localizedFor:self]];
		[alert setInformativeText:[@"Please enter your sftp username." localizedFor:self]];
		[alert runModal];
	} else if ([[urlField stringValue] isEqual:@""]) {
		NSAlert *alert = [[NSAlert new] autorelease];
		[alert setMessageText:[@"URL Required" localizedFor:self]];
		[alert setInformativeText:[@"Please enter the URL to where the files will be uploaded." localizedFor:self]];
		[alert runModal];
	} else {
		NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
		[[MGMController sharedController] setPassword:[passwordField stringValue]];
		[defaults setObject:[hostField stringValue] forKey:MGMSFTPHost];
		[defaults setObject:[[userField stringValue] replace:@"@" with:@"+"] forKey:MGMSFTPUser];
		[defaults setObject:[pathField stringValue] forKey:MGMSFTPPath];
		[defaults setObject:[urlField stringValue] forKey:MGMSFTPURL];
		[self lockLogin];
		
		SFTPTask = [NSTask new];
		[SFTPTask setLaunchPath:@"/usr/bin/ssh"];
		NSString *user = [defaults objectForKey:MGMSFTPUser];
		if (![[[MGMController sharedController] password] isEqual:@""])
			user = [user stringByAppendingFormat:@":%@", [[MGMController sharedController] password]];
		user = [user stringByAppendingFormat:@"@%@", [defaults objectForKey:MGMSFTPHost]];
		[SFTPTask setArguments:[NSArray arrayWithObjects:@"-v", user, nil]];
		
		SFTPPipe = [NSPipe new];
		SFTPInputPipe = [NSPipe new];
		[SFTPTask setStandardError:SFTPPipe];
		[SFTPTask setStandardOutput:SFTPPipe];
		[SFTPTask setStandardInput:SFTPInputPipe];
		NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
		[notificationCenter addObserver:self selector:@selector(loginTestExit:) name:NSTaskDidTerminateNotification object:SFTPTask];
		[notificationCenter addObserver:self selector:@selector(loginTestRead:) name:NSFileHandleReadCompletionNotification object:[SFTPPipe fileHandleForReading]];
		[[SFTPPipe fileHandleForReading] readInBackgroundAndNotify];
		
		[SFTPTask launch];
	}
}
- (void)loginTestExit:(NSNotification *)theNotification {
	NSLog(@"SFTP Exited");
	NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
	[notificationCenter removeObserver:self name:NSTaskDidTerminateNotification object:SFTPTask];
	[SFTPTask release];
	SFTPTask = nil;
	[notificationCenter removeObserver:self name:NSFileHandleReadCompletionNotification object:[SFTPPipe fileHandleForReading]];
	[SFTPPipe release];
	SFTPPipe = nil;
	[SFTPInputPipe release];
	SFTPInputPipe = nil;
	
	if (![loginButton isEnabled]) {
		NSAlert *alert = [[NSAlert new] autorelease];
		[alert setMessageText:[@"Account Error" localizedFor:self]];
		[alert setInformativeText:[@"Incorrect login info." localizedFor:self]];
		[alert runModal];
		[self unlockLogin];
	}
}
- (void)loginTestProcessSFTPString:(NSString *)theString {
	//NSLog(@"%@", theString);
	if ([theString rangeOfString:@"Entering interactive session"].location!=NSNotFound) {
		NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
		if ([[defaults objectForKey:MGMSFTPPath] isEqual:@""]) {
			NSAlert *alert = [[NSAlert new] autorelease];
			[alert setMessageText:[@"Login Successful" localizedFor:self]];
			[alert setInformativeText:[@"You have successfully logged into your account." localizedFor:self]];
			[alert runModal];
			[self unlockLogin];
		} else {
			[[SFTPInputPipe fileHandleForWriting] writeData:[[NSString stringWithFormat:@"cd %@\n", [[defaults objectForKey:MGMSFTPPath] escapePath]] dataUsingEncoding:NSUTF8StringEncoding]];
			[[SFTPInputPipe fileHandleForWriting] writeData:[@"echo $PWD\n" dataUsingEncoding:NSUTF8StringEncoding]];
		}
	} else if ([theString hasPrefix:@"/"]) {
		NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
		if ([[defaults objectForKey:MGMSFTPPath] hasPrefix:theString]) {
			NSAlert *alert = [[NSAlert new] autorelease];
			[alert setMessageText:[@"Login Successful" localizedFor:self]];
			[alert setInformativeText:[@"You have successfully logged into your account." localizedFor:self]];
			[alert runModal];
			[self unlockLogin];
		} else {
			NSAlert *alert = [[NSAlert new] autorelease];
			[alert setMessageText:[@"Account Error" localizedFor:self]];
			[alert setInformativeText:[@"You have successfully logged into your account, but the path you have entered does not exist." localizedFor:self]];
			[alert runModal];
			[self unlockLogin];
		}
		[[SFTPInputPipe fileHandleForWriting] writeData:[@"exit\n" dataUsingEncoding:NSUTF8StringEncoding]];
	} else if ([theString rangeOfString:@"Permission denied"].location!=NSNotFound) {
		NSAlert *alert = [[NSAlert new] autorelease];
		[alert setMessageText:[@"Account Error" localizedFor:self]];
		[alert setInformativeText:theString];
		[alert runModal];
		[self unlockLogin];
	} else if ([theString rangeOfString:@"Could not resolve"].location!=NSNotFound) {
		NSAlert *alert = [[NSAlert new] autorelease];
		[alert setMessageText:[@"Account Error" localizedFor:self]];
		[alert setInformativeText:theString];
		[alert runModal];
		[self unlockLogin];
	}
}
- (void)loginTestRead:(NSNotification *)theNotification {
	NSData *data = [[theNotification userInfo] objectForKey:NSFileHandleNotificationDataItem];
	NSString *dataString = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
	NSArray *components = [dataString componentsSeparatedByString:@"\n"];
	NSCharacterSet *newline = [NSCharacterSet newlineCharacterSet];
	for (int i=0; i<[components count]; i++) {
		[self loginTestProcessSFTPString:[[components objectAtIndex:i] stringByTrimmingCharactersInSet:newline]];
	}
	[[theNotification object] readInBackgroundAndNotify];
}

- (void)sendFileAtPath:(NSString *)thePath withName:(NSString *)theName {
	NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
	if ([defaults objectForKey:MGMSFTPHost]==nil || [defaults objectForKey:MGMSFTPUser]==nil || [defaults objectForKey:MGMSFTPURL]==nil) {
		NSError *error = [NSError errorWithDomain:[[NSBundle bundleForClass:[self class]] bundleIdentifier] code:5 userInfo:[NSDictionary dictionaryWithObject:[@"Account is not logged in." localizedFor:self] forKey:NSLocalizedDescriptionKey]];
		[[MGMController sharedController] upload:thePath receivedError:error];
		return;
	}
	
	[filePath release];
	filePath = [thePath retain];
	[fileName release];
	fileName = [theName retain];
	SFTPTask = [NSTask new];
	[SFTPTask setLaunchPath:@"/usr/bin/scp"];
	[SFTPTask setCurrentDirectoryPath:[filePath stringByDeletingLastPathComponent]];
	NSString *user = [defaults objectForKey:MGMSFTPUser];
	if (![[[MGMController sharedController] password] isEqual:@""])
		user = [user stringByAppendingFormat:@":%@", [[MGMController sharedController] password]];
	user = [user stringByAppendingFormat:@"@%@", [defaults objectForKey:MGMSFTPHost]];
	user = [user stringByAppendingFormat:@":%@", ([[defaults objectForKey:MGMSFTPPath] isEqual:@""] ? fileName : [[defaults objectForKey:MGMSFTPPath] stringByAppendingPathComponent:fileName])];
	[SFTPTask setArguments:[NSArray arrayWithObjects:@"-v", [filePath lastPathComponent], user, nil]];
	
	SFTPPipe = [NSPipe new];
	SFTPInputPipe = [NSPipe new];
	[SFTPTask setStandardError:SFTPPipe];
	[SFTPTask setStandardOutput:SFTPPipe];
	[SFTPTask setStandardInput:SFTPInputPipe];
	NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
	[notificationCenter addObserver:self selector:@selector(uploadExit:) name:NSTaskDidTerminateNotification object:SFTPTask];
	[notificationCenter addObserver:self selector:@selector(uploadRead:) name:NSFileHandleReadCompletionNotification object:[SFTPPipe fileHandleForReading]];
	[[SFTPPipe fileHandleForReading] readInBackgroundAndNotify];
	
	[SFTPTask launch];
}
- (void)uploadExit:(NSNotification *)theNotification {
	NSLog(@"SFTP Exited");
	NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
	[notificationCenter removeObserver:self name:NSTaskDidTerminateNotification object:SFTPTask];
	[SFTPTask release];
	SFTPTask = nil;
	[notificationCenter removeObserver:self name:NSFileHandleReadCompletionNotification object:[SFTPPipe fileHandleForReading]];
	[SFTPPipe release];
	SFTPPipe = nil;
	[SFTPInputPipe release];
	SFTPInputPipe = nil;
	
	if (theNotification!=nil) {
		NSError *error = [NSError errorWithDomain:[[NSBundle bundleForClass:[self class]] bundleIdentifier] code:1 userInfo:[NSDictionary dictionaryWithObject:[@"Incorrect login info" localizedFor:self] forKey:NSLocalizedDescriptionKey]];
		NSString *finishPath = [[filePath retain] autorelease];
		[filePath release];
		filePath = nil;
		[[MGMController sharedController] upload:finishPath receivedError:error];
	}
}
- (void)uploadProcessSFTPString:(NSString *)theString {
	//NSLog(@"%@", theString);
	if ([theString rangeOfString:@"exit-status"].location!=NSNotFound) {
		NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
		[self uploadExit:nil];
		NSString *url = [defaults objectForKey:MGMSFTPURL];
		if (![url hasSuffix:@"/"])
			url = [url stringByAppendingFormat:@"/%@", [fileName addPercentEscapes]];
		else
			url = [url stringByAppendingString:[fileName addPercentEscapes]];
		NSString *finishPath = [[filePath retain] autorelease];
		[filePath release];
		filePath = nil;
		[fileName release];
		fileName = nil;
		[[MGMController sharedController] uploadFinished:finishPath url:[NSURL URLWithString:url]];
	} else if ([theString rangeOfString:@"Permission denied"].location!=NSNotFound) {
		[self uploadExit:nil];
		NSError *error = [NSError errorWithDomain:[[NSBundle bundleForClass:[self class]] bundleIdentifier] code:1 userInfo:[NSDictionary dictionaryWithObject:theString forKey:NSLocalizedDescriptionKey]];
		NSString *finishPath = [[filePath retain] autorelease];
		[filePath release];
		filePath = nil;
		[fileName release];
		fileName = nil;
		[[MGMController sharedController] upload:finishPath receivedError:error];
	} else if ([theString rangeOfString:@"Could not resolve"].location!=NSNotFound) {
		[self uploadExit:nil];
		NSError *error = [NSError errorWithDomain:[[NSBundle bundleForClass:[self class]] bundleIdentifier] code:1 userInfo:[NSDictionary dictionaryWithObject:theString forKey:NSLocalizedDescriptionKey]];
		NSString *finishPath = [[filePath retain] autorelease];
		[filePath release];
		filePath = nil;
		[fileName release];
		fileName = nil;
		[[MGMController sharedController] upload:finishPath receivedError:error];
	}
}
- (void)uploadRead:(NSNotification *)theNotification {
	NSData *data = [[theNotification userInfo] objectForKey:NSFileHandleNotificationDataItem];
	NSString *dataString = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
	NSArray *components = [dataString componentsSeparatedByString:@"\n"];
	NSCharacterSet *newline = [NSCharacterSet newlineCharacterSet];
	for (int i=0; i<[components count]; i++) {
		[self uploadProcessSFTPString:[[components objectAtIndex:i] stringByTrimmingCharactersInSet:newline]];
	}
	[[theNotification object] readInBackgroundAndNotify];
}
@end