//
//  MGMSIPCallWindow.m
//  VoiceMac
//
//  Created by Mr. Gecko on 9/14/10.
//  Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
//  Permission to use, copy, modify, and/or distribute this software for any purpose
//  with or without fee is hereby granted, provided that the above copyright notice
//  and this permission notice appear in all copies.
//
//  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
//  REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
//  FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
//  OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
//  DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
//  ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//

#if MGMSIPENABLED
#import "MGMSIPCallWindow.h"
#import "MGMSIPUser.h"
#import "MGMController.h"
#import <VoiceBase/VoiceBase.h>
#import <MGMUsers/MGMUsers.h>
#import <QTKit/QTKit.h>

NSString * const MGMSCTitleFormat = @"Call With %@ %@";
NSString * const MGMSCTitleNoNameFormat = @"Call With %@";

@implementation MGMSIPCallWindow
+ (id)windowWithCall:(MGMSIPCall *)theCall SIPUser:(MGMSIPUser *)theSIPUser {
	return [[[self alloc] initWithCall:theCall SIPUser:theSIPUser] autorelease];
}
- (id)initWithCall:(MGMSIPCall *)theCall SIPUser:(MGMSIPUser *)theSIPUser {
	if ((self = [super init])) {
		if (![NSBundle loadNibNamed:@"SIPCallWindow" owner:self]) {
			NSLog(@"Unable to load SIP Call Window!");
			[self release];
			self = nil;
		} else {
			call = [theCall retain];
			[call setDelegate:self];
			[call setHoldMusicPath:[[[[MGMUser applicationSupportPath] stringByAppendingPathComponent:MGMTCallSoundsFolder] stringByAppendingPathComponent:MGMTSSIPHoldMusic] stringByAppendingPathExtension:MGMWavExt]];
			account = [call account];
			SIPUser = theSIPUser;
			[callWindow setLevel:NSNormalWindowLevel];
			[callWindow setExcludedFromWindowsMenu:NO];
			[[callWindow contentView] addSubview:numberPadView];
			NSRect padFrame = [numberPadView frame];
			callWindowSize = [callWindow frame].size;
			callWindowPadSize = [callWindow frame].size;
			padFrame.origin.y -= callWindowSize.height;
			callWindowPadSize.height += padFrame.size.height;
			[numberPadView setFrame:padFrame];
			[incomingWindow setLevel:NSStatusWindowLevel];
			[incomingWindow setExcludedFromWindowsMenu:YES];
			
			NSString *phoneCalling = [SIPUser phoneCalling];
			if (phoneCalling!=nil)
				[[call remoteURL] setUserName:phoneCalling];
			
			if ([call isIncoming] && phoneCalling==nil) {
				if ([[[call remoteURL] userName] isPhone]) {
					NSString *number = [[[call remoteURL] userName] phoneFormat];
					phoneNumber = [[number readableNumber] copy];
					[phoneField setStringValue:phoneNumber];
					NSString *name = [[SIPUser contacts] nameForNumber:number];
					if (name==nil || [name isEqual:phoneNumber]) {
						connectionManager = [MGMURLConnectionManager new];
						MGMWhitePagesHandler *handler = [MGMWhitePagesHandler reverseLookup:number delegate:self];
						[connectionManager addHandler:handler];
						[nameField setStringValue:@"Loading..."];
					} else {
						fullName = [name copy];
						[nameField setStringValue:fullName];
					}
				} else {
					phoneNumber = [[[call remoteURL] SIPAddress] copy];
					[phoneField setStringValue:phoneNumber];
					if ([[call remoteURL] fullName]!=nil && ![[[call remoteURL] fullName] isEqual:@""]) {
						fullName = [[[call remoteURL] fullName] copy];
						[nameField setStringValue:fullName];
					} else {
						[nameField setStringValue:@"Unknown"];
					}
				}
				[incomingWindow makeKeyAndOrderFront:self];
				[call sendRingingNotification];
				NSString *ringtonePath = [[[SIPUser controller] themeManager] currentSoundPath:MGMTSSIPRingtone];
				if (ringtonePath!=nil && ![ringtonePath isEqual:MGMTNoSound]) {
					ringtone = [[MGMSound alloc] initWithContentsOfFile:ringtonePath];
					[ringtone setLoops:YES];
					[ringtone play];
				}
			} else {
				if ([[[call remoteURL] userName] isPhone]) {
					NSString *number = [[[call remoteURL] userName] phoneFormat];
					phoneNumber = [[number readableNumber] copy];
					NSString *name = [[SIPUser contacts] nameForNumber:number];
					if (name==nil || [name isEqual:phoneNumber]) {
						connectionManager = [MGMURLConnectionManager new];
						MGMWhitePagesHandler *handler = [MGMWhitePagesHandler reverseLookup:number delegate:self];
						[connectionManager addHandler:handler];
					} else {
						fullName = [name copy];
					}
				} else {
					phoneNumber = [[[call remoteURL] SIPAddress] copy];
					if ([[call remoteURL] fullName]!=nil && ![[[call remoteURL] fullName] isEqual:@""])
						fullName = [[[call remoteURL] fullName] copy];
				}
				[self fillCallWindow];
				if (phoneCalling!=nil)
					[call answer];
				[callWindow makeKeyAndOrderFront:self];
			}
			
			if ([call state]==MGMSIPCallDisconnectedState) {
				[ringtone stop];
				[ringtone release];
				ringtone = nil;
			}
			
			NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
			[notificationCenter addObserver:self selector:@selector(soundChanged:) name:MGMTSoundChangedNotification object:nil];
			[notificationCenter addObserver:self selector:@selector(volumeChanged:) name:MGMSIPVolumeChangedNotification object:nil];
			[notificationCenter addObserver:self selector:@selector(micVolumeChanged:) name:MGMSIPMicVolumeChangedNotification object:nil];
		}
	}
	return self;
}
- (void)dealloc {
	[[NSNotificationCenter defaultCenter] removeObserver:self];
	[self hidePad];
	[call setDelegate:nil];
	[call release];
	[connectionManager release];
	[incomingWindow release];
	[callWindow release];
	[fullName release];
	[phoneNumber release];
	[ringtone stop];
	[ringtone release];
	[durationUpdater invalidate];
	[durationUpdater release];
	[startTime release];
	[super dealloc];
}

