//
//  GMNimChannelManager.m
//  Gengmei
//
//  Created by Jessica on 2020/4/16.
//  Copyright © 2020 更美互动信息科技有限公司. All rights reserved.
//

#import "GMNimChannelManager.h"
#import <CommonCrypto/CommonDigest.h>
@import GMRouter;
@implementation GMNimChannelManager
+ (instancetype)shareInstance {
    static dispatch_once_t onceToken;
    static id instance = nil;
    dispatch_once(&onceToken, ^{
        instance = [[[self class] alloc] init];
    });
    return instance;
}
#pragma mark - 频道相关

/// 创建频道
/// @param channelName 频道名称
/// @param channelType 类型
/// @param resultBlock 结果
- (void)doCreateChannelWithChannelName:(NSString *)channelName channelType:(NIMSignalingChannelType)channelType resultBlock:(nonnull NIMResultCreateBlock)resultBlock {
    NIMSignalingCreateChannelRequest *request = [[NIMSignalingCreateChannelRequest alloc] init];
    request.channelName = channelName;
    request.channelType = channelType;
    [[NIMSDK sharedSDK].signalManager signalingCreateChannel:request completion:^(NSError * _Nullable error, NIMSignalingChannelInfo * _Nullable response) {
            resultBlock(response);
    }];
}
/// 加入频道
/// @param channelId channelId
/// @param resultBlock 结果
- (void)doJoinChannelWithChannelId:(NSString *)channelId resultBlock:(nonnull NIMResultBlock)resultBlock{
    NIMSignalingJoinChannelRequest *request = [[NIMSignalingJoinChannelRequest alloc] init];
    request.channelId = channelId;
    [[NIMSDK sharedSDK].signalManager signalingJoinChannel:request completion:^(NSError * _Nullable error, NIMSignalingChannelDetailedInfo * _Nullable response) {
        if (error && error.code != 10407) { // 已经在房间
            resultBlock(NO);
        } else {
            resultBlock(YES);
        }
    }];
}

/// 加入并邀请对方加入频道
/// @param channelId channelId
/// @param accountId 对方，被邀请人，必填
/// @param customInfo 通知事件额外字段，非必填（邀请者附加的自定义信息，透传给被邀请者）
/// @param resultBlock 结果
- (void)doJoinAndInviteJoinChannelWithChannelId:(NSString *)channelId accountId:(NSString *)accountId customInfo:(NSString *)customInfo resultBlock:(nonnull NIMResultBlock)resultBlock {
    [self doJoinChannelWithChannelId:channelId resultBlock:^(BOOL isSuccess) {
        if (isSuccess) {
            [self doInviteJoinWithChannelId:channelId accountId:accountId customInfo:customInfo resultBlock:^(BOOL isSuccess) {
                resultBlock(isSuccess);
            }];
        } else {
            resultBlock(NO);
        }
    }];
}

/// 离开频道
/// @param channelId channelId
/// @param resultBlock 结果
- (void)doLeaveChannelWithChannelId:(NSString *)channelId resultBlock:(nonnull NIMResultBlock)resultBlock {
    NIMSignalingLeaveChannelRequest *request = [[NIMSignalingLeaveChannelRequest alloc] init];
    request.channelId = channelId;
    [[NIMSDK sharedSDK].signalManager signalingLeaveChannel:request completion:^(NSError * _Nullable error) {
        if (error) {
            resultBlock(NO);
        } else {
            resultBlock(YES);
        }
    }];
}

/// 关闭频道
/// @param channelId channelId
/// @param resultBlock 结果
- (void)doCloseChannelWithChannelId:(NSString *)channelId resultBlock:(nonnull NIMResultBlock)resultBlock {
    NIMSignalingCloseChannelRequest *req = [[NIMSignalingCloseChannelRequest alloc] init];
    req.channelId = channelId;
    [[NIMSDK sharedSDK].signalManager signalingCloseChannel:req completion:^(NSError * _Nullable error) {
        if (error) {
            resultBlock(NO);
        } else {
            resultBlock(YES);
        }
    }];
}

#pragma mark - 邀请相关

