//
//  ViewController.m
//  DuixDemo
//
// Created by gj on 2023/12/4.
//

#import "ViewController.h"
#import <GJDigitalSDK/GJDigitalSDK.h>
#import "GJAccess.h"
#import "WJLocalNetWorkManager.h"
#include <ifaddrs.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#import "GJCheckNetwork.h"
#import "UIView+drag.h"
#import "MBProgressHUD.h"

#define REGION @""
#define  ViewHeight [[UIScreen mainScreen] bounds].size.height
#define  ViewWidth [[UIScreen mainScreen] bounds].size.width
#define ScaleWidth  ViewWidth/375
#define ScaleHeight ViewHeight/812
#define StatusHeight [[UIApplication sharedApplication] statusBarFrame].size.height





//音频驱动音频地址示例
#define AudioUrl @"https://app.duix.ai/nfs/duix/tts-proxy/2024-07-04/5000-_-681987357994258432--D19B0EAA19E98BBB102F6421380085B7.wav"

@interface ViewController ()<DigitalViewDelegate,UITextFieldDelegate>

// Custom view
@property (nonatomic, strong) UIView *customView;

//本地视频界面
@property (nonatomic, strong) UIView *localView;


@property (nonatomic, strong)UIButton * switchBtn;

// Whether to display
@property (nonatomic, assign) BOOL digitalShow;

@property (nonatomic, strong)UILabel * conversationLabel;
//会话id
@property (nonatomic, strong)UITextField * conversationTextField;

//appid
@property (nonatomic, strong)UILabel * appIDLabel;
//appid
@property (nonatomic, strong)UITextField * appIDTextField;

//appkey
@property (nonatomic, strong)UILabel * appkeyLabel;
//appkey
@property (nonatomic, strong)UITextField * appkeyTextField;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor whiteColor];
    
    [self loadUI];
}

- (void)loadUI {
    
    self.customView=[[UIView alloc] initWithFrame:CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height)];
    [self.view addSubview:self.customView];
    
  
    [self.view addSubview:self.localView];
    

    
    self.conversationLabel=[[UILabel alloc] init];
    self.conversationLabel.frame=CGRectMake(20, 120, self.view.frame.size.width-40, 30);
    self.conversationLabel.textColor=[UIColor blackColor];
    self.conversationLabel.text=@"conversationId:";
    self.conversationLabel.font=[UIFont systemFontOfSize:20];
    self.conversationLabel.textAlignment=NSTextAlignmentLeft;
    [self.view addSubview:self.conversationLabel];
    
   self.conversationTextField=[[UITextField alloc] init];
    self.conversationTextField.frame=CGRectMake(20, CGRectGetMaxY(self.conversationLabel.frame), self.view.frame.size.width-40, 44);
    self.conversationTextField.backgroundColor = [UIColor clearColor];