- (void)disconnected:(MGMSIPCall *)theCall {
	[ringtone stop];
	[ringtone release];
	ringtone = nil;
	if ([callWindow isVisible]) {
		[durationUpdater invalidate];
		[durationUpdater release];
		durationUpdater = nil;
		[startTime release];
		startTime = nil;
		[statusField setStringValue:@"Disconnected"];
		[[[SIPUser controller] themeManager] playSound:MGMTSSIPDisconnected];
	} else {
		if ([incomingWindow isVisible])
			[incomingWindow close];
		[SIPUser callDone:self];
	}
}
- (void)confirmed:(MGMSIPCall *)theCall {
	[statusField setStringValue:@"Connected"];
	[[[SIPUser controller] themeManager] playSound:MGMTSSIPConnected];
	[self performSelectorOnMainThread:@selector(startDurationTimer) withObject:nil waitUntilDone:YES];
}
- (void)startDurationTimer {
	startTime = [NSDate new];
	durationUpdater = [[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateDuration) userInfo:nil repeats:YES] retain];
}

- (void)soundChanged:(NSNotification *)theNotification {
	if ([[theNotification object] isEqual:MGMTSSIPSound1])
		[sound1Button setTitle:[[[SIPUser controller] themeManager] nameOfSound:MGMTSSIPSound1]];
	if ([[theNotification object] isEqual:MGMTSSIPSound2])
		[sound2Button setTitle:[[[SIPUser controller] themeManager] nameOfSound:MGMTSSIPSound2]];
	if ([[theNotification object] isEqual:MGMTSSIPSound3])
		[sound3Button setTitle:[[[SIPUser controller] themeManager] nameOfSound:MGMTSSIPSound3]];
	if ([[theNotification object] isEqual:MGMTSSIPSound4])
		[sound4Button setTitle:[[[SIPUser controller] themeManager] nameOfSound:MGMTSSIPSound4]];
	if ([[theNotification object] isEqual:MGMTSSIPSound5])
		[sound5Button setTitle:[[[SIPUser controller] themeManager] nameOfSound:MGMTSSIPSound5]];
}

