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

#import "RCTAudioManager.h"
#import "RCTAudio.h"
#import "RCTAudioEvent.h"

@interface RCTAudioManager()
{
    unsigned long long _nextAudioId;
    BOOL hasListeners;
}

@property (nonatomic, strong) NSMutableDictionary* audios;

@end

@implementation RCTAudioManager

- (instancetype)init
{
    if (self = [super init])
    {
        self.audios = [[NSMutableDictionary alloc] init];
    }
    
    return self;
}

- (dispatch_queue_t)methodQueue
{
  return dispatch_get_main_queue();
}

RCT_EXPORT_MODULE(OMAudioPlayerManager);

- (NSArray<NSString *> *)supportedEvents
{
    return @[
             EVENT_OM_AUDIO_LOAD_START,
             EVENT_OM_AUDIO_LOAD,
             EVENT_OM_AUDIO_LOAD_STALLED,
             EVENT_OM_AUDIO_LOAD_RESUME,
             EVENT_OM_AUDIO_ERROR,
             EVENT_OM_AUDIO_PROGRESS,
             EVENT_OM_AUDIO_SEEK,
             EVENT_OM_AUDIO_END,
             EVENT_OM_AUDIO_READY_FOR_PLAY,
             EVENT_OM_AUDIO_STALLED,
             EVENT_OM_AUDIO_RESUME,
             EVENT_OM_AUDIO_RATE_CHANGE,
             EVENT_OM_AUDIO_PLAYER_ERROR
             ];
}

- (NSDictionary *)constantsToExport
{
    return @{ EVENT_OM_AUDIO_LOAD_START: EVENT_OM_AUDIO_LOAD_START,
              EVENT_OM_AUDIO_LOAD: EVENT_OM_AUDIO_LOAD,
              EVENT_OM_AUDIO_LOAD_STALLED: EVENT_OM_AUDIO_LOAD_STALLED,
              EVENT_OM_AUDIO_LOAD_RESUME: EVENT_OM_AUDIO_LOAD_RESUME,
              EVENT_OM_AUDIO_ERROR: EVENT_OM_AUDIO_ERROR,
              EVENT_OM_AUDIO_PROGRESS: EVENT_OM_AUDIO_PROGRESS,
              EVENT_OM_AUDIO_SEEK: EVENT_OM_AUDIO_SEEK,
              EVENT_OM_AUDIO_END: EVENT_OM_AUDIO_END,
              EVENT_OM_AUDIO_READY_FOR_PLAY: EVENT_OM_AUDIO_READY_FOR_PLAY,
              EVENT_OM_AUDIO_STALLED: EVENT_OM_AUDIO_STALLED,
              EVENT_OM_AUDIO_RESUME: EVENT_OM_AUDIO_RESUME,
              EVENT_OM_AUDIO_RATE_CHANGE: EVENT_OM_AUDIO_RATE_CHANGE,
              EVENT_OM_AUDIO_PLAYER_ERROR: EVENT_OM_AUDIO_PLAYER_ERROR
              };
}

- (unsigned long long)getAudioId
{
    @synchronized (self) {
        _nextAudioId++;
    }
    
    return _nextAudioId;
}

- (RCTAudio*)getAudio: (NSNumber* __nonnull)audioId
{
    RCTAudio *audio = (RCTAudio*)[self.audios objectForKey:audioId];
    
    return audio;
}

- (void)setAudio:(RCTAudio*)audio withAudioId:(NSNumber* __nonnull)audioId
{
    [self.audios setObject:audio forKey:audioId];
}

- (void)sendEvent:(NSString *)event withBody:(id)body
{
    if (hasListeners)
    {
        [self sendEventWithName:event body: body];
    }
}

- (void)startObserving
{
    hasListeners = YES;
}

- (void)stopObserving
{
    hasListeners = NO;
}

RCT_EXPORT_METHOD(createAudioPlayer:(RCTResponseSenderBlock)callback)
{
    RCTAudio *audio = [[RCTAudio alloc] init];
    NSNumber *audioId = [NSNumber numberWithUnsignedLongLong:[self getAudioId]];
    audio.delegate = self;
    audio.playerId = [audioId unsignedLongLongValue];
    [self setAudio:audio withAudioId:audioId];
    
    callback(@[[NSNull null], audioId]);
}

