//
//  MoviePlayerView.m
//

#import "MoviePlayerView.h"
#import "MoviePlayerDataProvider.h"
#import "FileURLHelper.h"
#ifdef IS_APPDOO_PREVIEW
#import "Prototype.h"
#import "ProjectResourcesCache.h"
#endif

@implementation MoviePlayerView {
	NSTimer * _publishCurrentStateTimer;
	BOOL _isPlaying;
	BOOL _didPrepare;
}

- (BOOL)isPlaying {
    if (self.moviePlayer != nil && self.moviePlayer.player != nil) {
        return (self.moviePlayer.player.timeControlStatus == AVPlayerTimeControlStatusPlaying);
    }
	return _isPlaying;
}

- (void)awakeFromNib {
	[super awakeFromNib];
	[self prepare];
	[self publishCurrentState];
}
	
- (void)dealloc {
    if (_moviePlayer) {
        [self unsetMoviePlayer];
    }
}

- (void)removeFromSuperview {
	[super removeFromSuperview];
    if (_moviePlayer) {
        [self unsetMoviePlayer];
    }
}
	
- (void)setMovieURLString:(NSString *)movieURLString {
	_movieURLString = [movieURLString copy];
	NSURL * url = GetFileURLFromString(self.movieURLString);
    if (!url) {
        return;
    }
#ifdef IS_APPDOO_PREVIEW
	// cache file:
	if ([_movieURLString hasPrefix:@"file:"]) {
		NSString * fileID = [[Prototype sharedInstance] resourceIDForFilename:[_movieURLString substringFromIndex:5]];
		if ([ProjectResourcesCache sharedCache] != nil && [[ProjectResourcesCache sharedCache] resourceWithIDIsCached:fileID]) {
			NSData * data = [[ProjectResourcesCache sharedCache] dataForResourceID:fileID];
			NSArray * paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
			NSString * cacheFile = [[paths objectAtIndex:0] stringByAppendingPathComponent:fileID];
			NSError *cacheError = nil;
			[data writeToFile:cacheFile options:NSDataWritingAtomic error:&cacheError];
			if(!cacheError) {
				url = [NSURL fileURLWithPath:cacheFile];
			}
		}
        if (!url) {
            return;
        }
	}
#endif
	if (!self.moviePlayer) {
        _moviePlayer = [[AVPlayerViewController alloc] init];
        _moviePlayer.player = [AVPlayer playerWithURL:url];
        _moviePlayer.view.frame = self.bounds;
        _moviePlayer.view.backgroundColor = self.backgroundColor;
        self.backgroundColor = [UIColor redColor];
        _moviePlayer.view.autoresizingMask = 18;
        if (@available(iOS 11, *)) {
            _moviePlayer.exitsFullScreenWhenPlaybackEnds = YES;
            _moviePlayer.entersFullScreenWhenPlaybackBegins = NO;
        }
        self.showsControls = _showsControls;
        self.autoplay = _autoplay;
        _moviePlayer.player.actionAtItemEnd = AVPlayerActionAtItemEndNone;
        [self prepare];
    } else {
        if (_moviePlayer.player.timeControlStatus != AVPlayerTimeControlStatusPaused) {
            [self stop];
        }
        _moviePlayer.player = [AVPlayer playerWithURL:url];
    }
}

- (void)setShowsControls:(BOOL)showsControls {
	_showsControls = showsControls;
    _moviePlayer.showsPlaybackControls = self.showsControls;
}

- (void)setAutoplay:(BOOL)autoplay {
	_autoplay = autoplay;
    if (autoplay && self.moviePlayer.viewLoaded) {
        [self play];
    }
}
	
- (void)setRepeat:(BOOL)repeat {
	_repeat = repeat;
}