///  邀请加入频道
/// @param channelId 频道Id 必填
/// @param accountId 对方，被邀请人，必填
/// @param requestId 邀请唯一标识（用于标识持续呼叫）,必填（邀请者邀请的请求id，需要邀请者填写，之后取消邀请、拒绝、接受需要复用该标示，长度必须小于128，超出会报参数错误）
/// @param customInfo 通知事件额外字段，非必填（邀请者附加的自定义信息，透传给被邀请者）
/// @param resultBlock 结果
- (void)doInviteJoinWithChannelId:(NSString *)channelId accountId:(NSString *)accountId customInfo:(NSString *)customInfo resultBlock:(nonnull NIMResultBlock)resultBlock {
    NIMSignalingInviteRequest *request = [[NIMSignalingInviteRequest alloc] init];
    request.channelId = channelId;
    request.accountId = accountId;
    request.requestId = [self createRequestId];
    request.customInfo = customInfo;
    [[NIMSDK sharedSDK].signalManager signalingInvite:request completion:^(NSError * _Nullable error) {
        if (error) {
            resultBlock(NO);
        } else {
            resultBlock(YES);
        }
    }];
}
///  取消邀请
/// @param channelId 频道Id 必填
/// @param accountId 对方，被邀请人，必填
/// @param requestId 邀请唯一标识（用于标识持续呼叫）,必填（邀请者邀请的请求id，需要邀请者填写，之后取消邀请、拒绝、接受需要复用该标示，长度必须小于128，超出会报参数错误）
/// @param customInfo 通知事件额外字段，非必填（邀请者附加的自定义信息，透传给被邀请者）
/// @param resultBlock 结果
- (void)doCancelInviteWithChannelId:(NSString *)channelId accountId:(NSString *)accountId customInfo:(NSString *)customInfo resultBlock:(nonnull NIMResultBlock)resultBlock {
    NIMSignalingCancelInviteRequest *request = [[NIMSignalingCancelInviteRequest alloc] init];
    request.channelId = channelId;
    request.accountId = accountId;
    request.requestId = [self createRequestId];
    request.customInfo = customInfo;
    [[NIMSDK sharedSDK].signalManager signalingCancelInvite:request completion:^(NSError * _Nullable error) {
        if (error) {
            resultBlock(NO);
        } else {
            resultBlock(YES);
        }
    }];
}

///  接受邀请
/// @param channelId 频道Id 必填
/// @param accountId 对方，被邀请人，必填
/// @param requestId 邀请唯一标识（用于标识持续呼叫）,必填（邀请者邀请的请求id，需要邀请者填写，之后取消邀请、拒绝、接受需要复用该标示，长度必须小于128，超出会报参数错误）
/// @param acceptCustomInfo 通知事件额外字段，非必填(被邀请者附加的自定义信息，透传给邀请者)
/// @param resultBlock 结果
- (void)doAcceptInviteWithChannelId:(NSString *)channelId accountId:(NSString *)accountId acceptCustomInfo:(NSString *)acceptCustomInfo resultBlock:(nonnull NIMResultBlock)resultBlock {
    NIMSignalingAcceptRequest *request = [[NIMSignalingAcceptRequest alloc] init];
    request.channelId = channelId;
    request.accountId = accountId;
    request.requestId = [self createRequestId];
    request.acceptCustomInfo = acceptCustomInfo;
    [[NIMSDK sharedSDK].signalManager signalingAccept:request completion:^(NSError * _Nullable error, NIMSignalingChannelDetailedInfo * _Nullable response) {
        if (error) {
            resultBlock(NO);
        } else {
            resultBlock(YES);
        }
    }];
}

///  拒绝邀请
/// @param channelId 频道Id 必填
/// @param accountId 对方，被邀请人，必填
/// @param requestId 邀请唯一标识（用于标识持续呼叫）,必填（邀请者邀请的请求id，需要邀请者填写，之后取消邀请、拒绝、接受需要复用该标示，长度必须小于128，超出会报参数错误）
/// @param customInfo 通知事件额外字段，非必填
/// @param resultBlock 结果
- (void)doRejectInviteWithChannelId:(NSString *)channelId accountId:(NSString *)accountId customInfo:(NSString *)customInfo resultBlock:(nonnull NIMResultBlock)resultBlock {
    NIMSignalingRejectRequest *request = [[NIMSignalingRejectRequest alloc] init];
    request.channelId = channelId;
    request.accountId = accountId;
    request.requestId = [self createRequestId];
    request.customInfo = customInfo;
    [[NIMSDK sharedSDK].signalManager signalingReject:request completion:^(NSError * _Nullable error) {
        if (error) {
            resultBlock(NO);
        } else {
            resultBlock(YES);
        }
    }];
}

