//
//  ErtcRoomViewController.m
//  EZOpenSDKDemo
//
//  Created by JuneCheng on 2025/4/17.
//  Copyright © 2025 hikvision. All rights reserved.
//

#import "ErtcRoomViewController.h"
#import "ErtcHelper.h"

#import "EZCameraInfo.h"

@interface ErtcRoomViewController ()<ERTCDelegate>

@property (weak, nonatomic) IBOutlet UILabel *devSerialLabel;///< 设备序列号
@property (weak, nonatomic) IBOutlet UILabel *videoTalkTimeLabel;///< 视频通话时长
@property (weak, nonatomic) IBOutlet UIView *bottomView;///< 底部视图
// 麦克风控制
@property (weak, nonatomic) IBOutlet UIView *microView;
@property (weak, nonatomic) IBOutlet UIImageView *microImageView;
@property (weak, nonatomic) IBOutlet UILabel *microLabel;
// 声音控制
@property (weak, nonatomic) IBOutlet UIView *soundView;
@property (weak, nonatomic) IBOutlet UIImageView *soundImageView;
@property (weak, nonatomic) IBOutlet UILabel *soundLabel;
// 挂断
@property (weak, nonatomic) IBOutlet UIView *hangUpView;
// 转换摄像头
@property (weak, nonatomic) IBOutlet UIView *switchCameraView;
@property (weak, nonatomic) IBOutlet UIImageView *switchCameraImageView;
// 摄像头已开/摄像头已关
@property (weak, nonatomic) IBOutlet UIView *cameraStateView;
@property (weak, nonatomic) IBOutlet UIImageView *cameraStateImageView;
@property (weak, nonatomic) IBOutlet UILabel *cameraStateLabel;

@property (weak, nonatomic) IBOutlet UIView *vcsRootView;///< 播放窗口父视图
@property (nonatomic, strong) ERTCView *vcsLocalPlayView;///< 本地播放窗口
@property (nonatomic, strong) ERTCView *vcsRemotePlayView;///< 远程播放窗口


@property (nonatomic, strong) NSTimer *videoTalkTimer;///< 视频通话时长定时器
@property (nonatomic, assign) NSTimeInterval videoTalkSecond;///< 视频通话时长秒数
@property (nonatomic, assign) BOOL isFullScreenLocalVideo;///< 当前全屏显示本地画面
@property (nonatomic, assign) BOOL isRemoteUserEnterRoom;///< 设备端是否已进入房间
@property (nonatomic, strong) NSMutableDictionary *remoteUserDict;///< 记录设备端镜头的开启状态，onUserVideoAvailable回调的状态跟当前的一致时不做处理

@end

@implementation ErtcRoomViewController

- (instancetype)init {
    if (self = [super init]) {
        self = [EZStoryBoardTool getViewController:@"VideoTalk" andIdentifier:@"ErtcRoomViewController"];
    }
    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    [self setData];
    [self setUI];
    
    [self startUpdateTimer];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    self.navigationController.navigationBarHidden = YES;
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    // 设置大码流视频参数
    ERTCVideoEncParam *videoParam = [[ERTCVideoEncParam alloc] init];
    videoParam.videoResolution = ERTCVideoResolution_1280_720;
    videoParam.videoFps = ERTCVideoFPS_15;
    // iOS端，videoBitrate单位是Kbps；Android端，videoBitrate单位是字节，需要 *1024
    videoParam.videoBitrate = 500;
    videoParam.resMode = ERTCVideoResolutionModePortrait;
    [[ErtcHelper sharedInstance].ertcEngine setVideoEncoderParam:videoParam];
    
    // 开关本地视频
    [[ErtcHelper sharedInstance].ertcEngine enableLocalVideo:YES];
    
    // 音频编码类型[必须，S10音频使用AAC]
    [[ErtcHelper sharedInstance].ertcEngine setAudioEncoderType:ERTCAudioEncodeType_AAC];
    
    // 设置填充模式及本地预览
    self.vcsLocalPlayView.fillMode = ERTCVideoFillMode_Fill;
    [[ErtcHelper sharedInstance].ertcEngine setLocalPreview:self.vcsLocalPlayView withRegionID:0];
    
    // 设置事件代理
    [ErtcHelper sharedInstance].ertcEngine.delegate = self;
    
    // 进入房间
    [[ErtcHelper sharedInstance].ertcEngine enterRoom:self.ertcParam withScene:ERTCAppScene_VideoCall];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    self.navigationController.navigationBarHidden = NO;
    // performSelector定时方法未执行完就退出的话会导致内存泄漏，退出前取消定时任务
    [NSObject cancelPreviousPerformRequestsWithTarget:self];
    [self stopUpdateTimer];
}

