//
//  SLNuisdkPlay.m
//  SLAiELTS
//
//  Created by Gusont on 2023/3/2.
//

#import "SLNuisdkPlay.h"
#import <nuisdk/NeoNuiTts.h>
#import "NLSPlayAudio.h"
#import "NuiSdkUtils.h"

#import <AVFoundation/AVFoundation.h>
#import <AdSupport/ASIdentifierManager.h>
#import <MediaPlayer/MediaPlayer.h>

@interface SLNuisdkPlay ()<NlsPlayerDelegate, NeoNuiTtsDelegate, AVAudioPlayerDelegate>

@property(nonatomic,strong) NLSPlayAudio *voicePlayer;

@property(nonatomic,strong) NeoNuiTts* nui;

@property(nonatomic,strong) NuiSdkUtils *utils;

@property (nonatomic, strong) AVAudioPlayer *audioPlayer;

@property (nonatomic, copy) SLNuisdkPlayFinshBlock finshBlock;

@property (nonatomic, assign) NSInteger currentPlay;

@property (nonatomic, strong) NSMutableArray *ttStringArr;

@end

static int loop_in = 0;
static BOOL loop_flag = NO;

@implementation SLNuisdkPlay

- (instancetype)init {
    self = [super init];
    if (self) {
        [self confignTTSPlayer];
    }
    return self;
}

-(void)dealloc {
    TLog(@"%s---%@",__FUNCTION__, @"stopNuisdkPlay");
    [_voicePlayer cleanup];
    [_nui nui_tts_release];
#ifdef DEBUG_TTS_DATA_SAVE
//    if (fp) {
//        fclose(fp);
//    }
#endif
}

- (void)confignTTSPlayer
{
    loop_in = TTS_EVENT_END;
    _voicePlayer = [[NLSPlayAudio alloc] init];
    _voicePlayer.delegate = self;
    _utils = [[NuiSdkUtils alloc] init];
    [self NuiTtsInit];
}

- (void)playerDidFinish {
    if (self.ttStringArr.count == self.currentPlay + 1) {
        NSLog(@"----->>>playerDidFinish");
        if (self.finshBlock) {
            self.finshBlock();
        }
    }else {
        self.currentPlay ++;
        [self.nui nui_tts_play:"1" taskId:"" text:[self.ttStringArr[self.currentPlay] UTF8String]];
    }
    
}

- (void)NuiTtsInit {
    if (_nui == NULL) {
        _nui = [NeoNuiTts get_instance];
        _nui.delegate = self;
    }
    //请注意此处的参数配置，其中账号相关需要在Utils.m getTicket 方法中填入后才可访问服务
    NSString * initParam = [self genInitParams];

    int retcode = [_nui nui_tts_initialize:[initParam UTF8String] logLevel:LOG_LEVEL_VERBOSE saveLog:YES];
    if (retcode != 0) {
         TLog(@"init failed.retcode:%d", retcode);
         return;
     }
#ifdef DEBUG_TTS_DATA_SAVE
    NSString *sp = self.createDir;
    const char* savePath = [sp UTF8String];

    if (fp == nullptr) {
        NSString *debug_file = [NSString stringWithFormat:@"%@/tts_dump.pcm", sp];
        fp = fopen([debug_file UTF8String], "w");
    }
#endif
}

#pragma mark -private methods

-(NSString *)genInitParams {
    NSString *strResourcesBundle = [[NSBundle mainBundle] pathForResource:@"Resources" ofType:@"bundle"];
    NSString *bundlePath = [[NSBundle bundleWithPath:strResourcesBundle] resourcePath];
    NSString *id_string = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
    NSString *debug_path = [_utils createDir];

    NSMutableDictionary *dictM = [NSMutableDictionary dictionary];
    
    [dictM setObject:bundlePath forKey:@"workspace"];
    [dictM setObject:debug_path forKey:@"debug_path"];
    [dictM setObject:id_string forKey:@"device_id"];
    
    //从阿里云获取appkey和token进行语音服务访问
    [dictM setObject:SLNuisdkAppKey forKey:@"app_key"];
//    [dictM setObject:SLNuisdkToken forKey:@"token"];

    //由于token 24小时过期，可以参考getTicket实现从阿里云服务动态获取
    [_utils getTicket:dictM];
    [dictM setObject:@"wss://nls-gateway.cn-shanghai.aliyuncs.com:443/ws/v1" forKey:@"url"];
    
    NSData *data = [NSJSONSerialization dataWithJSONObject:dictM options:NSJSONWritingPrettyPrinted error:nil];
    NSString * jsonStr = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
    return jsonStr;
}

- (void)playSendVoice:(MessageModel *)model {
    [self stopNuisdkPlay];
    self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:model.voicePath] error:nil];
    self.audioPlayer.delegate = self;
    [self.audioPlayer play];
}
/*支持一次性合成300字符以内的文字，其中1个汉字、1个英文字母、1个标点或1个句子中间空格均算作1个字符，
 超过300个字符的内容将会截断*/