- (void)fillCallWindow {
	if (fullName==nil)
		[self setTitle:[NSString stringWithFormat:MGMSCTitleNoNameFormat, phoneNumber]];
	else
		[self setTitle:[NSString stringWithFormat:MGMSCTitleFormat, fullName, phoneNumber]];
	[durationField setStringValue:[NSString stringWithSeconds:0]];
	[volumeSlider setFloatValue:[[MGMSIP sharedSIP] volume]];
	[micVolumeSlider setFloatValue:[[MGMSIP sharedSIP] micVolume]];
	if ([call state]!=MGMSIPCallConfirmedState)
		[statusField setStringValue:@"Connecting..."];
	else
		[self confirmed:call];
	
	[sound1Button setTitle:[[[SIPUser controller] themeManager] nameOfSound:MGMTSSIPSound1]];
	[sound2Button setTitle:[[[SIPUser controller] themeManager] nameOfSound:MGMTSSIPSound2]];
	[sound3Button setTitle:[[[SIPUser controller] themeManager] nameOfSound:MGMTSSIPSound3]];
	[sound4Button setTitle:[[[SIPUser controller] themeManager] nameOfSound:MGMTSSIPSound4]];
	[sound5Button setTitle:[[[SIPUser controller] themeManager] nameOfSound:MGMTSSIPSound5]];
}
- (IBAction)answer:(id)sender {
	[ringtone stop];
	[ringtone release];
	ringtone = nil;
	[incomingWindow close];
	[call answer];
	[self fillCallWindow];
	[callWindow makeKeyAndOrderFront:self];
}
- (IBAction)ignore:(id)sender {
	[ringtone stop];
	[ringtone release];
	ringtone = nil;
	[incomingWindow close];
	[SIPUser callDone:self];
}

- (void)updateDuration {
	int time = [[NSDate date] timeIntervalSinceDate:startTime];
	[durationField setStringValue:[NSString stringWithSeconds:time]];
}

- (void)setTitle:(NSString *)theTitle {
	[titleField setStringValue:theTitle];
	[callWindow setTitle:theTitle];
}

- (void)volumeChanged:(NSNotification *)theNotification {
	[volumeSlider setFloatValue:[[theNotification object] floatValue]];
}
- (IBAction)volume:(id)sender {
	[[MGMSIP sharedSIP] setVolume:[volumeSlider floatValue]];
}
- (void)micVolumeChanged:(NSNotification *)theNotification {
	[micVolumeSlider setFloatValue:[[theNotification object] floatValue]];
}
- (IBAction)micVolume:(id)sender {
	[[MGMSIP sharedSIP] setMicVolume:[micVolumeSlider floatValue]];
}

- (IBAction)hold:(id)sender {
	[call hold];
	[holdButton setImage:[NSImage imageNamed:([call isLocalOnHold] ? @"unholdButton" : @"holdButton")]];
}
- (void)hidePad {
	if (NSEqualSizes([callWindow frame].size, callWindowPadSize)) {
		NSRect frame = [callWindow frame];
		frame.origin.y -= callWindowSize.height-frame.size.height;
		frame.size = callWindowSize;
		[callWindow setFrame:frame display:NO animate:NO];
	}
}
- (IBAction)showPad:(id)sender {
	if (NSEqualSizes([callWindow frame].size, callWindowSize)) {
		NSRect frame = [callWindow frame];
		frame.origin.y -= callWindowPadSize.height-frame.size.height;
		frame.size = callWindowPadSize;
		[callWindow setFrame:frame display:YES animate:YES];
	} else {
		NSRect frame = [callWindow frame];
		frame.origin.y -= callWindowSize.height-frame.size.height;
		frame.size = callWindowSize;
		[callWindow setFrame:frame display:YES animate:YES];
	}
}
- (IBAction)hangUp:(id)sender {
	[callWindow close];
	[durationUpdater invalidate];
	[durationUpdater release];
	durationUpdater = nil;
	[startTime release];
	startTime = nil;
	[call hangUp];
	[SIPUser callDone:self];
}