#pragma mark - Action Methods 点击事件

/**
 * 麦克风开关
 */
- (void)microAction {
    NSInteger tag = self.microView.tag;
    BOOL isSelect = self.microView.tag = (tag == 0 ? 1 : 0);
    [[ErtcHelper sharedInstance].ertcEngine enableLocalAudio:isSelect];
    self.microImageView.image = isSelect ? GetImage(@"ys_mt_audio_on") : GetImage(@"ys_mt_audio_off");
    self.microLabel.text = isSelect ? @"静音" : @"解除静音";
}

/**
 *  声音开关
 */
- (void)soundAction {
    NSInteger tag = self.soundView.tag;
    BOOL isSelect = self.soundView.tag = (tag == 0 ? 1 : 0);
    [[ErtcHelper sharedInstance].ertcEngine setEnableSpeakerphone:isSelect];
    self.soundImageView.image = isSelect ? GetImage(@"ys_mt_sound_speaker") : GetImage(@"ys_mt_sound_earpiece");
    self.soundLabel.text = isSelect ? @"扬声器" : @"耳机";
}

/**
 * 挂断
 */
- (void)hangUpAction {
    // 客户端呼叫设备 && 设备未接听，取消邀请设备入会
    if (self.isClientCallDevice && !self.isRemoteUserEnterRoom) {
        [self cancelInviteDeviceEnterMeeting];
    }
    [self releaseERTC];
    [self.navigationController popViewControllerAnimated:YES];
}

/**
 * 摄像头切换
 */
- (void)switchCameraAction {
    [[ErtcHelper sharedInstance].ertcEngine switchCamera];
}

/**
 * 摄像头开关
 */
- (void)cameraStateAction {
    NSInteger tag = self.cameraStateView.tag;
    BOOL isSelect = self.cameraStateView.tag = (tag == 0 ? 1 : 0);
    [[ErtcHelper sharedInstance].ertcEngine enableLocalVideo:isSelect];
    [[ErtcHelper sharedInstance].ertcEngine setLocalPreview:isSelect ? self.vcsLocalPlayView : nil withRegionID:0];
    self.cameraStateImageView.image = isSelect ? GetImage(@"ys_mt_video_on") : GetImage(@"ys_mt_video_off");
    self.cameraStateLabel.text = isSelect ? @"摄像头已开" : @"摄像头已关";
    self.switchCameraImageView.image = isSelect ? GetImage(@"ys_mt_switch_camera_enable") : GetImage(@"ys_mt_switch_camera_disable");
    self.switchCameraView.userInteractionEnabled = isSelect;
}

/**
 * 本地画面点击
 */
- (void)vcsLocalPlayViewAction {
    if (self.isFullScreenLocalVideo) {// 全屏显示本地画面，远程画面在小窗口中显示时，显示底部视图
        // 显示/隐藏底部视图
        [self showOrHideBottomView];
    } else {
        [self switchVcsPlayViewPosition];
    }
}

/**
 * 设备端画面点击
 */
- (void)vcsRemotePlayViewAction {
    if (self.isFullScreenLocalVideo) {// 全屏显示本地画面，远程画面在小窗口中显示时，切换窗口
        [self switchVcsPlayViewPosition];
    } else {
        // 显示/隐藏底部视图
        [self showOrHideBottomView];
    }
}

/**
 * 交换两个播放器的位置
 */
- (void)switchVcsPlayViewPosition {
    self.isFullScreenLocalVideo = !self.isFullScreenLocalVideo;
    if (self.isFullScreenLocalVideo) {
        [self.vcsRemotePlayView mas_remakeConstraints:^(MASConstraintMaker *make) {
            make.width.mas_equalTo(90);
            make.height.mas_equalTo(160);
            make.top.equalTo(self.vcsRootView).offset(64);
            make.right.equalTo(self.vcsRootView).offset(-5);
        }];
        [self.vcsLocalPlayView mas_remakeConstraints:^(MASConstraintMaker *make) {
            make.edges.equalTo(self.vcsRootView);
        }];
        [self.vcsRootView bringSubviewToFront:self.vcsRemotePlayView];
    } else {
        [self.vcsLocalPlayView mas_remakeConstraints:^(MASConstraintMaker *make) {
            make.width.mas_equalTo(90);
            make.height.mas_equalTo(160);
            make.top.equalTo(self.vcsRootView).offset(64);
            make.right.equalTo(self.vcsRootView).offset(-5);
        }];
        [self.vcsRemotePlayView mas_remakeConstraints:^(MASConstraintMaker *make) {
            make.edges.equalTo(self.vcsRootView);
        }];
        [self.vcsRootView bringSubviewToFront:self.vcsLocalPlayView];
    }
    // 如果窗口的大小发生变化，需要重新设置一遍
    [self.vcsRootView layoutIfNeeded];
    [[ErtcHelper sharedInstance].ertcEngine setLocalPreview:nil withRegionID:0];
    [[ErtcHelper sharedInstance].ertcEngine setLocalPreview:self.vcsLocalPlayView withRegionID:0];
}

