//
//  IFlySpeech.m
//  MobilePortal
//
//  Created by xiejiangbo on 2019/9/3.
//  Copyright © 2019 yin chen. All rights reserved.
//

#import "IFlySpeech.h"
#import <iflyAIUI/iflyAIUI.h>
#import <QuartzCore/QuartzCore.h>

@protocol IFlySpeechDataIntentSemanticSlots;
@interface IFlySpeechDataIntentSemanticSlots : JSONModel
@property NSString<Optional>*begin;
@property NSString<Optional>*end;
@property NSString<Optional>*name;
@property NSString<Optional>*normValue;
@property NSString<Optional>*value;
@end
@implementation IFlySpeechDataIntentSemanticSlots
@synthesize description;
@end

@protocol IFlySpeechDataIntentSemantic;
@interface IFlySpeechDataIntentSemantic : JSONModel
@property NSString<Optional>*template;
@property NSString<Optional>*entrypoint;
@property NSString<Optional>*hazard;
@property NSString<Optional>*intent;
@property NSString<Optional>*score;
@property NSMutableArray <IFlySpeechDataIntentSemanticSlots,Optional>* slots;
@end
@implementation IFlySpeechDataIntentSemantic
@synthesize description;
@end


@protocol IFlySpeechDataIntentAnswer;
@interface IFlySpeechDataIntentAnswer : JSONModel
@property NSString<Optional>*text;
@property NSString<Optional>*type;

@end
@implementation IFlySpeechDataIntentAnswer
@synthesize description;
@end

@protocol IFlySpeechDataIntent;
@interface IFlySpeechDataIntent : JSONModel
@property NSString<Optional>*category;
@property NSString<Optional>*sessionIsEnd;
@property NSString<Optional>*shouldEndSession;
@property NSString<Optional>*text;
@property NSString<Optional>*result;
@property NSString<Optional>*rc;
@property NSString<Optional>*sid;
@property IFlySpeechDataIntentAnswer<Optional> *answer;
@property NSMutableArray <IFlySpeechDataIntentSemantic,Optional>* semantic;
@end
@implementation IFlySpeechDataIntent
@synthesize description;
@end


@protocol IFlySpeechData;
@interface IFlySpeechData : JSONModel
@property IFlySpeechDataIntent *intent;
@end
@implementation IFlySpeechData
@synthesize description;
@end


