//
//  CustomVoicePlayer.m
//  support-im-ios-debugdemo
//
//  Created by wangyanxu on 2025/6/16.
//

#import "CustomVoicePlayer.h"
#import <RongIMKit/RongIMKit.h>
#import <AVFoundation/AVFoundation.h>
#import <RongIMKit/RCKitConfig.h>
#import <RongIMKit/RCKitCommonDefine.h>

NSString *const kNotificationStopVoicePlayer = @"kNotificationStopVoicePlayer";

static BOOL bSensorStateStart = YES;
static CustomVoicePlayer *rcVoicePlayerHandler = nil;

@interface CustomVoicePlayer () <AVAudioPlayerDelegate>

@property (nonatomic, strong) AVAudioPlayer *audioPlayer;
@property (nonatomic) BOOL isPlaying;
@property (nonatomic, weak) id<CustomVoicePlayerObserver> voicePlayerObserver;
@property (nonatomic) RCMessageDirection messageDirection;
@property (nonatomic) NSString *playerCategory;

- (void)enableSystemProperties;
- (void)setDefaultAudioSession:(NSString *)category;
- (void)disableSystemProperties;
- (BOOL)startPlayVoice:(NSData *)data;

@end

@implementation CustomVoicePlayer

+ (CustomVoicePlayer *)defaultPlayer {
    @synchronized(self) {
        if (nil == rcVoicePlayerHandler) {
            rcVoicePlayerHandler = [[[self class] alloc] init];
            rcVoicePlayerHandler.playerCategory = AVAudioSessionCategoryPlayback;
        }
    }
    return rcVoicePlayerHandler;
}

- (void)setDefaultAudioSession:(NSString *)category {
    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    DebugLog(@"[RongIMKit]: [audioSession category ] %@", [audioSession category]);
    [audioSession setCategory:category error:nil];
    [audioSession setActive:YES error:nil];
}

