//
//  VideoCallingViewController.m
//  TRTC-API-Example-OC
//
//  Created by bluedang on 2021/4/12.
//

/*
实时视频通话功能
 TRTC APP 实时视频通话功能
 本文件展示如何集成实时视频通话功能
 1、切换摄像头 API:[[_trtcCloud getDeviceManager] switchCamera:_isFrontCamera];
 2、打开关闭摄像头 API: [self.trtcCloud startLocalPreview:_isFrontCamera view:_localVideoView];
                     [self.trtcCloud stopLocalPreview];
 3、切换听筒与扬声器 API：[[_trtcCloud getDeviceManager] setAudioRoute:TXAudioRouteEarpiece];
                      [[_trtcCloud getDeviceManager] setAudioRoute:TXAudioRouteSpeakerphone];
 4、静音当前设备，其他人将无法听到该设备的声音 API: [_trtcCloud muteLocalAudio:YES];
 参考文档：https://cloud.tencent.com/document/product/647/42044
 */

/*
Real-Time Audio Call
 TRTC Audio Call
 This document shows how to integrate the real-time audio call feature.
 1. Switch between the speaker and receiver: [[_trtcCloud getDeviceManager] setAudioRoute:TXAudioRouteSpeakerphone]
 2. Mute the device so that others won’t hear the audio of the device: [_trtcCloud muteLocalAudio:YES]
 3. Display other network and volume information: delegate -> onNetworkQuality, onUserVoiceVolume
 Documentation: https://cloud.tencent.com/document/product/647/42046
*/

#import "VideoCallingViewController.h"

#import "TrtcUserInfo.h"
#import "CordovaEventKit.h"
#import "UIView+Toast.h"
#import "Events.h"
#import "UserUpdateListener.h"


static const NSInteger maxRemoteUserNum = 7;

@interface VideoCallingViewController ()<TRTCCloudDelegate>

@property (weak, nonatomic) IBOutlet UIButton *backButton;
@property (weak, nonatomic) IBOutlet UIButton *subVisibleButton;
@property (weak, nonatomic) IBOutlet UIButton *viewRotateButton;
@property (strong, nonatomic) IBOutletCollection(UIView) NSArray *remoteViewArr;
@property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *subViewBtnArr;
@property (strong, nonatomic) IBOutletCollection(UILabel) NSArray *displayLabelArr;
@property (weak, nonatomic) IBOutlet UILabel *displayLabel;

@property (assign, nonatomic) UInt32 roomId;
@property (strong, nonatomic) NSString* userId;
@property(nonatomic, assign) UInt32 sdkAppId;
@property (strong, nonatomic) NSString* userSig;
@property (strong, nonatomic) TRTCCloud *trtcCloud;
@property (strong, nonatomic) NSMutableOrderedSet *remoteUidSet;
@property (strong, nonatomic) NSMutableArray<TrtcUserInfo*> *viewUsers;

@property (assign, nonatomic) BOOL isFrontCamera;
@property (assign, nonatomic) BOOL *hasShareUser;
@property (assign, nonatomic) BOOL *hiddenAllSubView;

@property (assign, nonatomic) NSInteger rotation;
@end

@implementation VideoCallingViewController

    static VideoCallingViewController* _self;

+(VideoCallingViewController*)viewController{
    return _self;
}
- (TRTCCloud*)trtcCloud {
    if (!_trtcCloud) {
        _trtcCloud = [TRTCCloud sharedInstance];
    }
    return _trtcCloud;
}

- (NSMutableOrderedSet<TrtcUserInfo*> *)remoteUidSet {
    if (!_remoteUidSet) {
        _remoteUidSet = [[NSMutableOrderedSet alloc] initWithCapacity:maxRemoteUserNum];
    }
    return _remoteUidSet;
}

- (NSMutableArray<TrtcUserInfo*> *)viewUsers {
    if (!_viewUsers) {
        _viewUsers = [[NSMutableArray alloc] initWithCapacity:maxRemoteUserNum];
    }
    return _viewUsers;
}

- (instancetype)initWithRoomId:(UInt32)roomId userId:(NSString *)userId appId:(UInt32)appId userSig:(NSString *)userSig{
    NSLog(@"TRTC - initWithRoomId:::::");
    self = [super initWithNibName:NSStringFromClass([self class]) bundle:nil];
    if (self) {
        _roomId = roomId;
        _userId = userId;
        _sdkAppId = appId;
        _userSig = userSig;
    }
    NSLog(@"TRTC - roomid:%d,userID:%@,sdkAppid:%d,userSig:%@",_roomId,_userId,_sdkAppId,_userSig);
    _self = self;
    return  self;
}