//        _phoneTextField.layer.borderColor=[UIColor colorWithHexString:@"#FFFFFF" alpha:0.29].CGColor;
//        _phoneTextField.layer.borderWidth=1;
    self.conversationTextField.layer.masksToBounds = YES;
    self.conversationTextField.delegate = self;
    self.conversationTextField.layer.cornerRadius = 10;
    self.conversationTextField.layer.borderColor = [UIColor redColor].CGColor;
    self.conversationTextField.layer.borderWidth = 1;
    self.conversationTextField.returnKeyType=UIReturnKeyDone;
    UIView *paddingView1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0,10,44)];
    paddingView1.backgroundColor = [UIColor clearColor];
    self.conversationTextField.leftView = paddingView1;
    self.conversationTextField.leftViewMode = UITextFieldViewModeAlways;
    [self.view addSubview:self.conversationTextField];
    
 
    self.appIDLabel=[[UILabel alloc] init];
    self.appIDLabel.frame=CGRectMake(20, CGRectGetMaxY(self.conversationTextField.frame), self.view.frame.size.width-40, 30);
    self.appIDLabel.textColor=[UIColor blackColor];
    self.appIDLabel.text=@"appId:";
    self.appIDLabel.font=[UIFont systemFontOfSize:20];
    self.appIDLabel.textAlignment=NSTextAlignmentLeft;
    [self.view addSubview:self.appIDLabel];
    
    self.appIDTextField=[[UITextField alloc] init];
     self.appIDTextField.frame=CGRectMake(20,CGRectGetMaxY(self.appIDLabel.frame), self.view.frame.size.width-40, 44);
    self.appIDTextField.backgroundColor = [UIColor clearColor];
 //        _phoneTextField.layer.borderColor=[UIColor colorWithHexString:@"#FFFFFF" alpha:0.29].CGColor;
 //        _phoneTextField.layer.borderWidth=1;
     self.appIDTextField.layer.masksToBounds = YES;
     self.appIDTextField.delegate = self;
     self.appIDTextField.layer.cornerRadius = 10;
     self.appIDTextField.layer.borderColor = [UIColor redColor].CGColor;
     self.appIDTextField.layer.borderWidth = 1;
     self.appIDTextField.returnKeyType=UIReturnKeyDone;
    UIView *paddingView2 = [[UIView alloc] initWithFrame:CGRectMake(0, 0,10,44)];
    paddingView2.backgroundColor = [UIColor clearColor];
    self.appIDTextField.leftView = paddingView2;
    self.appIDTextField.leftViewMode = UITextFieldViewModeAlways;
     [self.view addSubview:self.appIDTextField];

    
    
    
    self.appkeyLabel=[[UILabel alloc] init];
    self.appkeyLabel.frame=CGRectMake(20, CGRectGetMaxY(self.appIDTextField.frame), self.view.frame.size.width-40, 30);
    self.appkeyLabel.textColor=[UIColor blackColor];
    self.appkeyLabel.text=@"appKey:";
    self.appkeyLabel.font=[UIFont systemFontOfSize:20];
    self.appkeyLabel.textAlignment=NSTextAlignmentLeft;
    [self.view addSubview:self.appkeyLabel];
    
    self.appkeyTextField=[[UITextField alloc] init];
     self.appkeyTextField.frame=CGRectMake(20,CGRectGetMaxY(self.appkeyLabel.frame), self.view.frame.size.width-40, 44);
    self.appkeyTextField.backgroundColor = [UIColor clearColor];
 //        _phoneTextField.layer.borderColor=[UIColor colorWithHexString:@"#FFFFFF" alpha:0.29].CGColor;
 //        _phoneTextField.layer.borderWidth=1;
     self.appkeyTextField.layer.masksToBounds = YES;
     self.appkeyTextField.delegate = self;
     self.appkeyTextField.layer.cornerRadius = 10;
     self.appkeyTextField.layer.borderColor = [UIColor redColor].CGColor;
     self.appkeyTextField.layer.borderWidth = 1;
     self.appkeyTextField.returnKeyType=UIReturnKeyDone;
    UIView *paddingView3 = [[UIView alloc] initWithFrame:CGRectMake(0, 0,10,44)];
    paddingView3.backgroundColor = [UIColor clearColor];
    self.appkeyTextField.leftView = paddingView3;
    self.appkeyTextField.leftViewMode = UITextFieldViewModeAlways;
     [self.view addSubview:self.appkeyTextField];
     


    
    UIButton *startbtn = [UIButton buttonWithType:UIButtonTypeCustom];
    startbtn.frame = CGRectMake(20, self.view.frame.size.height - 220, 100, 40);
    [startbtn setTitle:@"Start" forState:UIControlStateNormal];
    [startbtn setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];
    [startbtn addTarget:self action:@selector(toStart) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:startbtn];

    UIButton *stopbtn = [UIButton buttonWithType:UIButtonTypeCustom];
    stopbtn.frame = CGRectMake(self.view.frame.size.width - 120, self.view.frame.size.height - 220, 100, 40);
    [stopbtn setTitle:@"Stop" forState:UIControlStateNormal];
    [stopbtn setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];
    [stopbtn addTarget:self action:@selector(toStop) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:stopbtn];

    UIButton *breakbtn = [UIButton buttonWithType:UIButtonTypeCustom];
    breakbtn.frame = CGRectMake((self.view.frame.size.width - 120) / 2.0, self.view.frame.size.height - 220, 120, 40);
    [breakbtn setTitle:@"Interrupt" forState:UIControlStateNormal];
    [breakbtn setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];
    [breakbtn addTarget:self action:@selector(toBreak) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:breakbtn];

    UIButton *textbtn = [UIButton buttonWithType:UIButtonTypeCustom];
    textbtn.frame = CGRectMake(20, self.view.frame.size.height - 160, 100, 40);
    [textbtn setTitle:@"Text-driven" forState:UIControlStateNormal];
    [textbtn setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];
    [textbtn addTarget:self action:@selector(toTextPlay) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:textbtn];

    UIButton *audiobtn = [UIButton buttonWithType:UIButtonTypeCustom];
    audiobtn.frame = CGRectMake((self.view.frame.size.width - 120) / 2.0, self.view.frame.size.height - 160, 120, 40);
    [audiobtn setTitle:@"Audio-driven" forState:UIControlStateNormal];
    [audiobtn setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];
    [audiobtn addTarget:self action:@selector(toAudioPlay) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:audiobtn];

    UIButton *askbtn = [UIButton buttonWithType:UIButtonTypeCustom];
    askbtn.frame = CGRectMake(self.view.frame.size.width - 120, self.view.frame.size.height - 160, 100, 40);
    [askbtn setTitle:@"Text Q&A" forState:UIControlStateNormal];
    [askbtn setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];
    [askbtn addTarget:self action:@selector(toAskText) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:askbtn];
    
    
    UIButton *openCameraBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    openCameraBtn.frame = CGRectMake(20, self.view.frame.size.height - 100, 120, 40);
    [openCameraBtn setTitle:@"Open Camera" forState:UIControlStateNormal];
    [openCameraBtn setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];
    [openCameraBtn addTarget:self action:@selector(toOpenCamera) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:openCameraBtn];
    
    
    UIButton *stopCameraBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    stopCameraBtn.frame = CGRectMake((self.view.frame.size.width - 120) / 2.0, self.view.frame.size.height - 100, 120, 40);
    [stopCameraBtn setTitle:@"Stop Camera" forState:UIControlStateNormal];
    [stopCameraBtn setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];
    [stopCameraBtn addTarget:self action:@selector(toStopCamera) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:stopCameraBtn];
    
    NSUserDefaults * defaults=[NSUserDefaults standardUserDefaults];


    self.conversationTextField.text=[defaults objectForKey:@"ConversationIdKEY"]?:@"";
    self.appIDTextField.text=[defaults objectForKey:@"APPIDKEY"]?:@"";
    self.appkeyTextField.text=[defaults objectForKey:@"APPKEY"]?:@"";

    //获取网络权限
    [[GJCheckNetwork manager] getWifiState];
    __weak typeof(self)weakSelf = self;
    [GJCheckNetwork manager].on_net = ^(NetType state) {
        if (state == Net_WWAN
            || state == Net_WiFi) {
         
        }
    };
}
-(void)toOpenCamera
{
    if([DigitalConfig shareConfig].multimodal==1)
    {
        //多模态打开摄像头
        self.switchBtn.hidden=NO;
        [[DigitalManager manager] toOpenCamera];
    }
    else
    {
        self.switchBtn.hidden=YES;
        [self showLoadText:@"会话不支持多模态" :self.view];
    }
}
-(void)toStopCamera
{
    self.switchBtn.hidden=YES;
    [[DigitalManager manager] toStopCamera];
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    
    NSUserDefaults * defaults=[NSUserDefaults standardUserDefaults];
     if(textField==self.conversationTextField)
     {
        
         [defaults setObject:textField.text forKey:@"ConversationIdKEY"];
     }
    else if(textField==self.appIDTextField)
    {
        [defaults setObject:textField.text forKey:@"APPIDKEY"];
    }
    else if(textField==self.appkeyTextField)
    {
        [defaults setObject:textField.text forKey:@"APPKEY"];
    }
    return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    [textField resignFirstResponder];
    
  
    return YES;
}
-(UIView*)localView
{
    if(nil==_localView)
    {
        _localView=[[UIView alloc] initWithFrame:CGRectMake(ViewWidth-98*ScaleWidth-12*ScaleWidth, StatusHeight+48*ScaleWidth, 98*ScaleWidth, 174*ScaleWidth)];
        _localView.backgroundColor=[UIColor clearColor];
        _localView.layer.cornerRadius=5*ScaleWidth;
        _localView.clipsToBounds=YES;
        _localView.fl_canSlide = YES;
        _localView.fl_bounces = YES;
        _localView.fl_isAdsorb = NO;
        _localView.hidden = YES;
    }
    return _localView;

}
-(UIButton*)switchBtn
{
    if(nil==_switchBtn)
    {
        _switchBtn=[UIButton  buttonWithType:UIButtonTypeCustom];
        _switchBtn.frame=CGRectMake(0*ScaleWidth, 0*ScaleWidth, 35*ScaleWidth, 42*ScaleWidth);
        [_switchBtn setImage:[UIImage imageNamed:@"switch_camera"] forState:UIControlStateNormal];
        _switchBtn.backgroundColor=[UIColor clearColor];
        [_switchBtn addTarget:self action:@selector(switchCamera) forControlEvents:UIControlEventTouchDown];
        _switchBtn.hidden=YES;
    }
    return _switchBtn;
}
#pragma mark - 翻转摄像头
-(void)switchCamera
{
    [[DigitalManager manager] swichCamera];
}
#pragma mark - UIButton Click Events

