//
//  RCTMediaPlayer.m
//  RCTOMPlayer
//
//  Created by lcg on 2017/7/13.
//  Copyright © 2017年 Anren. All rights reserved.
//

#import "RCTMediaPlayer.h"
#import "IJKMediaFramework/IJKMediaFramework.h"
#import "JX_GCDTimerManager.h"

@interface RCTMediaPlayer()

@property (nonatomic, strong) IJKFFMoviePlayerController* player;
@property (nonatomic, assign) BOOL seeking;
@property (nonatomic, assign) BOOL notificationInited;

@end

@implementation RCTMediaPlayer

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.rate = 1.0f;
        self.volume = 1.0f;
        self.paused = YES;
        self.notificationInited = NO;
    }
    return self;
}

- (void)dealloc
{
    
}

#pragma mark - player

- (void)initPlayer
{
    [IJKFFMoviePlayerController setLogReport:NO];
    [IJKFFMoviePlayerController setLogLevel:k_IJK_LOG_ERROR];
    
    [IJKFFMoviePlayerController checkIfFFmpegVersionMatch:YES];
    
    IJKFFOptions *options = [IJKFFOptions optionsByDefault];
    [options setPlayerOptionIntValue:5 forKey:@"framedrop"];
    [options setFormatOptionValue:self.cookie forKey:@"user-agent"];
    [options setOptionValue:@"1" forKey:@"dns_cache_clear" ofCategory:kIJKFFOptionCategoryFormat];
    NSURL *url = [NSURL URLWithString:self.src];
    if (!url)
    {
        return ;
    }
    self.player = [[IJKFFMoviePlayerController alloc] initWithContentURL:url withOptions:options];
    self.player.shouldAutoplay = NO;
    self.player.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    self.player.scalingMode = IJKMPMovieScalingModeAspectFit;
    if (self.delegate)
    {
        [self.delegate OnLoadStart:@{@"src": @{
                                             @"uri": self.src,
                                             @"isNetwork": [NSNumber numberWithBool:![url isFileURL]]
                                             }}];
    }
}

- (void)destoryPlayer
{
    [self removeMovieNotificationObservers];
    [self removePlayerTimer];
    if (self.player) {
        [self.player stop];
        [self.player shutdown];
        [self.player.view removeFromSuperview];
        self.player = nil;
    }
}

#pragma mark - timer

- (void)initPlayerTimer
{
    NSString *timerName = [NSString stringWithFormat:@"timer_%p", self];
    
    [[JX_GCDTimerManager sharedInstance] scheduledDispatchTimerWithName:timerName
                                                           timeInterval:0.25
                                                                  queue:nil
                                                                repeats:YES
                                                           actionOption:AbandonPreviousAction
                                                                 action:^{
                                                                     dispatch_async(dispatch_get_main_queue(), ^{
                                                                         [self progressTimer];
                                                                     });
                                                                 }];
}

- (void)removePlayerTimer
{
    NSString *timerName = [NSString stringWithFormat:@"timer_%p", self];
    [[JX_GCDTimerManager sharedInstance] cancelTimerWithName:timerName];
}

- (void)progressTimer
{
    if (self.player && !self.seeking && self.delegate && !self.paused)
    {
        [self.delegate OnProgress:@{@"currentTime": [NSNumber numberWithDouble:self.player.currentPlaybackTime],
                                    @"playableDuration": [NSNumber numberWithDouble:self.player.playableDuration],
                                    @"duration": [NSNumber numberWithDouble:self.player.duration]
                                    }];
    }
}

#pragma mark - observers

- (void)initNotificationObservers
{
    if (!_player || self.notificationInited) {
        return ;
    }
    
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(loadStateDidChange:)
                                                 name:IJKMPMoviePlayerLoadStateDidChangeNotification
                                               object:_player];
    
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(moviePlayBackDidFinish:)
                                                 name:IJKMPMoviePlayerPlaybackDidFinishNotification
                                               object:_player];
    
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(mediaIsPreparedToPlayDidChange:)
                                                 name:IJKMPMediaPlaybackIsPreparedToPlayDidChangeNotification
                                               object:_player];
    
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(moviePlayBackStateDidChange:)
                                                 name:IJKMPMoviePlayerPlaybackStateDidChangeNotification
                                               object:_player];
    
    self.notificationInited = YES;
}