@interface IFlySpeech() <IFlyAIUIListener>
@property IFlyAIUIAgent *aiuiAgent;
@property (nonatomic, readwrite) BOOL autoTTS;
@property (nonatomic, copy) NSString *globalSid;
@property (nonatomic, readwrite) int aiuiState;
@property (copy) void (^completeBlock)(NSObject *aiuiInfo,NSObject *userInfo);
@property (copy) void (^errorBlock)(void);
@property (copy) void (^actionValueBlock)(NSObject *value);
//@property (nonatomic, strong) IFlyAIUILocationRequest* mLocationRequest;
@end
@implementation IFlySpeech
+ (IFlySpeech *)ShareIFlySpeech{
    static IFlySpeech *iFlySpeech = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        iFlySpeech = [[IFlySpeech alloc]init];
    });
    return iFlySpeech;
}
-(void)initIfly{
    
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    [IFlyAIUISetting setSaveDataLog:NO];
    [IFlyAIUISetting setLogLevel:LV_INFO];
    [IFlyAIUISetting setAIUIDir:paths[0]];
    [IFlyAIUISetting setMscDir:paths[0]];
}
-(void)setBlock:(void(^)(NSObject *aiuiInfo,NSObject *userInfo))completeBlock andErrotBlock:(void(^)(void))errotBlock{
    _completeBlock = completeBlock;
    _errorBlock = errotBlock;
}
-(void)getActionValueBlock:(void(^)(NSObject *value))actionValueBlock{
    _actionValueBlock = actionValueBlock;
}
-(void)initIFlyAIUIAgent{
    _autoTTS = YES;
    // 读取aiui.cfg配置文件
    NSString *cfgFilePath = [[NSBundle mainBundle] pathForResource:@"aiui" ofType:@"cfg"];
    NSString *cfg = [NSString stringWithContentsOfFile:cfgFilePath encoding:NSUTF8StringEncoding error:nil];
    //创建AIUIAgent
    _aiuiAgent = [IFlyAIUIAgent createAgent:cfg withListener:self];
    //发送唤醒消息
    IFlyAIUIMessage *wakeuMsg = [[IFlyAIUIMessage alloc]init];
    wakeuMsg.msgType = CMD_WAKEUP;
    [_aiuiAgent sendMessage:wakeuMsg];
    NSString *params;
    if (!_autoTTS) {
        //由sdk内部进行合成
        params = @"{\"tts\":{\"play_mode\":\"sdk\"}}";
        _autoTTS = YES;
    } else {
        //sdk不自动合成，抛出EVENT_RESULT事件包含音频数据开发者自己处理
        params = @"{\"tts\":{\"play_mode\":\"user\"}}";
        _autoTTS = NO;
    }
    //设置参数
    IFlyAIUIMessage *msg = [[IFlyAIUIMessage alloc] init];
    msg.msgType = CMD_SET_PARAMS;
    msg.params = params;
    [_aiuiAgent sendMessage:msg];
}
// 开始
-(void)startParsing{
    if (_aiuiAgent == nil)
    {
        return;
    }
    if (self.aiuiState == STATE_IDLE) {
        //[_popUpView showText:NSLocalizedString(@"agentNull", nil)];
        return;
    }
    
    if (self.aiuiState == STATE_READY) {
        IFlyAIUIMessage *msg = [[IFlyAIUIMessage alloc] init];
        msg.msgType = CMD_WAKEUP;
        [_aiuiAgent sendMessage:msg];
    }
    [self stopAutoTTS];
    IFlyAIUIMessage *msg = [[IFlyAIUIMessage alloc] init];
    msg.msgType = CMD_START_RECORD;
    [_aiuiAgent sendMessage:msg];
//    VoiceWaveView.share().startVoice()
    [[VoiceWaveView ShareVoiceWaveView] StartVoice];
}
//取消合成
- (void)stopAutoTTS
{
    IFlyAIUIMessage *msg = [[IFlyAIUIMessage alloc] init];
    msg.msgType = CMD_TTS;
    msg.arg1 = TTS_CANCEL;
    [_aiuiAgent sendMessage:msg];
}
//停止录音
- (void)stopRecord{
    [[VoiceWaveView ShareVoiceWaveView] EndVoice];
    IFlyAIUIMessage *msg = [[IFlyAIUIMessage alloc] init];
    msg.msgType = CMD_STOP_RECORD;
    [_aiuiAgent sendMessage:msg];
}
//处理结果
- (void)processResult:(IFlyAIUIEvent *)event{
    
    NSString *info = event.info;
    NSData *infoData = [info dataUsingEncoding:NSUTF8StringEncoding];
    NSError *err;
    NSDictionary *infoDic = [NSJSONSerialization JSONObjectWithData:infoData options:NSJSONReadingMutableContainers error:&err];
    if(!infoDic){
        NSLog(@"parse error! %@", info);
        return;
    }
    
    //NSLog(@"infoDic = %@", infoDic);
    
    NSDictionary *data = [((NSArray *)[infoDic objectForKey:@"data"]) objectAtIndex:0];
    NSDictionary *params = [data objectForKey:@"params"];
    NSDictionary *content = [(NSArray *)[data objectForKey:@"content"] objectAtIndex:0];
    NSString *sub = [params objectForKey:@"sub"];
    
    if([sub isEqualToString:@"nlp"]){
        
        NSString *cnt_id = [content objectForKey:@"cnt_id"];
        if(!cnt_id){
            NSLog(@"Content Id is empty");
            return;
        }
        
        NSData *rltData = [event.data objectForKey:cnt_id];
        if(rltData){
            NSString *rltStr = [[[NSString alloc]initWithData:rltData encoding:NSUTF8StringEncoding] stringByReplacingOccurrencesOfString:@"\0" withString:@""];
            
            NSLog(@"nlp result: %@", rltStr);
            if (rltStr.length > 20)
            {
                NSData *data = [rltStr dataUsingEncoding:NSUTF8StringEncoding];
                NSDictionary *rstDic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
                NSError *error;
                IFlySpeechData *dataModel = [[IFlySpeechData  alloc]initWithDictionary:rstDic error:(NSError **)&error];
                if (error) {
                    NSLog(@"IFlySpeechData Error===%@",error);
                }
                NSLog(@"text is  %@", dataModel.intent.text);
                NSLog(@"answer is  %@",  dataModel.intent.answer.text);
                if ([dataModel.intent.rc isEqualToString:@"0"]) {
                    [self processingModel:dataModel];
                    [self answerTextJudge:dataModel.intent.answer.text];
                    if (self.completeBlock != nil) {
                        self.completeBlock([self getNilString: dataModel.intent.answer.text], [self getNilString:dataModel.intent.text]);
                    }else{
                        [[SuspensionView ShareSuspensionView] setSuspensionLabel:[self getNilString:dataModel.intent.answer.text]];
                    }
                }else{
                    [[SuspensionView ShareSuspensionView] setSuspensionLabel:[NSString stringWithFormat:@"您说的是 %@吗？",[self getNilString:dataModel.intent.text]]];
                }
                
            }
        }
    } else if([sub isEqualToString:@"tts"]){
        NSLog(@"receive tts event");
        
        NSString *cnt_id = [content objectForKey:@"cnt_id"];
        if(cnt_id){
            //合成音频数据
            NSData *audioData = [event.data objectForKey:cnt_id];
            //当前音频块状态：0（开始）,1（中间）,2（结束）,3（一块）
            int dts = [(NSNumber *)[content objectForKey:@"dts"] intValue];
            //合成进度
            int text_per = [(NSNumber *)[content objectForKey:@"text_percent"] intValue];
            NSLog(@"dataLen=%lu, dts=%d, text_percent=%d", (unsigned long)[audioData length], dts, text_per);
        }
    }
}
-(void)processingModel:(IFlySpeechData *)dataModel{
    if ([dataModel.intent.shouldEndSession isEqualToString:@"1"]) {
        NSArray *semanticArray = dataModel.intent.semantic;
        IFlySpeechDataIntentSemantic *semantic = semanticArray[0];
        NSArray *slotsArray = semantic.slots;
        IFlySpeechDataIntentSemanticSlots *slots = slotsArray[slotsArray.count-1];
        if (self.actionValueBlock != nil) {
            self.actionValueBlock([self getNilString:slots.normValue]);
        }
    }
    
}