- (void)unsetMoviePlayer {
    [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:[_moviePlayer.player currentItem]];
    [self.moviePlayer.player.currentItem removeObserver:self forKeyPath:@"status"];

	[self stop];
	[self.moviePlayer.view removeFromSuperview];
	self.moviePlayer = nil;
    if (_publishCurrentStateTimer) {
        [_publishCurrentStateTimer invalidate];
    }
	_publishCurrentStateTimer = nil;
    
	[[NSNotificationCenter defaultCenter] postNotificationName:@"AudioPlayerDidDisappear" object:self];
    
#ifdef IS_APPDOO_PREVIEW
	// remove cached media file:
	if ([_movieURLString hasPrefix:@"file:"]) {
		NSString * fileID = [[Prototype sharedInstance] resourceIDForFilename:[_movieURLString substringFromIndex:5]];
		NSArray * paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
		NSString * cacheFile = [[paths objectAtIndex:0] stringByAppendingPathComponent:fileID];
		if([[NSFileManager defaultManager] isReadableFileAtPath:cacheFile]) {
			[[NSFileManager defaultManager] removeItemAtPath:cacheFile error:nil];
		}
	}
#endif
}

- (void)prepare {
	if (!_moviePlayer || _didPrepare) {
        return;
    }
    
	_didPrepare = YES;
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moviePlaybackDidFinish:) name:AVPlayerItemDidPlayToEndTimeNotification object:[_moviePlayer.player currentItem]];
    [self.moviePlayer.player.currentItem addObserver:self forKeyPath:@"status" options:(NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew) context:nil];
    [self addSubview:_moviePlayer.view];
	[[NSNotificationCenter defaultCenter] postNotificationName:@"AudioPlayerDidPrepare" object:self];
}

- (void)publishCurrentState {
	[self.dataProvider updateContents];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if ([keyPath isEqualToString:@"status"]) {
        if (self.moviePlayer.player.timeControlStatus == AVPlayerTimeControlStatusPlaying) {
            [self beginPublishingCurrentState];
            _isPlaying = YES;
        }
        if (self.moviePlayer.player.timeControlStatus == AVPlayerTimeControlStatusPaused) {
            [self endPublishingCurrentState];
            _isPlaying = NO;
        }
        [self publishCurrentState];
    }
}

- (void)moviePlaybackDidFinish:(NSNotification*)notification {
    if (self.repeat) {
        AVPlayerItem *p = [notification object];
        [p seekToTime:kCMTimeZero];
        if (![self isPlaying]) {
            [self play];
        }
    } else {
        if (@available(iOS 11, *)) {} else {
            [self.moviePlayer dismissViewControllerAnimated:YES completion:nil];
        }
    }
}

- (void)moviePlaybackStateDidChange:(NSNotification*)notification {
}
		
- (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)play {
    [self.moviePlayer.player play];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"AudioPlayerDidPrepare" object:self];
}

- (void)pause {
    [self.moviePlayer.player pause];
}

- (void)pauseOrPlay {
    if (self.moviePlayer.player.timeControlStatus == AVPlayerTimeControlStatusPlaying) {
        [self.moviePlayer.player pause];
    } else {
        [self.moviePlayer.player play];
    }
}

- (void)stop {
    [self.moviePlayer.player pause];
    [self.moviePlayer.player.currentItem seekToTime:kCMTimeZero];
}

- (void)toggleFullScreen {
    // TODO: implement this (if necessary)
}

- (void)seekBackward {
    [_moviePlayer.player.currentItem seekToTime:CMTimeSubtract(self.moviePlayer.player.currentItem.currentTime, CMTimeMake(5, 1))];
}

- (void)seekForward {
    [_moviePlayer.player.currentItem seekToTime:CMTimeAdd(self.moviePlayer.player.currentItem.currentTime, CMTimeMake(5, 1))];
}

- (void)beginSeekingBackward {
}

- (void)beginSeekingForward {
}

- (void)endSeeking {
}

- (void)setDataProvider:(MoviePlayerDataProvider *)dataProvider {
	dataProvider.playerView = self;
	_dataProvider = dataProvider;
}

- (void)destroy {
	[self unsetMoviePlayer];
}

- (void)viewWillAppear:(BOOL)animated {
    if (!self.moviePlayer && self.movieURLString != nil) {
        [self setMovieURLString:_movieURLString];
    }
    if ([self autoplay] && ![self isPlaying]) {
        [self play];
    }
}

@end