/**
 * 显示或隐藏视频通话工具栏
 */
- (void)showOrHideBottomView {
    if (!self.bottomView.hidden) {
        self.bottomView.hidden = YES;
    } else {
        self.bottomView.hidden = NO;
    }
}

#pragma mark - ERTC代理 事件回调

/// 用户加入房间成功，加入房间成功后将收到回调
/// @param result 加入房间耗时
- (void)onEnterRoomSuccess:(NSInteger)result {
    NSLog(@"ERTCDelegate onEnterRoomSuccess result: %ld", (long)result);
    // 客户端发起视频通话，邀请设备入会
    if (self.isClientCallDevice) {
        [self inviteDeviceEnterMeeting];
    }
}

/// 用户退出房间，非主动退出房间才会收到该回调
/// @param reason 退出房间原因
- (void)onExitRoom:(ERTCSelfExitReason)reason {
    NSLog(@"ERTCDelegate onEnterRoomSuccess reason: %lu", (unsigned long)reason);
}

/// 远端用户进入房间成功回调，进入房间时将会收到所有已在房间内用户加入房间的回调
/// @param userId 用户id
- (void)onRemoteUserEnterRoom:(NSString *)userId {
    NSLog(@"ERTCDelegate onRemoteUserEnterRoom RemoteUser加入房间成功 userId:%@", userId);
    self.isRemoteUserEnterRoom = YES;
    self.vcsRemotePlayView.hidden = NO;
}

/// 远端用户离开房间
/// @param userId 用户ID
/// @param reason 离开原因，0表示用户主动退出房间，1表示用户超时退出。
- (void)onRemoteUserLeaveRoom:(NSString *)userId reason:(NSInteger)reason {
    NSLog(@"ERTCDelegate onRemoteUserLeaveRoom RemoteUser离开房间成功 userId:%@", userId);
    [EZToast show:@"设备端已挂断，视频通话结束"];
    [self hangUpAction];
}

/// 远端用户打开或关闭视频流的回调
/// @param userId 远端用户id
/// @param available true-视频可用 false-视频不可用
- (void)onUserVideoAvailable:(NSString *)userId available:(BOOL)available {
    NSLog(@"ERTCDelegate onUserVideoAvailable RemoteUser userId:%@, available:%@", userId, available ? @"YES" : @"NO");
    BOOL value = [[self.remoteUserDict objectForKey:userId] boolValue];
    if (value == available) {
        NSLog(@"ERTCDelegate duplicate message, filtered");
        return;
    }
    
    [self.remoteUserDict setValue:[NSNumber numberWithBool:available] forKey:userId];
    if (available) {
        // 订阅远端视频
        self.vcsRemotePlayView.fillMode = ERTCVideoFillMode_Fit;
        [[ErtcHelper sharedInstance].ertcEngine subscribe:YES forUser:userId withStream:ERTCVideoStreamTypeBig];
        [[ErtcHelper sharedInstance].ertcEngine setRemoteView:self.vcsRemotePlayView forUser:userId withRegionID:0];
    } else {
        [[ErtcHelper sharedInstance].ertcEngine subscribe:NO forUser:userId withStream:ERTCVideoStreamTypeBig];
        [[ErtcHelper sharedInstance].ertcEngine setRemoteView:nil forUser:userId withRegionID:0];
    }
}

- (void)onError:(NSInteger)errCode {
    // ERTC错误码文档：https://open.ys7.com/help/1822
    NSLog(@"ERTCDelegate onError: %ld", (long)errCode);
    if (errCode == ERTC_ERR_SERVICE_AccesstokenInvalid) {
        [EZToast show:@"ertcToken异常，请更新token后重新入会。"];
    } else {
        [EZToast show:[NSString stringWithFormat:@"errorCode:%ld", (long)errCode]];
    }
    [self hangUpAction];
}

#pragma mark - 其他方法

/** 邀请设备入会 */
- (void)inviteDeviceEnterMeeting {
    [EZOpenSDK inviteDeviceEnterMeeting:self.ertcParam.appID ertcToken:self.ertcDeviceToken roomId:self.ertcParam.roomId deviceSerial:self.cameraInfo.deviceSerial cameraNo:self.cameraInfo.cameraNo account:self.ertcParam.userId completion:^(NSError * _Nonnull error) {
        if (error) {
            NSLog(@"inviteDeviceEnterMeeting error:%@", error);
            [EZToast show:@"邀请设备入会失败"];
            [self hangUpAction];
        }
    }];
}