- (IBAction)startRecording:(id)sender {
	if ([call isRecording]) {
		[call stopRecording];
	} else {
		NSFileManager *manager = [NSFileManager defaultManager];
		NSString *baseName = [[NSString stringWithFormat:@"~/Desktop/Call With %@ - ", phoneNumber] stringByExpandingTildeInPath];
		NSString *name = nil;
		for (int i=1; i<50; i++) { // Not like someone will have 50 recordings with one person on their desktop...
			name = [[baseName stringByAppendingFormat:@"%02d", i] stringByAppendingPathExtension:MGMWavExt];
			if (![manager fileExistsAtPath:name])
				break;
		}
		[call startRecording:name];
	}
	[recordingButton setTitle:([call isRecording] ? @"Stop Recording" : @"Start Recording")];
}
- (IBAction)muteMicrophone:(id)sender {
	[call muteMic];
	[muteMicrophoneButton setTitle:([call isMicMuted] ? @"Unmute Microphone" : @"Mute Microphone")];
}
- (IBAction)muteSpeakers:(id)sender {
	[call mute];
	[muteSpeakersButton setTitle:([call isMuted] ? @"Unmute Speakers" : @"Mute Speakers")];
}
- (IBAction)sound:(id)sender {
	NSString *soundName = nil;
	if (sender==sound1Button)
		soundName = MGMTSSIPSound1;
	else if (sender==sound2Button)
		soundName = MGMTSSIPSound2;
	else if (sender==sound3Button)
		soundName = MGMTSSIPSound3;
	else if (sender==sound4Button)
		soundName = MGMTSSIPSound4;
	else if (sender==sound5Button)
		soundName = MGMTSSIPSound5;
	NSString *soundFile = [[[[MGMUser applicationSupportPath] stringByAppendingPathComponent:MGMTCallSoundsFolder] stringByAppendingPathComponent:soundName] stringByAppendingPathExtension:MGMWavExt];
	[call playSound:soundFile];
	[[[SIPUser controller] themeManager] performSelector:@selector(playSound:) withObject:soundName afterDelay:0.2]; // The phone has a delay, so why not delay this so you hear it at the same time?
}
- (IBAction)dial:(id)sender {
	if (sender==n1Button)
		[call sendDTMFDigits:@"1"];
	else if (sender==n2Button)
		[call sendDTMFDigits:@"2"];
	else if (sender==n3Button)
		[call sendDTMFDigits:@"3"];
	else if (sender==n4Button)
		[call sendDTMFDigits:@"4"];
	else if (sender==n5Button)
		[call sendDTMFDigits:@"5"];
	else if (sender==n6Button)
		[call sendDTMFDigits:@"6"];
	else if (sender==n7Button)
		[call sendDTMFDigits:@"7"];
	else if (sender==n8Button)
		[call sendDTMFDigits:@"8"];
	else if (sender==n9Button)
		[call sendDTMFDigits:@"9"];
	else if (sender==nStarButton)
		[call sendDTMFDigits:@"*"];
	else if (sender==n0Button)
		[call sendDTMFDigits:@"0"];
	else if (sender==nPoundButton)
		[call sendDTMFDigits:@"#"];
}

- (void)reverseLookupDidFindInfo:(MGMWhitePagesHandler *)theHandler {
	if ([theHandler name]!=nil) {
		fullName = [[theHandler name] copy];
		if ([callWindow isVisible])
			[self setTitle:[NSString stringWithFormat:MGMSCTitleFormat, fullName, phoneNumber]];
		else
			[nameField setStringValue:fullName];
	} else if ([theHandler location]!=nil) {
		if ([incomingWindow isVisible])
			[nameField setStringValue:[theHandler location]];
	}
}
@end
#endif