- (void) updateUser:(NSDictionary*)extra{
    NSLog(@"TRTC - userinfo.update -- userID:%@,displayname:%@",extra[@"userId"],extra[@"displayName"]);
    TrtcUserInfo *user = [[TrtcUserInfo alloc]initWithPersonid:extra[@"userId"]];
    NSInteger index = [[self remoteUidSet] indexOfObject: user];
    NSLog(@"TRTC - userinfo.update -- userId:%@,index:%ld",extra[@"userId"],index);
    if (index == NSNotFound) { return; }
    TrtcUserInfo *obj = [self remoteUidSet][index];
    [obj setDisplayName: extra[@"displayName"]];
    dispatch_async(dispatch_get_main_queue(), ^{
        [self refreshRemoteVideoViews];
    });
}

- (void)viewDidLoad {
    [super viewDidLoad];

    self.isFrontCamera = NO;
    self.trtcCloud.delegate = self;
    
    [self setupDefaultUIConfig];
    [self setupTRTCCloud];
    
    [self.view sendSubviewToBack:self.view];
}

- (void)setupDefaultUIConfig {
    NSLog(@"TRTC - setupDefaultUIConfig:::::");
    _displayLabel.text = @"我";
    _displayLabel.hidden = NO;
    _rotation = 0;
    [Events addListener:@"userinfo.update" listener: [[UserUpdateListener alloc] init] ];
}


- (void)setupTRTCCloud {
    [[self remoteUidSet] removeAllObjects];
    
    [self.trtcCloud startLocalPreview:_isFrontCamera view:self.view];
    TRTCParams *params = [TRTCParams new];
    params.sdkAppId = _sdkAppId;
    params.roomId = _roomId;
    params.userId = _userId;
    params.role = TRTCRoleAnchor;
    params.userSig = _userSig;
    
    [self.trtcCloud enterRoom:params appScene:TRTCAppSceneVideoCall];
    
    TRTCVideoEncParam *encParams = [TRTCVideoEncParam new];
    encParams.videoResolution = TRTCVideoResolution_640_360;
    encParams.videoBitrate = 550;
    encParams.videoFps = 15;
    
    [self.trtcCloud setVideoEncoderParam:encParams];
    [self.trtcCloud startLocalAudio:TRTCAudioQualityMusic];

}

- (void)dealloc {
    [self.trtcCloud exitRoom];
    [TRTCCloud destroySharedIntance];
}

- (void)changeUser:(NSInteger) a and:(NSInteger) b{
    if(a == b || a < 0 || b < 0){return;}
    NSInteger x = a > b ? b : a;
    NSInteger y = a > b ? a : b;
    if([self remoteUidSet].count > y && x>-1){
        // 交换
        NSLog(@"TRTC - onSubViewClcik:::::Before change:%@,%@",[[self remoteUidSet][x] personid],[[self remoteUidSet][y] personid]);
        TrtcUserInfo* info = [self remoteUidSet][x];
        TrtcUserInfo* info2 = [self remoteUidSet][y];
        [_remoteUidSet removeObjectAtIndex:x];
        [_remoteUidSet setObject:info atIndex: y-1];
        [_remoteUidSet insertObject:info2 atIndex:x];
        NSLog(@"TRTC - onSubViewClcik:::::after change:%@,%@",[[self remoteUidSet][x] personid],[[self remoteUidSet][y] personid]);
        [self refreshRemoteVideoViews];
        NSDictionary *event = [[NSDictionary alloc]initWithObjectsAndKeys:
                [[NSString alloc] initWithFormat:@"%d",_roomId],@"room",info2.personid,@"userId", nil];
        [CordovaEventKit fireEvent:@"onLayoutChangeMessage" obj:event];
    }
}

#pragma mark - IBActions

- (IBAction)onSubVisibleChange:(UIButton*)sender {
    NSLog(@"TRTC - onSubVisibleChange:::::，before:%@",[NSNumber numberWithBool:sender.selected]);
    sender.selected = !sender.selected;
    NSLog(@"TRTC - onSubVisibleChange:::::，after:%@",[NSNumber numberWithBool:sender.selected]);
    [self refreshRemoteVideoViews];
}