/** 取消邀请设备入会 */
- (void)cancelInviteDeviceEnterMeeting {
    [EZOpenSDK cancelInviteDeviceEnterMeeting:self.ertcParam.appID ertcToken:self.ertcDeviceToken roomId:self.ertcParam.roomId deviceSerial:self.cameraInfo.deviceSerial cameraNo:self.cameraInfo.cameraNo account:self.ertcParam.userId completion:^(NSError * _Nonnull error) {
        if (error) {
            NSLog(@"inviteDeviceEnterMeeting error:%@", error);
            [EZToast show:@"取消邀请设备入会失败"];
        }
    }];
}

/** 启动计时器 */
- (void)startUpdateTimer {
    if (!_videoTalkTimer) {
        _videoTalkTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerStart:) userInfo:nil repeats:YES];
    }
}

- (void)timerStart:(NSTimer *)timer {
    NSInteger currentTime = ++self.videoTalkSecond;
    self.videoTalkTimeLabel.text = [NSString stringWithFormat:@"%02d:%02d", (int)currentTime/60, (int)currentTime % 60];
    // 15秒后设备仍未进入会议的话，视频通话失败，退出房间
    if (self.videoTalkSecond > 15 && !self.isRemoteUserEnterRoom) {
        [EZToast show:@"设备端无人接听，视频通话结束"];
        [self stopUpdateTimer];
        [self hangUpAction];
    }
}

/** 停止定时器 */
- (void)stopUpdateTimer {
    if (_videoTalkTimer) {
        [_videoTalkTimer invalidate];
        _videoTalkTimer = nil;
    }
}

- (void)releaseERTC {
    if ([ErtcHelper sharedInstance].ertcEngine) {
        [[ErtcHelper sharedInstance].ertcEngine exitRoom];
        [ErtcHelper sharedInstance].ertcEngine.delegate = nil;
        [ErtcHelper sharedInstance].ertcEngine = nil;
        [ERTCEngine destroySharedIntance];
    }
}

#pragma mark - Data

- (void)setData {
    self.remoteUserDict = [NSMutableDictionary dictionary];
    self.isFullScreenLocalVideo = YES;
}

#pragma mark - UI

- (ERTCView *)vcsLocalPlayView {
    if (!_vcsLocalPlayView) {
        _vcsLocalPlayView = [[ERTCView alloc] init];
        _vcsLocalPlayView.backgroundColor = [UIColor blackColor];
    }
    return _vcsLocalPlayView;
}

- (ERTCView *)vcsRemotePlayView {
    if (!_vcsRemotePlayView) {
        _vcsRemotePlayView = [[ERTCView alloc] init];
        _vcsRemotePlayView.backgroundColor = [UIColor blackColor];
        _vcsRemotePlayView.hidden = YES;
    }
    return _vcsRemotePlayView;
}

- (void)setUI {
    [self microAction];// 麦克风默认关闭状态
    [self.vcsRootView addSubview:self.vcsLocalPlayView];
    [self.vcsRootView addSubview:self.vcsRemotePlayView];
    [self layoutSubviews];
    [self.microView addActionBlock:^(UIView * _Nullable view) {
        [self microAction];
    }];
    [self.soundView addActionBlock:^(UIView * _Nullable view) {
        [self soundAction];
    }];
    [self.hangUpView addActionBlock:^(UIView * _Nullable view) {
        [self hangUpAction];
    }];
    [self.switchCameraView addActionBlock:^(UIView * _Nullable view) {
        [self switchCameraAction];
    }];
    [self.cameraStateView addActionBlock:^(UIView * _Nullable view) {
        [self cameraStateAction];
    }];
    EZWeak(self);
    [self.vcsLocalPlayView addActionBlock:^(UIView * _Nullable view) {
        EZStrong(self);
        [strongself vcsLocalPlayViewAction];
    }];
    [self.vcsRemotePlayView addActionBlock:^(UIView * _Nullable view) {
        EZStrong(self);
        [strongself vcsRemotePlayViewAction];
    }];
}

#pragma mark 设置约束

- (void)layoutSubviews {
    [self.vcsLocalPlayView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(self.vcsRootView);
    }];
    [self.vcsRemotePlayView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.width.mas_equalTo(90);
        make.height.mas_equalTo(160);
        make.top.equalTo(self.vcsRootView).offset(100);
        make.right.equalTo(self.vcsRootView).offset(-5);
    }];
}

@end
