//
//  SimpleAudioPlayer.m
//

#import "SimpleAudioPlayer.h"
#import <AudioToolbox/AudioToolbox.h>
#import "FileURLHelper.h"

#ifdef IS_APPDOO_PREVIEW
#import "ProjectResourcesCache.h"
#endif

#ifdef LOAD_RESOURCES_FROM_DATA
static NSString * AVFileTypeFromName(NSString * name) {
	NSString * pathExtension = name.pathExtension;
	if ([pathExtension isEqualToString:@"mp3"])		return @"public.mp3";
	if ([pathExtension isEqualToString:@"m4a"])		return @"com.apple.m4a-audio";
	if ([pathExtension isEqualToString:@"aac"])		return @"com.apple.m4a-audio";
	if ([pathExtension isEqualToString:@"mp4"])		return @"public.mpeg-4";
	if ([pathExtension isEqualToString:@"m4v"])		return @"public.mpeg-4";
	if ([pathExtension isEqualToString:@"aif"])		return @"public.aiff-audio";
	if ([pathExtension isEqualToString:@"aiff"])	return @"public.aiff-audio";
	if ([pathExtension isEqualToString:@"aifc"])	return @"public.aifc-audio";
	if ([pathExtension isEqualToString:@"wav"])		return @"com.microsoft.waveform-audio";
	if ([pathExtension isEqualToString:@"3gp"])		return @"public.3gpp";
	if ([pathExtension isEqualToString:@"ac3"])		return @"public.ac3-audio";
	if ([pathExtension isEqualToString:@"amr"])		return @"org.3gpp.adaptive-multi-rate-audio";
	if ([pathExtension isEqualToString:@"mov"])		return @"com.apple.quicktime-movie";
	if ([pathExtension isEqualToString:@"au"])		return @"public.au-audio";
	return nil;
}
#endif

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"

@implementation SimpleAudioPlayer {
	float _stepInterval;
	__weak NSTimer * _seekingIntervalTimer;
	__weak NSTimer * _publishCurrentStateTimer;
	NSMutableDictionary * _nowPlayingInfo;
	BOOL _didPlay;
}


+ (void)playSoundNamed:(NSString *)soundName {
	NSString *soundPath = [[NSBundle mainBundle] pathForResource:soundName ofType:@""];
	if(!soundPath) return;
	NSURL *soundPathURL = [NSURL fileURLWithPath:soundPath];
	if(soundPathURL != nil) {
		SystemSoundID soundID;
		AudioServicesCreateSystemSoundID((__bridge CFURLRef)soundPathURL, &soundID);
		AudioServicesPlaySystemSound (soundID);
	}
}

- (void)awakeFromNib {
	[super awakeFromNib];
	if (self.autoplay) {
		//[self play];
		dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1*NSEC_PER_SEC), dispatch_get_main_queue(), ^(void){
			dispatch_async(dispatch_get_main_queue(), ^{
				[self play];
			});
		});
	}
	[self publishCurrentState];
}

- (void)setSoundName: (NSString *)soundName {
	_soundName = soundName;
}
	
- (void)setSoundIdentifier: (NSString *)soundIdentifier {
	_soundIdentifier = soundIdentifier;
}

- (BOOL)prepareToPlay {
	
	[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
	if (!_player) {
		NSError * error = nil;
		if (self.soundName.length) {
#ifdef LOAD_RESOURCES_FROM_DATA
			NSData * data = GetDataFromLocalFile(self.soundName, nil);
			self.player = [[AVAudioPlayer alloc] initWithData:data error:&error];
#else
			NSString *soundPath = [[NSBundle mainBundle] pathForResource:self.soundName ofType:@""];
			if(soundPath != nil && soundPath.length > 0) {
				NSURL *soundPathURL = [NSURL fileURLWithPath:soundPath];
				if(soundPathURL != nil) {
					self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundPathURL error:&error];
				}
			}
#ifdef IS_APPDOO_PREVIEW
			if(!_player && self.soundIdentifier != nil && self.soundIdentifier.length > 0) {
				if ([ProjectResourcesCache sharedCache] != nil) {
					if ([[ProjectResourcesCache sharedCache] resourceWithIDIsCached:self.soundIdentifier]) {
						NSData * data = [[ProjectResourcesCache sharedCache] dataForResourceID:self.soundIdentifier];
						self.player = [[AVAudioPlayer alloc] initWithData:data error:&error];
					}
				}
			}
#endif
#endif
		} else if (self.soundURLString.length) {
			if ([self.soundURLString hasPrefix:@"file:"]) {
#ifdef LOAD_RESOURCES_FROM_DATA
				NSURL * url = GetFileURLFromString(self.soundURLString);
				if(!url) {
					return false;
				}
				self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
				if (error) {
					NSLog(@"Error in audio player: %@", error);
					return false;
				}
#else
				NSURL * url = GetFileURLFromString(self.soundURLString);
				if (!url) {
					return false;
				}
				self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
#endif
			}
			else {
				self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL URLWithString:self.soundURLString] error:&error];
			}
		} else {
			NSLog(@"self.soundName %@",self.soundName);
			NSLog(@"self.soundURLString %@",self.soundURLString);
		}
		_player.enableRate = YES;
	}
	
	return (self.player != nil);
}

- (void)play {
	_didPlay = YES;
	_stepInterval = 0.5;
	
	BOOL prepared = [self prepareToPlay];
	if(!prepared) {
		_didPlay = NO;
		return;
	}
	[_player play];
	[[NSNotificationCenter defaultCenter] postNotificationName:@"AudioPlayerDidPrepare" object:self];
	
	[self becomeFirstResponder];
	
	//[self.nowPlayingInfo setObject:@1 forKey:MPNowPlayingInfoPropertyPlaybackRate];
	//[self.nowPlayingInfo setObject:[NSNumber numberWithDouble:self.player.duration] forKey:MPMediaItemPropertyPlaybackDuration];

	[self beginPublishingCurrentState];
}