- (void)startTTSWith:(NSString *)ttString roleModel:(RoleModel *)roleModel finshBlock:(SLNuisdkPlayFinshBlock)finshBlock {
    if (!self.nui) {
        TLog(@"tts not init");
        return;
    }
    dispatch_async(dispatch_get_main_queue(), ^{
        self.finshBlock = finshBlock;
        [self updateTtsParams:roleModel];
        AVAudioSession *audioSession = [AVAudioSession sharedInstance];
        [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:nil];
        // 如果上个任务没有合成完毕，手动取消，开始合成新的任务
        [self stopNuisdkPlay];
        
        NSInteger ttCount = ceil(ttString.length / 300.0);
        self.currentPlay = 0;
        NSInteger idx = 0;
        [self.ttStringArr removeAllObjects];
        NSInteger m = 300;
        for (NSInteger i = 1; i < ttCount + 1; i ++) {
            for (NSInteger j = 0; j < 15 ; j ++) {
                NSString *t = [ttString substringWithRange:NSMakeRange(MIN(300 + idx - j, ttString.length - 1), 1)];
                if ([t isEqualToString:@" "]) {
                    m = 300 - j;
                    break;
                }
                
            }
            NSString * str = [ttString substringWithRange:NSMakeRange(idx, MIN(m, ttString.length - idx))];
            idx += m;
            [self.ttStringArr addObject:str];
        }
        [self.nui nui_tts_play:"1" taskId:"" text:[self.ttStringArr.firstObject UTF8String]];
    });
}

- (void)stopNuisdkPlay {
    [self.nui nui_tts_cancel:NULL];
    [self->_voicePlayer stop];
    if (self.audioPlayer) {
        [self.audioPlayer pause];
        self.audioPlayer = nil;
    }
}

- (void)updateTtsParams:(RoleModel *)roleModel {
    NSString *fontName = @"luna";
    if ([roleModel.language isEqualToString:@"1"]) {
        fontName = @"luna";
        if ([roleModel.dataSex isEqualToString:@"男"]) {
            fontName = @"luca";
        }
    }else {
        fontName = @"abby";
        if ([roleModel.dataSex isEqualToString:@"男"]) {
            fontName = @"andy";
        }
    }
    [self.nui nui_tts_set_param:"font_name" value:[fontName UTF8String]];
    [self.nui nui_tts_set_param:"speed_level" value:[roleModel.speechRate UTF8String]];
    [self.nui nui_tts_set_param:"mode_type" value:"2"];
    [self.nui nui_tts_set_param:"enable_subtitle" value:"1"];
}


#pragma mark - tts callback
- (void)onNuiTtsEventCallback:(NuiSdkTtsEvent)event taskId:(char*)taskid code:(int)code {
    TLog(@"onNuiTtsEventCallback event[%d]", event);
    if (event == TTS_EVENT_START) {
        loop_in = TTS_EVENT_START;
        // 启动播放器
        [self->_voicePlayer play];
    } else if (event == TTS_EVENT_END || event == TTS_EVENT_CANCEL || event == TTS_EVENT_ERROR) {
        loop_in = event;
        if (event == TTS_EVENT_END) {
            // 注意这里的event事件是指语音合成完成，而非播放完成，播放完成需要由voicePlayer对象来进行通知
            [self->_voicePlayer drain];
        } else {
            // 取消播报、或者发生异常时终止播放
            [self->_voicePlayer stop];
        }
        dispatch_async(dispatch_get_main_queue(), ^{

        });
    }
}

- (void)onNuiTtsUserdataCallback:(char*)info infoLen:(int)info_len buffer:(char*)buffer len:(int)len taskId:(char*)task_id {
    TLog(@"onnuiTtsUserdataCallback info text %s index %d", info, info_len);
    if (len > 0) {
        [_voicePlayer write:(char*)buffer Length:(unsigned int)len];
    }
}

-(void)onNuiTtsVolumeCallback:(int)volume taskId:(char*)task_id {
    
}

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
    if (player == _audioPlayer && flag) {
        [_audioPlayer pause];
        _audioPlayer = nil;
        NSLog(@"----audioPlayerDidFinishPlaying");
    }
}

- (void)audioPlayerBeginInterruption:(AVAudioPlayer *)player {
    if (player == _audioPlayer){
        NSLog(@"播放被中断");
        [_audioPlayer pause];
        _audioPlayer = nil;
        NSLog(@"----audioPlayerDidFinishPlaying");
    }
}

- (NSMutableArray *)ttStringArr {
    if (!_ttStringArr) {
        _ttStringArr = [NSMutableArray array];
    }
    return _ttStringArr;
}


@end