#pragma mark - Text Q&A
- (void)toAskText {
    // Command to ask a question
    [[DigitalManager manager] commandAskWithText:@"what your name" interrupt:YES];
}

#pragma mark - Audio-driven
- (void)toAudioPlay {
    // Command to play an audio event
    [[DigitalManager manager] commandEventWithAudioUrl:AudioUrl interrupt:YES];
}

#pragma mark - Text-driven
- (void)toTextPlay {
    // Command to send a text message
    [[DigitalManager manager] commandEventWithText:@"can we chat" interrupt:YES];
}

#pragma mark - Interrupt
- (void)toBreak {
    // Command to interrupt the digital assistant
    [[DigitalManager manager] toBreakDigital];
}

#pragma mark - Start Conversation
- (void)toStart {


    [DigitalManager manager].remote_view = self.customView; // Remote video view
    [DigitalManager manager].local_view = self.localView; // local video view
    [DigitalManager manager].delegate = self; // Set delegate
    __weak typeof(self) weakSelf = self;
    triggerLocalNetworkPrivacyAlertObjC();
    [[GJAccess manager] getmicrophoneaccess:^(bool isPermis) {
        if (isPermis) {
            [weakSelf sdkInit]; // Initialize SDK if permission is granted
        }
    }];
    

}