- (NSMutableDictionary *)nowPlayingInfo {
	if (!_nowPlayingInfo) {
		_nowPlayingInfo = @{
			//MPMediaItemPropertyTitle: self.soundName != nil ? self.soundName.stringByDeletingPathExtension : @"",
			//MPMediaItemPropertyMediaType: [NSNumber numberWithInteger:MPMediaTypeAnyAudio],
		}.mutableCopy;
	}
	return _nowPlayingInfo;
}

- (void)pause {
	[_player pause];
	//[self.nowPlayingInfo setObject:@0 forKey:MPNowPlayingInfoPropertyPlaybackRate];
	//MPNowPlayingInfoCenter.defaultCenter.nowPlayingInfo = self.nowPlayingInfo;
}

- (void)playOrPause {
	if (!_player || !_player.isPlaying)
		[self play];
	else
		[self pause];
}

- (void)pauseOrPlay {
	[self playOrPause];
}

- (void)stop {
	[_player stop];
	_player.currentTime = 0;
	[self endPublishingCurrentState];
}

#define SEEKING_STEP_INCREASE 0.05
#define SEEKING_INTERVAL 0.2


- (void)beginSeekingForward {
	if (_player.playing) _player.rate = 4;
	else _seekingIntervalTimer = [NSTimer scheduledTimerWithTimeInterval:SEEKING_INTERVAL target:self selector:@selector(stepForwardFromTimer) userInfo:nil repeats:YES];
}

- (void)beginSeekingBackward {
	_seekingIntervalTimer = [NSTimer scheduledTimerWithTimeInterval:SEEKING_INTERVAL target:self selector:@selector(stepBackwardFromTimer) userInfo:nil repeats:YES];
}

- (void)endSeeking {
	_player.rate = 1;
	_stepInterval = 0.5;
	[_seekingIntervalTimer invalidate];
}

- (void)dealloc {
	NSLog(@"dealloc: %@", self);
}

- (void)stepBackward {
	_player.currentTime -= _stepInterval;
}

- (void)stepForward {
	_player.currentTime += _stepInterval;
}

- (void)seekBackward {
	[self stepBackward];
}

- (void)seekForward {
	[self stepForward];
}

- (void)stepBackwardFromTimer {
	if (_stepInterval < 1) _stepInterval += SEEKING_STEP_INCREASE;
	[self stepBackward];
}

- (void)stepForwardFromTimer {
	if (_stepInterval < 1) _stepInterval += SEEKING_STEP_INCREASE;
	[self stepForward];
}

- (void)publishCurrentState {
	[self.dataProvider updateContents];
	//[self.nowPlayingInfo setObject:[NSNumber numberWithDouble:self.player.currentTime] forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime];
	//if (_didPlay) { MPNowPlayingInfoCenter.defaultCenter.nowPlayingInfo = self.nowPlayingInfo; }
}

- (void)setDataProvider:(SimpleAudioPlayerDataProvider *)dataProvider {
	dataProvider.player = self;
	_dataProvider = dataProvider;
}

- (void)beginPublishingCurrentState {
	if (_publishCurrentStateTimer) [self endPublishingCurrentState];
	_publishCurrentStateTimer = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:@selector(publishCurrentState) userInfo:nil repeats:YES];
	
}

- (void)endPublishingCurrentState {
	[self publishCurrentState];
	[_publishCurrentStateTimer invalidate];
	_publishCurrentStateTimer = nil;
}

- (void)destroy {
	[self resignFirstResponder];
	[_player stop];
	[_seekingIntervalTimer invalidate], _seekingIntervalTimer = nil;
	[_publishCurrentStateTimer invalidate], _publishCurrentStateTimer = nil;
	_player = nil;
	_dataProvider = nil;
	[[NSNotificationCenter defaultCenter] postNotificationName:@"AudioPlayerDidDisappear" object:self];
}

- (BOOL)canBecomeFirstResponder {
	return YES;
}

- (void)remoteControlReceivedWithEvent:(UIEvent *)event {

	if (event.type == UIEventTypeRemoteControl){
		switch (event.subtype) {
			case UIEventSubtypeRemoteControlStop:
				[self stop];
				break;
			case UIEventSubtypeRemoteControlTogglePlayPause:
				[self pauseOrPlay];
				break;
			case UIEventSubtypeRemoteControlPlay:
				[self play];
				break;
			case UIEventSubtypeRemoteControlPause:
				[self pause];
				break;
			case UIEventSubtypeRemoteControlBeginSeekingBackward:
				[self beginSeekingBackward];
				break;
			case UIEventSubtypeRemoteControlBeginSeekingForward:
				[self beginSeekingForward];
				break;
			case UIEventSubtypeRemoteControlEndSeekingBackward:
			case UIEventSubtypeRemoteControlEndSeekingForward:
				[self endSeeking];
				break;
			default:
				break;
		}
	}
	
	[self publishCurrentState];

}

- (BOOL)becomeFirstResponder {
	BOOL result = [super becomeFirstResponder];
	return result;
}

- (BOOL)resignFirstResponder {
	BOOL result = [super resignFirstResponder];
	return result;
}

- (UIResponder *)nextResponder {
	return UIApplication.sharedApplication.keyWindow;
}

@end

#pragma GCC diagnostic pop