RCT_EXPORT_METHOD(releaseAudioPlayer:(NSNumber* __nonnull)audioId)
{
    RCTAudio *audio = [self getAudio:audioId];
    [audio releaseResource];
    
    [self.audios removeObjectForKey:audioId];
}

RCT_EXPORT_METHOD(setSrc:(NSString*)src
                  withAudioId:(NSNumber* __nonnull)audioId)
{
    RCTAudio *audio = [self getAudio:audioId];
    if (audio)
    {
        audio.player.src = src;
    }
    else
    {
        [self sendEvent:EVENT_OM_AUDIO_PLAYER_ERROR withBody: @{@"id": audioId}];
    }
}

RCT_EXPORT_METHOD(setToken:(NSString*)cookie
                  withAudioId:(NSNumber* __nonnull)audioId)
{
    RCTAudio *audio = [self getAudio:audioId];
    NSString *ijkCookie = [NSString stringWithFormat: @"ijkplayer_%@", cookie];
    if (audio)
    {
        [audio.player setCookie: ijkCookie];
    }
    else
    {
        [self sendEvent:EVENT_OM_AUDIO_PLAYER_ERROR withBody: @{@"id": audioId}];
    }
}

RCT_EXPORT_METHOD(setRepeat:(BOOL)repeat
                  withAudioId:(NSNumber* __nonnull)audioId)
{
    RCTAudio *audio = [self getAudio:audioId];
    if (audio)
    {
        audio.player.repeat = repeat;
    }
    else
    {
        [self sendEvent:EVENT_OM_AUDIO_PLAYER_ERROR withBody: @{@"id": audioId}];
    }
}

RCT_EXPORT_METHOD(setMuted:(BOOL)muted
                  withAudioId:(NSNumber* __nonnull)audioId)
{
    RCTAudio *audio = [self getAudio:audioId];
    if (audio)
    {
        audio.player.muted = muted;
    }
    else
    {
        [self sendEvent:EVENT_OM_AUDIO_PLAYER_ERROR withBody: @{@"id": audioId}];
    }
}

RCT_EXPORT_METHOD(setVolume:(NSNumber* __nonnull)volume
                  withAudioId:(NSNumber* __nonnull)audioId)
{
    RCTAudio *audio = [self getAudio:audioId];
    if (audio)
    {
        audio.player.volume = [volume floatValue];
    }
    else
    {
        [self sendEvent:EVENT_OM_AUDIO_PLAYER_ERROR withBody: @{@"id": audioId}];
    }
}

RCT_EXPORT_METHOD(setRate:(NSNumber* __nonnull)rate
                  withAudioId:(NSNumber* __nonnull)audioId)
{
    RCTAudio *audio = [self getAudio:audioId];
    if (audio)
    {
        audio.player.rate = [rate floatValue];
    }
    else
    {
        [self sendEvent:EVENT_OM_AUDIO_PLAYER_ERROR withBody: @{@"id": audioId}];
    }
}

RCT_EXPORT_METHOD(seek:(NSNumber* __nonnull)seek
                  withAudioId:(NSNumber* __nonnull)audioId)
{
    RCTAudio *audio = [self getAudio:audioId];
    if (audio)
    {
        audio.player.currentTime = [seek doubleValue];
    }
    else
    {
        [self sendEvent:EVENT_OM_AUDIO_PLAYER_ERROR withBody: @{@"id": audioId}];
    }
}

RCT_EXPORT_METHOD(play:(NSNumber* __nonnull)audioId)
{
    RCTAudio *audio = [self getAudio:audioId];
    if (audio)
    {
        audio.player.paused = NO;
    }
    else
    {
        [self sendEvent:EVENT_OM_AUDIO_PLAYER_ERROR withBody: @{@"id": audioId}];
    }
}

RCT_EXPORT_METHOD(pause:(NSNumber* __nonnull)audioId)
{
    RCTAudio *audio = [self getAudio:audioId];
    if (audioId)
    {
        audio.player.paused = YES;
    }
    else
    {
        [self sendEvent:EVENT_OM_AUDIO_PLAYER_ERROR withBody: @{@"id": audioId}];
    }
}

RCT_EXPORT_METHOD(stop:(NSNumber* __nonnull)audioId)
{
    RCTAudio *audio = [self getAudio:audioId];
    if (audio)
    {
        [audio.player stop];
    }
    else
    {
        [self sendEvent:EVENT_OM_AUDIO_PLAYER_ERROR withBody: @{@"id": audioId}];
    }
}

@end