-(void)answerTextJudge:(NSString *)answerText{
    [self stopRecord];
    __weak typeof(self) weakSelf = self;
    if ([answerText isEqualToString:@"好的,即将为您跳转->待办"]) {
//        [[AudioPlayerPrompt ShareAudioPlayerPrompt] upcomingPlay:^{
//            //            [weakSelf startParsing];
//        }];
    }else if ([answerText isEqualToString:@"已为您打开流程图页面，请查看网页结果"]){
//        [[AudioPlayerPrompt ShareAudioPlayerPrompt] flowChartPlay:^{
//            //            [weakSelf startParsing];
//        }];
    }else if ([answerText isEqualToString:@"已为您发送新增节点请求，请查看网页结果"]){
//        [[AudioPlayerPrompt ShareAudioPlayerPrompt] addNodePlay:^{
//            //            [weakSelf startParsing];
//        }];
    }else if ([answerText isEqualToString:@"已为您发送删除节点请求，请查看网页结果"]){
//        [[AudioPlayerPrompt ShareAudioPlayerPrompt] deleteNodePlay:^{
//            //            [weakSelf startParsing];
//        }];
    }else if ([answerText isEqualToString:@"已为您发送清空节点请求，请查看网页结果"]){
//        [[AudioPlayerPrompt ShareAudioPlayerPrompt] emptyNodePlay:^{
//            //            [weakSelf startParsing];
//        }];
    }
}
- (void)processCmdRtn:(IFlyAIUIEvent *)event{
    
    if(CMD_SYNC == event.arg1)
    {
        int retcode = event.arg2;
        int dtype;
        NSNumber *dtypeNum = [event.data objectForKey:@"sync_dtype"];
        if(!dtypeNum){
            dtype = -1;
        }else{
            dtype = [dtypeNum intValue];
        }
        
        switch (dtype)
        {
            case SYNC_DATA_SCHEMA:
            {
                NSString *syncSid = [event.data objectForKey:@"sid"];
                if(syncSid){
                    self.globalSid = syncSid;
                }else{
                    self.globalSid = @"";
                }
                
                if (0 == retcode)
                {
                    
                }
                else
                {
                    NSString *retCode = [[NSString alloc] initWithFormat:@"retcode:%d",retcode];
                    
                }
                NSLog(@"sid=%@",_globalSid);
            } break;
                
            case SYNC_DATA_QUERY:
            {
                if (0 == retcode)
                {
                    NSLog(@"sync query success");
                }
                else
                {
                    NSLog(@"sync query error= %d",retcode);
                }
            } break;
        }
    } else if(CMD_QUERY_SYNC_STATUS == event.arg1)
    {
        int syncType;
        NSNumber *syncTypeNum = [event.data objectForKey:@"sync_dtype"];
        if(syncTypeNum){
            syncType = [syncTypeNum intValue];
        }else{
            syncType = -1;
        }
        
        if (SYNC_DATA_QUERY == syncType)
        {
            NSString *rltInfo = [event.data objectForKey:@"result"];
            
        }
    }
}
#pragma mark - IFlyAIUIListener