#pragma mark - End Conversation
- (void)toStop {
    self.conversationTextField.hidden=NO;
    self.appIDTextField.hidden=NO;
    self.appkeyTextField.hidden=NO;
    self.conversationLabel.hidden=NO;
    self.appIDLabel.hidden=NO;
    self.appkeyLabel.hidden=NO;
    self.digitalShow = NO; // Hide digital display
    self.localView.hidden=YES;
    
    [[DigitalManager manager] toStop]; // Stop the session
}

#pragma mark - SDK Initialization
- (void)sdkInit {
    if (self.appIDTextField.text.length == 0 || self.appkeyTextField.text.length == 0 || self.conversationTextField.text.length == 0) {
        NSLog(@"GJDigitalDemo==Please configure correct AppId, AppKey, ConversationId");
        return;
    }
    NSLog(@"GJDigitalDemo==Loading...");
    __weak typeof(self) weakSelf = self;
    self.conversationTextField.text=[self.conversationTextField.text stringByReplacingOccurrencesOfString:@" " withString:@""];
    self.appIDTextField.text=[self.appIDTextField.text stringByReplacingOccurrencesOfString:@" " withString:@""];
    self.appkeyTextField.text=[self.appkeyTextField.text stringByReplacingOccurrencesOfString:@" " withString:@""];

    [[DigitalManager manager] initNewWithAppId:self.appIDTextField.text appKey:self.appkeyTextField.text conversationId:self.conversationTextField.text region:REGION block:^(BOOL isSuccee, NSString *errorMsg) {
        if (isSuccee) {
    
             
            [[DigitalManager manager] toStart]; // Start if initialized successfully
            if([DigitalConfig shareConfig].multimodal==1)
            {
                dispatch_async(dispatch_get_main_queue(), ^{
                    [weakSelf.localView addSubview:weakSelf.switchBtn];
                });
          
            }
        } else {
            NSLog(@"GJDigitalDemo==errorMsg==%@", errorMsg);
            [self showLoadText:errorMsg :weakSelf.view];
        }
    }];
}
-(void)showLoadText:(NSString *)loadtext :(UIView*)view
{
    if (loadtext.length==0) {
        return;
    }
    if(view==nil)
    {
        return;
    }
    MBProgressHUD*  hud = [[MBProgressHUD alloc]initWithView:view];
    [view addSubview:hud];
    hud.mode = MBProgressHUDModeCustomView;
    hud.detailsLabel.text =loadtext;
    hud.userInteractionEnabled = NO;
    hud.detailsLabel.font=[UIFont fontWithName:@"PingFangSC-Medium" size:14];
    hud.detailsLabel.textColor=[UIColor whiteColor];
    hud.contentColor=[UIColor whiteColor];
    hud.bezelView.style = MBProgressHUDBackgroundStyleSolidColor;
    hud.bezelView.backgroundColor = [UIColor blackColor];
    [hud showAnimated:YES];
    [hud hideAnimated:YES afterDelay:2];
//    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2* NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//        [MBProgressHUD hideAllHUDsForView:view animated:YES];
//    });
}
#pragma mark - SDK Delegate DigitalViewDelegate