- (IBAction)onVideoRotate:(UIButton*)sender {
    NSLog(@"TRTC - onRouteChange:::::,%@,local index: %ld",[[self remoteUidSet][0] personid],[_viewUsers indexOfObject:_userId]);
    TRTCRenderParams *params = [[TRTCRenderParams alloc] init];

    params.fillMode = TRTCVideoFillMode_Fit;
    _rotation += 1;
    _rotation = _rotation > 3 ? 0 : _rotation;
    params.rotation = _rotation;
//    [_trtcCloud stopRemoteView:[[self viewUsers][0] personid] streamType:TRTCVideoStreamTypeBig];
    [_trtcCloud setRemoteRenderParams:[[self remoteUidSet][0] personid] streamType:TRTCVideoStreamTypeBig params:params];
//    [_trtcCloud updateRemoteView:self.view streamType:TRTCVideoStreamTypeBig forUser:[[self remoteUidSet][0] personid]];
//    [_trtcCloud startRemoteView:[[self viewUsers][0] personid] streamType: TRTCVideoStreamTypeBig view:self.view];

}

- (IBAction)onBackClick:(UIButton*)sender {
    NSLog(@"TRTC - onBackClick:::::");
    [self.trtcCloud exitRoom];
    [TRTCCloud destroySharedIntance];
    [self dismissViewControllerAnimated:YES completion:nil];
}

- (IBAction)onSwitchCameraClick:(UIButton*)sender {
    NSLog(@"TRTC - onSwitchCameraClick:::::");
    _isFrontCamera = !_isFrontCamera;
    [[_trtcCloud getDeviceManager] switchCamera:_isFrontCamera];
}


- (IBAction)onMicCaptureClick:(UIButton*)sender {
    NSLog(@"TRTC - onMicCaptureClick:::::");
    sender.selected = !sender.selected;
    if ([sender isSelected]) {
        [_trtcCloud muteLocalAudio:YES];
    } else {
        [_trtcCloud muteLocalAudio:NO];
    }
}

- (IBAction)onSwitchSpeakerClick:(UIButton*)sender {
    NSLog(@"TRTC - onSwitchSpeakerClick:::::");
    sender.selected = !sender.selected;
    if ([sender isSelected]) {
        [[_trtcCloud getDeviceManager] setAudioRoute:TXAudioRouteEarpiece];
    } else {
        [[_trtcCloud getDeviceManager] setAudioRoute:TXAudioRouteSpeakerphone];
    }
}

- (IBAction)onSubViewClcik:(UIButton*)sender {
    NSLog(@"TRTC - onSubViewClcik:::::button");
    NSInteger index = [_subViewBtnArr indexOfObject:sender];
    if (index == NSNotFound) {return;}
    index = index + 1;
    [self changeUser:0 and:index];
}


#pragma mark - TRTCCloud Delegate

- (void)onEnterRoom:(NSInteger) result{
    NSLog(@"TRTC - onEnterRoom, %ld",result);
    [_trtcCloud startLocalPreview:_isFrontCamera view:self.view];
    // 添加本地用户到用户列表
    TrtcUserInfo *info =  [[TrtcUserInfo alloc] initWithPersonid:_userId];
    [info setLocal:YES];
    NSInteger index = [[self remoteUidSet] indexOfObject:info];
    if (index != NSNotFound) {
        return;
    } else {
        [[self remoteUidSet] addObject:info];
    }

    NSDictionary *event = [[NSDictionary alloc]initWithObjectsAndKeys:
                           [[NSString alloc] initWithFormat:@"%d",_roomId],@"room",_userId,@"userId", nil];

    [CordovaEventKit fireEvent:@"onLayoutChangeMessage" obj:event];
}

- (void)onUserVideoAvailable:(NSString *)userId available:(BOOL)available {
    NSLog(@"TRTC - onUserVideoAvailable, user:%@,available%@",userId, available ? @"YES":@"NO");
    // 添加远端用户到用户列表
    TrtcUserInfo *info =  [[TrtcUserInfo alloc] initWithPersonid:userId];
    NSInteger index = [[self remoteUidSet] indexOfObject:info];
    if (available) {
        if (index != NSNotFound) { return; }
        if([info isShareUser]){
            _hasShareUser = YES;
        }
        [[self remoteUidSet] addObject:info];
    } else {
        if (index == NSNotFound) { return; }
        if([info isShareUser]){
            _hasShareUser = NO;
            _hiddenAllSubView = NO;
        }
        [_trtcCloud stopRemoteView:userId streamType:TRTCVideoStreamTypeSmall];
        [[self remoteUidSet] removeObject:userId];
    }
    [self refreshRemoteVideoViews];
    if(_hasShareUser){
        // 切换分享屏幕到主窗口
        [self changeUser:0 and:[[self remoteUidSet] indexOfObject:info]];
        // 隐藏所有子窗口
        _hiddenAllSubView = YES;
        [self refreshRemoteVideoViews];
//        [_trtcCloud stopLocalPreview];
    }
    NSDictionary *event = @{@"room": [[NSString alloc] initWithFormat:@"%d", _roomId], @"userId": userId, @"available": [NSNumber numberWithBool:available]};
    [CordovaEventKit fireEvent:@"onUserVideoAvailable" obj:event];
}