- (void)sensorStateChange:(NSNotification *)notification {
    if (bSensorStateStart) {
        bSensorStateStart = NO;
        
        dispatch_async(dispatch_get_main_queue(), ^{
            if ([[UIDevice currentDevice] proximityState] == YES) {
                self.playerCategory = AVAudioSessionCategoryPlayAndRecord;
                DebugLog(@"[RongIMKit]: Device is close to user");
                [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
            } else {
                DebugLog(@"[RongIMKit]: Device is not close to user");
                self.playerCategory = AVAudioSessionCategoryPlayback;
                [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
            }
            bSensorStateStart = YES;
        });
    }
}

- (BOOL)playVoice:(RCConversationType)conversationType
         targetId:(NSString *)targetId
        messageId:(long)messageId
        direction:(RCMessageDirection)messageDirection
        voiceData:(NSData *)data
         observer:(id<CustomVoicePlayerObserver>)observer {
    
    if (self.isPlaying) {
        [self resetPlayer];
    }
    
    self.voicePlayerObserver = observer;
    self.messageId = messageId;
    self.conversationType = conversationType;
    self.targetId = targetId;
    [self enableSystemProperties];
    [self setDefaultAudioSession:_playerCategory];
    
    self.messageDirection = messageDirection;
    
    return [self startPlayVoice:data];
}

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
    DebugLog(@"%s", __FUNCTION__);
    
    self.isPlaying = self.audioPlayer.playing;
    [self disableSystemProperties];
    
    if ([self.voicePlayerObserver respondsToSelector:@selector(PlayerDidFinishPlaying:)]) {
        [self.voicePlayerObserver PlayerDidFinishPlaying:flag];
    }
    
    self.voicePlayerObserver = nil;
    self.audioPlayer = nil;
    if (!RCKitConfigCenter.message.isExclusiveSoundPlayer) {
        [[AVAudioSession sharedInstance] setActive:NO
                                       withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation
                                             error:nil];
    } else {
        AVAudioSession *audioSession = [AVAudioSession sharedInstance];
        [audioSession setCategory:AVAudioSessionCategoryAmbient error:nil];
        [audioSession setActive:YES error:nil];
    }
    
    [self sendPlayFinishNotification];
    [self sendContinuousPlayNotification];
}

- (void)sendContinuousPlayNotification {
    [[NSNotificationCenter defaultCenter] postNotificationName:@"RCContinuousPlayNotification"
                                                        object:@(self.messageId)
                                                      userInfo:@{
                                                          @"conversationType" : @(self.conversationType),
                                                          @"targetId" : self.targetId
                                                      }];
}

- (void)sendPlayStartNotification {
    [[NSNotificationCenter defaultCenter] postNotificationName:@"kNotificationPlayVoice"
                                                        object:@(self.messageId)
                                                      userInfo:@{
                                                          @"conversationType" : @(self.conversationType),
                                                          @"targetId" : self.targetId
                                                      }];
}

- (void)sendPlayFinishNotification {
    [[NSNotificationCenter defaultCenter] postNotificationName:kNotificationStopVoicePlayer
                                                        object:@(self.messageId)
                                                      userInfo:@{
                                                          @"conversationType" : @(self.conversationType),
                                                          @"targetId" : self.targetId
                                                      }];
}

- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error {
    DebugLog(@"%s", __FUNCTION__);
    self.isPlaying = self.audioPlayer.playing;
    [self disableSystemProperties];
    
    if ([self.voicePlayerObserver respondsToSelector:@selector(audioPlayerDecodeErrorDidOccur:)]) {
        [self.voicePlayerObserver audioPlayerDecodeErrorDidOccur:error];
    }
    self.voicePlayerObserver = nil;
    self.audioPlayer = nil;
    if (!RCKitConfigCenter.message.isExclusiveSoundPlayer) {
        [[AVAudioSession sharedInstance] setActive:NO
                                       withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation
                                             error:nil];
    } else {
        AVAudioSession *audioSession = [AVAudioSession sharedInstance];
        [audioSession setCategory:AVAudioSessionCategoryAmbient error:nil];
        [audioSession setActive:YES error:nil];
    }
    [self sendPlayFinishNotification];
}

- (BOOL)startPlayVoice:(NSData *)data {
    NSError *error = nil;
    
    self.audioPlayer = [[AVAudioPlayer alloc] initWithData:data error:&error];
    self.audioPlayer.delegate = self;
    self.audioPlayer.volume = 1.0;
    
    BOOL ready = NO;
    if (!error) {
        DebugLog(@"[RongIMKit]: init AudioPlayer %@", error);
        
        ready = [self.audioPlayer prepareToPlay];
        DebugLog(@"[RongIMKit]: prepare audio player %@", ready ? @"success" : @"failed");
        ready = [self.audioPlayer play];
        DebugLog(@"[RongIMKit]: async play is %@", ready ? @"success" : @"failed");
        if (ready) {
            [self sendPlayStartNotification];
        }
    }
    self.isPlaying = self.audioPlayer.playing;
    DebugLog(@"self.isPlaying > %d", self.isPlaying);
    DebugLog(@"[RongIMKit]: [audioSession category ] %@", [[AVAudioSession sharedInstance] category]);
    return ready;
}

- (void)stopPlayVoice {
    [self resetPlayer];
    if (!RCKitConfigCenter.message.isExclusiveSoundPlayer) {
        [[AVAudioSession sharedInstance] setActive:NO
                                       withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation
                                             error:nil];
    } else {
        AVAudioSession *audioSession = [AVAudioSession sharedInstance];
        [audioSession setCategory:AVAudioSessionCategoryAmbient error:nil];
        [audioSession setActive:YES error:nil];
    }
}

- (void)resetPlayer {
    if (nil != self.audioPlayer && self.audioPlayer.playing) {
        [self.audioPlayer stop];
        self.audioPlayer = nil;
        
        [self sendPlayFinishNotification];
        [self disableSystemProperties];
    }
    self.isPlaying = self.audioPlayer.playing;
    self.voicePlayerObserver = nil;
}

- (void)enableSystemProperties {
    [[UIDevice currentDevice] setProximityMonitoringEnabled:YES];
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIDeviceProximityStateDidChangeNotification
                                                  object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(sensorStateChange:)
                                                 name:UIDeviceProximityStateDidChangeNotification
                                               object:nil];
    [[UIApplication sharedApplication] setIdleTimerDisabled:YES];
}

- (void)disableSystemProperties {
    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC));
    dispatch_after(time, dispatch_get_main_queue(), ^(void) {
        if (!self.isPlaying) {
            self.playerCategory = AVAudioSessionCategoryPlayback;
            [[UIDevice currentDevice] setProximityMonitoringEnabled:NO];
            [[NSNotificationCenter defaultCenter] removeObserver:self
                                                            name:UIDeviceProximityStateDidChangeNotification
                                                          object:nil];
        }
    });
    [[UIApplication sharedApplication] setIdleTimerDisabled:NO];
}

@end 