#pragma mark - Video Load Completion
- (void)onVideoShow:(BOOL)isSuccess progress:(float)progress {
    if (isSuccess) {
        self.digitalShow = YES; // Show digital avatar if loaded successfully
        
        __weak typeof(self) weakSelf = self;
        dispatch_async(dispatch_get_main_queue(), ^{
            weakSelf.localView.hidden=NO;
            
            weakSelf.conversationTextField.hidden=YES;
            weakSelf.appIDTextField.hidden=YES;
            weakSelf.appkeyTextField.hidden=YES;
            weakSelf.conversationLabel.hidden=YES;
            weakSelf.appIDLabel.hidden=YES;
            weakSelf.appkeyLabel.hidden=YES;
        });
 
        NSLog(@"GJDigitalDemo==Load Complete");
    } else {
        NSLog(@"GJDigitalDemo==Loading - %lf", progress); // Log loading progress
    }
}

#pragma mark - Error Handling
- (void)onError:(NSInteger)error_code errorMsg:(NSString *)errorMsg {
    // Handle different error codes
    switch (error_code) {
        case -1:
        case -2:
            // MQTT connection issues
            break;
        case 50001:
            // Invalid or empty AppId
            break;
        case 50002:
            // Resource check failed, contact admin
            break;
        case 50003:
            // Resource occupied, check and try again
            break;
        case 50004:
            // Human request timeout
            break;
        case 50005:
            // Exception retrieving resources from group
            break;
        case 50006:
            // Signature failure
            break;
        case 50007:
            // Insufficient total concurrency of resources, please check and try again
            break;
        case 50009:
            // Resource timeout or not configured
            break;
    }
    [self showLoadText:errorMsg :self.view];
    NSLog(@"GJDigitalDemo==errorMsg==%@", errorMsg);
}
-(void)onByeBye
{
    [self showLoadText:@"会话被销毁" :self.view];
}
#pragma mark - ASR Start Recognition
- (void)toWebrtcAsrStart {
    NSLog(@"GJDigitalDemo==ASR Start Recognition");
}