- (void) onEvent:(IFlyAIUIEvent *) event {
    
    switch (event.eventType) {
            
        case EVENT_CONNECTED_TO_SERVER:
        {
            
            NSLog(@"CONNECT TO SERVER");
        } break;
            
        case EVENT_SERVER_DISCONNECTED:
        {
            
            NSLog(@"DISCONNECT TO SERVER");
        } break;
            
        case EVENT_START_RECORD:
        {
            
            NSLog(@"EVENT_START_RECORD");
        } break;
            
        case EVENT_STOP_RECORD:
        {
            
            NSLog(@"EVENT_STOP_RECORD");
        } break;
            
        case EVENT_STATE:
        {
            switch (event.arg1)
            {
                case STATE_IDLE:
                {
                    self.aiuiState = STATE_IDLE;
                    NSLog(@"EVENT_STATE: %s", "IDLE");
                } break;
                    
                case STATE_READY:
                {
                    self.aiuiState = STATE_READY;
                    
                    NSLog(@"EVENT_STATE: %s", "READY");
                } break;
                    
                case STATE_WORKING:
                {
                    self.aiuiState = STATE_WORKING;
                    
                    NSLog(@"EVENT_STATE: %s", "WORKING");
                } break;
            }
        } break;
            
        case EVENT_WAKEUP:
        {
            
            NSLog(@"EVENT_WAKEUP");
        } break;
            
        case EVENT_SLEEP:
        {
            
            NSLog(@"EVENT_SLEEP");
            //            [self stopRecord];
        } break;
            
        case EVENT_VAD:
        {
            switch (event.arg1)
            {
                case VAD_BOS:
                {
                    
                    NSLog(@"EVENT_VAD_BOS");
                } break;
                    
                case VAD_EOS:
                {
                    
                    NSLog(@"EVENT_VAD_EOS");
                } break;
                    
                case VAD_VOL:
                {
                    NSString *volume = [[NSString alloc] initWithFormat:@"Volume:%d",event.arg2];
                    NSLog(@"vol: %d", event.arg2);
                } break;
            }
        } break;
            
        case EVENT_RESULT:
        {
            NSLog(@"EVENT_RESULT");
            [self processResult:event];
        } break;
            
        case EVENT_CMD_RETURN:
        {
            NSLog(@"EVENT_CMD_RETURN");
            [self processCmdRtn:event];
        } break;
            
        case EVENT_ERROR:
        {
            NSString *error = [[NSString alloc] initWithFormat:@"Error Message：%@\nError Code：%d",event.info,event.arg1];
            if (self.errorBlock != nil) {
                self.errorBlock();
            }
            [self stopRecord];
            //            VoiceWaveView.share().startVoice()
            //            [[VoiceWaveView ShareVoiceWaveView] EndVoice];
            NSLog(@"EVENT_ERROR: %@",error);
        } break;
    }
    
}
- (NSString *)getNilString:(NSString *)string {
    if (string == nil || string == NULL) {
        return @"";
    }
    if ([string isKindOfClass:[NSNull class]]) {
        return @"";
    }
    if ([[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] length]==0) {
        return @"";
    }
    return string;
}
@end