- (void)refreshRemoteVideoViews {
    NSLog(@"TRTC - refreshRemoteVideoViews:%ld",_remoteViewArr.count);

    _subVisibleButton.hidden = _hasShareUser != nil;
    _viewRotateButton.hidden = _hasShareUser == nil;
    _viewRotateButton.enabled = !_viewRotateButton.hidden;
    for (int i = 0; i <= _remoteViewArr.count; i++) {
        TrtcUserInfo* nUser = [self remoteUidSet].count > i ? [self remoteUidSet][i] : nil;
        TrtcUserInfo* oUser = [self viewUsers].count > i ? [self viewUsers][i] : nil;
        UIView* view = i == 0 ? self.view : _remoteViewArr[i-1];
        UILabel* label = i ==0 ? _displayLabel : _displayLabelArr[i-1];
        UIButton* btn = i ==0 ? nil : _subViewBtnArr[i-1];
        NSLog(@"TRTC - refreshRemoteVideoViews - new : %@, o: %@",nUser == nil ? nil : [nUser personid],oUser == nil ? nil : [oUser personid]);
        if((_hiddenAllSubView || ![_subVisibleButton isSelected]) && i!=0){
            [view setHidden:YES];
            [label setHidden:YES];
        }else{
            if(nUser != nil){
                if([nUser isEqual:oUser] && ![view isHidden]){
                    if([nUser isLocalUser]){
                        [label setText:@"我"];
                    } else if([nUser displayName] == nil || [nUser displayName].length == 0) {
                        [label setText:[NSString stringWithFormat:@"%@%@",[nUser personid], [nUser isShareUser] ? @"的屏幕分享" : @""]];
                    } else {
                        [label setText:[NSString stringWithFormat:@"%@%@",[nUser displayName], [nUser isShareUser] ? @"的屏幕分享" : @""]];
                    }
                    [label sizeToFit];
                    continue;
                }
                TRTCRenderParams *params = [[TRTCRenderParams alloc] init];
                params.rotation = 0;
                params.fillMode = [nUser isShareUser] ? TRTCVideoFillMode_Fit : TRTCVideoFillMode_Fill;
                if([nUser isLocalUser]){
                    [_trtcCloud startLocalPreview:_isFrontCamera view:view];
                    [_trtcCloud setLocalRenderParams:params];
                    [label setText:@"我"];
                    [label sizeToFit];
                } else {
                    [_trtcCloud setRemoteRenderParams:[nUser personid] streamType:i == 0 ? TRTCVideoStreamTypeBig : TRTCVideoStreamTypeSmall params:params];
                    [_trtcCloud startRemoteView:[nUser personid] streamType:i == 0 ? TRTCVideoStreamTypeBig : TRTCVideoStreamTypeSmall view:view];

                    if([nUser displayName] == nil || [nUser displayName].length == 0) {
                        [label setText:[NSString stringWithFormat:@"%@%@",[nUser personid], [nUser isShareUser] ? @"的屏幕分享" : @""]];
                    } else {
                        [label setText:[NSString stringWithFormat:@"%@%@",[nUser displayName], [nUser isShareUser] ? @"的屏幕分享" : @""]];
                    }
                    [label sizeToFit];
                }
                [label setHidden:NO];
                [view setHidden:NO];
                if(btn != nil){
                    [btn setHidden:NO];
                }
            } else {
                [view setHidden:YES];
                [label setHidden:YES];
                if(btn != nil){
                    [btn setHidden:YES];
                }
            }
        }
        if(nUser != nil){
            [self viewUsers].count > i ? [self viewUsers][i] = nUser : [[self viewUsers] addObject:nUser];
        }else {
            while([self viewUsers].count > i){
                [[self viewUsers] removeObjectAtIndex:i];
            }
        }
    }
}

- (void) onError:(TXLiteAVError)errCode errMsg:(NSString *)errMsg extInfo:(NSDictionary *)extInfo{
    NSLog(@"TRTC - onError::sdk callback onError code: %d,msg: %@,extInfo: %@",errCode,errMsg,extInfo);
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.view makeToast: [[NSString alloc] initWithFormat:@"%@[%d]",errMsg,errCode]];
    });
//    [self.trtcCloud exitRoom];
//    [TRTCCloud destroySharedIntance];
//    [self dismissViewControllerAnimated:YES completion:nil];
}

- (void) onExitRoom:(NSInteger)reason{
    if (reason == 2) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.view makeToast: @"远程协助已结束"];
        });
    }
    [self dismissViewControllerAnimated:YES completion:nil];
}

@end