#pragma mark - ASR Recognition
- (void)toWebrtcAsrText:(NSString*)asrText isFinish:(BOOL)isFinish {
    NSLog(@"GJDigitalDemo==ASR Recognition==%@", asrText);
}

#pragma mark - Digital Avatar Starts Speaking
- (void)toSpeakStart:(NSDictionary *)dict {
    NSLog(@"GJDigitalDemo==Started Speaking - %@", dict);
}
-(void)toSpeakText:(NSDictionary *)dict
{
    NSLog(@"GJDigitalDemo==toSpeakText- %@", dict);
}
#pragma mark - Digital Avatar Stops Speaking
- (void)toSpeakStop:(NSDictionary *)dict {
    NSLog(@"GJDigitalDemo==Stopped Speaking - %@", dict);
}

static NSArray<NSData *> * addressesOfDiscardServiceOnBroadcastCapableInterfaces(void) {
    struct ifaddrs * addrList = NULL;
    int err = getifaddrs(&addrList);
    if (err != 0) {
        return @[];
    }
    NSMutableArray<NSData *> * result = [NSMutableArray array];
    for (struct ifaddrs * cursor = addrList; cursor != NULL; cursor = cursor->ifa_next) {
        if ( (cursor->ifa_flags & IFF_BROADCAST) &&
            (cursor->ifa_addr != NULL)
            ) {
            switch (cursor->ifa_addr->sa_family) {
                case AF_INET: {
                    struct sockaddr_in sin = *(struct sockaddr_in *) cursor->ifa_addr;
                    sin.sin_port = htons(9);
                    NSData * addr = [NSData dataWithBytes:&sin length:sizeof(sin)];
                    [result addObject:addr];
                } break;
                case AF_INET6: {
                    struct sockaddr_in6 sin6 = *(struct sockaddr_in6 *) cursor->ifa_addr;
                    sin6.sin6_port = htons(9);
                    NSData * addr = [NSData dataWithBytes:&sin6 length:sizeof(sin6)];
                    [result addObject:addr];
                } break;
                default: {
                    // do nothing
                } break;
            }
        }
    }
    freeifaddrs(addrList);
    return result;
}

extern void triggerLocalNetworkPrivacyAlertObjC(void) {
    int sock4 = socket(AF_INET, SOCK_DGRAM, 0);
    int sock6 = socket(AF_INET6, SOCK_DGRAM, 0);
    
    if ((sock4 >= 0) && (sock6 >= 0)) {
        char message = '!';
        NSArray<NSData *> * addresses = addressesOfDiscardServiceOnBroadcastCapableInterfaces();
        for (NSData * address in addresses) {
            int sock = ((const struct sockaddr *) address.bytes)->sa_family == AF_INET ? sock4 : sock6;
            (void) sendto(sock, &message, sizeof(message), MSG_DONTWAIT, address.bytes, (socklen_t) address.length);
        }
    }
    close(sock4);
    close(sock6);
}

@end