-(void)removeMovieNotificationObservers
{
    [[NSNotificationCenter defaultCenter]removeObserver:self name:IJKMPMoviePlayerLoadStateDidChangeNotification object:_player];
    [[NSNotificationCenter defaultCenter]removeObserver:self name:IJKMPMoviePlayerPlaybackDidFinishNotification object:_player];
    [[NSNotificationCenter defaultCenter]removeObserver:self name:IJKMPMediaPlaybackIsPreparedToPlayDidChangeNotification object:_player];
    [[NSNotificationCenter defaultCenter]removeObserver:self name:IJKMPMoviePlayerPlaybackStateDidChangeNotification object:_player];
    self.notificationInited = NO;
}

- (void)loadStateDidChange:(NSNotification*)notification
{
    IJKMPMovieLoadState loadState = _player.loadState;
    
    if (loadState & IJKMPMovieLoadStatePlayable && self.delegate) {
        [self.delegate OnLoad:@{@"duration": [NSNumber numberWithDouble: self.player.duration],
                                @"currentTime": [NSNumber numberWithDouble: self.player.currentPlaybackTime],
                                @"naturalSize": @{
                                            @"width": [NSNumber numberWithFloat:self.player.naturalSize.width],
                                            @"height": [NSNumber numberWithFloat:self.player.naturalSize.height]
                                        }
                                }];
    }
    
    if (loadState & IJKMPMovieLoadStatePlaythroughOK && self.delegate) {
        [self.delegate OnLoadResume];
    }
    else if (loadState & IJKMPMovieLoadStateStalled && self.delegate) {
        [self.delegate OnLoadStalled];
    }
}

- (void)moviePlayBackDidFinish:(NSNotification*)notification
{
    [self removePlayerTimer];
    [self removeMovieNotificationObservers];
    self.currentTime = 0;
    self.paused = YES;
    
    int reason = [[[notification userInfo] valueForKey:IJKMPMoviePlayerPlaybackDidFinishReasonUserInfoKey] intValue];
    
    switch (reason)
    {
        case IJKMPMovieFinishReasonPlaybackEnded:
            if (_repeat) {
                [self initPlayerTimer];
                [self initNotificationObservers];
                self.currentTime = 0;
                self.paused = NO;
            }
            else
            {
                if (self.delegate)
                {
                    [self.delegate OnProgress:@{@"currentTime": [NSNumber numberWithDouble:self.player.duration],
                                                @"playableDuration": [NSNumber numberWithDouble:self.player.duration],
                                                @"duration": [NSNumber numberWithDouble:self.player.duration]
                                                }];
                }
            }
            break;
        case IJKMPMovieFinishReasonUserExited:
            
            break;
        case IJKMPMovieFinishReasonPlaybackError:
            if (self.delegate)
            {
                [self.delegate OnError:@{@"error": @{@"code": [NSNumber numberWithInteger:reason]}}];
            }
            break;
        default:
            NSLog(@"playbackPlayBackDidFinish: ???: %d\n", reason);
            break;
    }
    
    if (self.delegate)
    {
        [self.delegate OnEnd];
        if (self.player)
        {
            [self destoryPlayer];
        }
        [self initPlayer];
        [self initPlayerTimer];
        [self initNotificationObservers];
        [self.player prepareToPlay];
        
        if (self.parent)
        {
            self.parent = self.parent;
        }
    }
}

- (void)mediaIsPreparedToPlayDidChange:(NSNotification*)notification
{
    if (self.delegate)
    {
        [self.delegate OnReayForPlay];
    }
    
    [self.player setPlaybackRate:self.rate];
    
    if (self.currentTime > 0) {
        [self.player setCurrentPlaybackTime:self.currentTime];
    }
    
    if (self.muted)
    {
        [self.player setPlaybackVolume:0.0f];
    }
    else
    {
        [self.player setPlaybackVolume:self.volume];
    }
    
    if (!_paused && !_player.shouldAutoplay)
    {
        [self.player play];
    }
}