/// 直接呼叫
/// @param accountId 对方accid，被邀请者的账号
/// @param customInfo 通知事件额外字段，非必填
/// @param resultBlock 结果
- (void)doCallWithAccountId:(NSString *)accountId customInfo:(NSString *)customInfo resultBlock:(nonnull NIMResultBlock)resultBlock {
    NIMSignalingCallRequest *request = [[NIMSignalingCallRequest alloc] init];
    NSInteger user = (NSInteger)[[GMRouter sharedInstance] pushScheme:@"gengmei://gm_userId"];
    request.uid = user;
    request.accountId = accountId;
    request.requestId = [self createRequestId];
    request.customInfo = customInfo;
    [[NIMSDK sharedSDK].signalManager signalingCall:request completion:^(NSError * _Nullable error, NIMSignalingChannelDetailedInfo * _Nullable response) {
        if (error) {
            resultBlock(NO);
        } else {
            resultBlock(YES);
        }
    }];
}

- (NSString *)createRequestId {
    NSString *requestId = @"";
    // 1、先取 当前时间 按照 "年/月/日/时分" 转换 作为图片路径的上半部分--> 2018/10/25/1821
    NSDate* date = [NSDate dateWithTimeIntervalSinceNow:0];//获取当前时间0秒后的时间
    NSTimeInterval timeNow = [date timeIntervalSince1970];
    NSString *frontPart = [self getDateStringWithTimeStr:timeNow];
    
    requestId = [requestId stringByAppendingString:frontPart];
    
    // 2、取当前的时间戳 + 随机字符串(长度 32) 组成字符串，将该字符串 MD5哈希，取该哈希值的前 12位 作为下半部分 --> caf8f8d86886
    NSString *timeNowStr = [NSString stringWithFormat:@"%.0f", timeNow];
    NSString *radomStr = [self getRadomString];
    NSString *secondPart = [timeNowStr stringByAppendingString:radomStr];
    
    NSString *secondPartMD5 = [[self MD5ForLower32Bate:secondPart] substringToIndex:12];
    
    return [NSString stringWithFormat:@"%@/%@", requestId, secondPartMD5];
}

// 时间戳转字符串
- (NSString *)getDateStringWithTimeStr:(float )time{
    NSDate *detailDate=[NSDate dateWithTimeIntervalSince1970:time];
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; //实例化一个NSDateFormatter对象
    //设定时间格式,这里可以设置成自己需要的格式
    [dateFormatter setDateFormat:@"yyyy/MM/dd/HHmm"];
    NSString *currentDateStr = [dateFormatter stringFromDate: detailDate];
    
    return currentDateStr;
}

// 取随机字符串
- (NSString *)getRadomString {
    NSArray *array = [[NSArray alloc] initWithObjects:@"a",@"b",@"c",@"d",@"e",@"f",@"g",@"h",@"i",@"j",@"k",@"l",@"m",@"n",@"o",@"p",@"q",@"r",@"s",@"t",@"u",@"v",@"w",@"x",@"y",@"z",@"0",@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9",nil];
    NSMutableArray *randomArray = [[NSMutableArray alloc] init];
    while (randomArray.count < 32) {
        int r = arc4random() % [array count];
        [randomArray addObject:[array objectAtIndex:r]];
    }
    return [randomArray componentsJoinedByString:@""];
}

// MD5加密
-(NSString *)MD5ForLower32Bate:(NSString *)str{
    
    //要进行UTF8的转码
    const char* input = [str UTF8String];
    unsigned char result[CC_MD5_DIGEST_LENGTH];
    CC_MD5(input, (CC_LONG)strlen(input), result);
    
    NSMutableString *digest = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
    for (NSInteger i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
        [digest appendFormat:@"%02x", result[i]];
    }
    return digest;
}

@end