- (void)moviePlayBackStateDidChange:(NSNotification*)notification
{
    int state = [_player playbackState];
    
    NSLog(@"--------state----------:%d", state);
    
    switch (state)
    {
        case IJKMPMoviePlaybackStateStopped:
            break;
        case IJKMPMoviePlaybackStatePlaying:
            self.seeking = NO;
            if (self.delegate)
            {
                [self.delegate OnPlaybackResume];
            }
            break;
        case IJKMPMoviePlaybackStatePaused:
            if (self.delegate)
            {
                [self.delegate OnPlaybackStalled];
            }
            break;
        case IJKMPMoviePlaybackStateInterrupted:
            break;
        case IJKMPMoviePlaybackStateSeekingForward:
        case IJKMPMoviePlaybackStateSeekingBackward:
            self.seeking = YES;
            break;
        default:
            break;
    }
}

#pragma mark - property

- (void)setSrc:(NSString *)src
{
    _src = src;
    if(!_cookie && [src hasSuffix:@".m3u8"]) {
        return;
    }
    
    if (self.player)
    {
        [self destoryPlayer];
    }
    [self initPlayer];
    [self initPlayerTimer];
    [self initNotificationObservers];
    [self.player prepareToPlay];
    
    if (self.parent)
    {
        self.parent = self.parent;
    }
}
- (void)setCookie:(NSString *)cookie
{
    _cookie = cookie;
    if (_src && [_src hasSuffix:@".m3u8"]) {
        [self setSrc:_src];
    }
}
-(void) setDisplayText:(NSString *)displayText
{
    _displayText = displayText;
}
-(void) setDisplayDelay:(float)displayDelay
{
    _displayDelay = displayDelay / 1000;
}

-(void) setDisplayTextSize:(float)displayTextSize
{
    _displayTextSize = displayTextSize;
}
- (void)setParent:(UIView *)parent
{
    _parent = parent;
    
    if (!self.player)
    {
        return ;
    }
    
    [self.player.view removeFromSuperview];
    
    if (parent)
    {
        self.player.view.frame = parent.bounds;
        [parent addSubview:self.player.view];
    }
}

- (void)setPaused:(BOOL)paused
{
    _paused = paused;
    
    if (paused)
    {
        [self.player pause];
//        if(self.delegate)
//        {
//            [self.delegate removePlayerTimer];
//        }
    }
    else
    {
        [self initPlayerTimer];
        [self initNotificationObservers];
        [self.player play];
        if (self.delegate && _displayDelay != 0) {
            [self.delegate initTimer];
        }
    }
}

- (void)setMuted:(BOOL)muted
{
    _muted = muted;
    
    if (muted)
    {
        [self.player setPlaybackVolume:0.0f];
    }
    else
    {
        [self.player setPlaybackVolume:_volume];
    }
}

- (void)setFullscreen:(BOOL)fs
{
    _fullscreen = fs;
}

- (void)setVolume:(float)volume
{
    _volume = volume;
    
    [self.player setPlaybackVolume:volume];
}

- (void)setRate:(float)rate
{
    if (_rate == rate) {
        return ;
    }
    
    _rate = rate;
    
    [self.player setPlaybackRate:rate];
    if (self.delegate)
    {
        [self.delegate OnPlaybackRateChange:@{@"playbackRate": [NSNumber numberWithDouble:rate]}];
    }
}

- (void)setCurrentTime:(float)currentTime
{
    if (_currentTime == currentTime) {
        return ;
    }
    
    _currentTime = currentTime;
    [self.player setCurrentPlaybackTime:currentTime];
    
    if (self.delegate)
    {
        [self.delegate OnSeek:@{@"currentTime": [NSNumber numberWithFloat:currentTime],
                                @"seekTime": [NSNumber numberWithFloat: currentTime]
                                }];
    }
}

- (void)stop
{
    if (self.player)
    {
        [self destoryPlayer];
    }
}

@end
