//
//  GWebSocket.m
//  TUIContact
//
//  Created by gan on 2025/3/24.
//

#import <Foundation/Foundation.h>
#import "GWebSocket.h"
#import "SocketRocket/SRWebSocket.h"
//#import "AFNetworking/AFNetworkReachabilityManager.h"
#import "GDBManager.h"
//#import "AFNetworkReachabilityManager.h"
#import "ChatListStore.h"
#import "ChatsStore.h"
#import "WebRTCStore.h"
#import "UserNetApi.h"


static int const kHeartbeatDuration = 1;
static int const timeoutError = 5;

static NSString *ping = @"{\"code\":0}";
static NSString *redeady = @"{\"code\":1}";


@interface GWebSocket ()<SRWebSocketDelegate>
@property (nonatomic,strong) SRWebSocket *socket;
@property (strong, nonatomic) NSTimer *heatBeat;

@property (nonatomic,strong) NSString *serverIpString;
@property (nonatomic,strong) NSString *userid;

@property (nonatomic,assign) BOOL autoReconnect;
@property (nonatomic,assign) NSInteger pingCount;
@property (nonatomic,assign) NSInteger reconnetCount;
@property (nonatomic,assign) BOOL isFirstload;
@property (nonatomic,strong) NSString *UUID;
@end


@implementation GWebSocket

+ (GWebSocket *_Nonnull)shareInstance{
    static id gShareInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
      gShareInstance = [[self alloc] init];
    });
    return gShareInstance;
}

- (instancetype)init {
    if (self = [super init]) {
        self.pingCount = 0;
        self.reconnetCount = 0;
        NSUUID *uid = [NSUUID UUID];
        _UUID=uid.UUIDString;
        NSLog(@"_UUID:%@",_UUID);
    }
    return self;
}

#pragma mark - Public -
- (void)connectWebSocket {
    self.autoReconnect = YES;
    [self initWebSocket];
    [self startHeartbeat];
}
- (void)closeWebSocket {
    self.autoReconnect = NO;
//    _UUID=nil;
    [self close];
}

#pragma mark 探测socket 状态
- (void)chekWebSocket{
    
}

- (void)sendMsg:(NSString *)msg {
    if (self.socket && self.socket.readyState == SR_OPEN) {
        // 只有在socket状态为SR_OPEN 时，才可以发送消息
        // 在socket状态不为SR_OPEN，可以将消息放进队列里，在websocket连上时，再发送
        NSLog(@"sendMsg:%@",msg);
        [self.socket sendString:msg error:nil];
    }
    else{
        NSLog(@"socket--------不可用");
        [self reConnect];
    }
//    NSLog(@"_UUID:%@",_UUID);
}



#pragma mark -- WebSocket
//初始化 WebSocket
- (void)initWebSocket{
    if (_socket) {
        return;
    }
    self.isFirstload =YES;
//    [self destoryHeartbeat];
    NSDictionary *userinfo =[UDManager.shareInstance getDDManager:dkuserinfo];
    self.userid =userinfo[@"id"];
    
    NSString *token = (NSString *)[UDManager.shareInstance getSDManager:gkeytoken];
    if(_UUID==nil){
        NSUUID *uid = [NSUUID UUID];
        _UUID=uid.UUIDString;
    }
    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@token=%@&client=mobile&uuid=%@",WebSocketUrl,token,_UUID]];
    //请求
    //NSLog(@"url:%@",url);
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
    //初始化请求`
    _socket = [[SRWebSocket alloc] initWithURLRequest:request];
    
    //代理协议`
    _socket.delegate = self;
    //直接连接
    [_socket open];
}

-(void)sendReady{
    NSLog(@"------%@",redeady);
    [self.socket sendString:redeady error:nil];
}
-(void)sendPing{
    [self.socket sendString:ping error:nil];
}

#pragma mark - Heart Timer -
//保活机制 探测包
- (void)startHeartbeat {
    if(self.heatBeat){
        return;
    }
    self.heatBeat = [NSTimer scheduledTimerWithTimeInterval:kHeartbeatDuration target:self selector:@selector(heartbeatAction) userInfo:nil repeats:YES];
    [self.heatBeat setFireDate:[NSDate distantPast]];
    [[NSRunLoop currentRunLoop] addTimer:_heatBeat forMode:NSRunLoopCommonModes];
}


//断开连接时销毁心跳
- (void)destoryHeartbeat{
    if(self.heatBeat){
        [self.heatBeat invalidate];
        self.heatBeat = nil;
    }
}

// 发送心跳
- (void)heartbeatAction {

    if (self.socket.readyState == SR_OPEN) {
//        NSLog(@"heartbeatAction1111");
        self.pingCount = self.pingCount+1;
        self.reconnetCount = self.reconnetCount+1;
        if(self.pingCount>5){//连续多次发送ping 没有收到回复，发起重连；
            [self.socket close];
            self.socket = nil;
            self.pingCount=0;
            [self reConnect];
        }
        if(self.pingCount>=3&&self.socket){
            [self sendPing];
        }
    }
    else{
//        NSLog(@"heartbeatAction222");
        self.pingCount = self.pingCount+1;
        self.reconnetCount = self.reconnetCount+1;
        if(self.pingCount>5){//连续多次发送ping 没有收到回复，发起重连；
            [self.socket close];
            self.socket = nil;
            self.pingCount=0;
            [self reConnect];
        }
    }
}


//重连机制
- (void)reConnect{
    if (!self.autoReconnect) {
        return;
    }
    
    self.socket = nil;
    [self initWebSocket];
    
//    NSLog(@"reConnect1111---------:%ld",(long)self.reconnetCount);
    if(self.reconnetCount>15){
        NSString *token = [UDManager.shareInstance getSDManager:gkeytoken];
        if([token isKindOfClass:[NSString class]]&&token.length>10){
            [UserNetApi getUserinfo:^(int code, NSDictionary * res) {
                NSNumber *gcode=res[@"code"];
                NSLog(@"gcode11");
                if([gcode intValue]==401){//token有效
                    [self logoutAct];
                }
            } fail:^(NSError * _Nonnull error) {
                NSLog(@"11%@", error);
            }];
        }
    }
    
}


// 关闭Socket
- (void)close {
    [self destoryHeartbeat];
    [self.socket close];
    self.socket = nil;
}

#pragma mark -- SRWebSocketDelegate
//收到服务器消息是回调
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message{
    //NSLog(@"----XTWebSocket didReceiveMessage：%@",message);
    if ([message isKindOfClass:[NSString class]]) {
        NSString *msg = (NSString *)message;
        NSError *error;
        self.pingCount = 0;
        self.reconnetCount = 0;
        if([msg isEqual:ping]){
            if(self.isFirstload){//第一次打开socket数据加载完成需要执行的
                
            }
            return;
        }
//        NSLog(@"didReceiveMessage：%@",msg);
        NSData *data = [msg dataUsingEncoding:NSUTF8StringEncoding];
        
        NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
        if (error) {
            NSLog(@"JSON解析错误: %@", error);
        } else {
//            NSLog(@"解析后的字典: %@", jsonDict);
            NSString *code =jsonDict[@"code"];
            if([code isEqualToString:SendCode_MESSAGE]){//收到消息数据
                [self onmessage:jsonDict[@"message"]];
                return;
            }
            if([code isEqualToString:SendCode_READ]){//已读消息
                [self onRead:jsonDict[@"message"]];
                return;
            }
            if([code isEqualToString:SendCode_OTHER_LOGIN]){//账号在其他地方登陆
                NSDictionary *mmsg = jsonDict[@"message"];
                NSString *uuid =mmsg[@"uuid"];
                if([uuid isEqualToString:_UUID]){
                    return;
                }
                else{
                    [self logoutAct];
                }
                return;
            }
            if([code isEqualToString:SendCode_NEW_FRIEND]){//好友申请
                NSLog(@"好友申请----------");
                [[NSNotificationCenter defaultCenter] postNotificationName: nkonAddFriendNote object:nil];
                return;
            }
            if([code isEqualToString:SendCode_GROUP_VALIDATE]){//群申请验证
                [[NSNotificationCenter defaultCenter] postNotificationName: nkonEXGroupdNote object:nil];
                return;
            }
            if([code isEqualToString:SendCode_WEBRTC_result]){//音视频通话结果
                [self onmessage:jsonDict[@"message"]];
                return;
            }
            if([code isEqualToString:SendCode_WEBRTC_CALL]){//音视频通话请求
                [WebRTCStore.shareInstance reciveMsg:jsonDict[@"message"]];
                return;
            }
            if([code isEqualToString:SendCode_WEBRTC_CLOSE]){//关闭音视频通话
                [WebRTCStore.shareInstance reciveMsg:jsonDict[@"message"]];
                return;
            }
            if([code isEqualToString:SendCode_WEBRTC_BUSY]){//音视频通话忙碌
                [WebRTCStore.shareInstance reciveMsg:jsonDict[@"message"]];
                return;
            }
            if([code isEqualToString:SendCode_WEBRTC_xinling]){//webrtc信令交互
                [WebRTCStore.shareInstance reciveMsg:jsonDict[@"message"]];
                return;
            }
            if([code isEqualToString:SendCode_deletemsg]){//删除消息
               
                return;
            }
            if([code isEqualToString:SendCode_WEBRTC_DFBUSY]){//对方正在忙
                [WebRTCStore.shareInstance reciveMsg:jsonDict[@"message"]];
                return;
            }
            if([code isEqualToString:SendCode_RECMsg]){//收到消息回执
                
                return;
            }
        }
        if(self.delegate){
            [self.delegate GWebSocketAction:message];
        }
    }
}

//连接成功
- (void)webSocketDidOpen:(SRWebSocket *)webSocket{
    NSLog(@"-----XTWebSocket DidOpen");
    
    // 下面逻辑，根据业务情况处理
    if (self.socket != nil) {
        // 只有 SR_OPEN 开启状态才能调 send 方法啊，不然要崩
        if (_socket.readyState == SR_OPEN) {
            //NSString *jsonString = @"{\"sid\": \"13b313a3-fea9-4e28-9e56-352458f7007f\"}";
            //[_socket sendString:jsonString error:nil];  //发送数据包
            [self sendReady];
        } else if (_socket.readyState == SR_CONNECTING) {
            NSLog(@"正在连接中，重连后其他方法会去自动同步数据");
            // 每隔2秒检测一次 socket.readyState 状态，检测 10 次左右
            // 只要有一次状态是 SR_OPEN 的就调用 [ws.socket send:data] 发送数据
            // 如果 10 次都还是没连上的，那这个发送请求就丢失了，这种情况是服务器的问题了，小概率的
            // 代码有点长，我就写个逻辑在这里好了
            
        } else if (_socket.readyState == SR_CLOSING || _socket.readyState == SR_CLOSED) {
            // websocket 断开了，调用 reConnect 方法重连
            NSLog(@"websocket 断开了，调用 reConnect 方法重连");
            [self reConnect];
        }
    }
}


//连接失败的回调
- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error{
    NSLog(@"XTWebSocket didFailWithError %@",error);
    // 1.判断当前网络环境，如果断网了就不要连了，等待网络到来，在发起重连
    // 2.判断调用层是否需要连接，例如用户都没在聊天界面，连接上去浪费流量
    
//    [self reConnect];
}

//连接断开的回调
- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean{
    NSLog(@"XTWebSocket Close code %ld reason %@",(long)code,reason);
}

- (void)webSocket:(SRWebSocket *)webSocket didReceivePong:(NSData *)pongPayload {
    NSLog(@"XTWebSocket Pong");
}

#pragma mark - 其他 -
- (void)dealloc {
    NSLog(@"LFC: dealloc: %@", self);
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}


#pragma mark -数据处理-

-(void)onmessage:(NSDictionary *)msg{
    NSLog(@"onmessage:%@",msg);
//    NSLog(@"%@",msg[@"chatId"]);
//    NSLog(@"%@",msg[@"fromId"]);
    //NSLog(@"%@",msg[@"content"]);
    
    NSMutableDictionary *mutablemsg = [msg mutableCopy];
    
    
    if([self.userid isEqual:msg[@"fromId"]]){
        [mutablemsg setObject:[NSNumber numberWithBool:YES] forKey:@"mine"];
//        NSLog(@"----------------------11");
        [ChatsStore.shareInstance deleteMineTmpMsg:msg];//删除本地临时消息
    }else{
        if([Friendchat isEqual:msg[@"type"]]){
            [mutablemsg setObject:msg[@"fromId"] forKey:@"chatId"];
        }
    }
    [ChatsStore.shareInstance reciveMsg:mutablemsg];//聊天窗信息
    [ChatListStore.shareInstance reciveMsg:[mutablemsg copy]];//聊天窗列表
    [[NSNotificationCenter defaultCenter] postNotificationName:nkonNewMessageNote object:mutablemsg];
}

//消息已收到回执
-(void)sendRecNote:(NSDictionary *)msg{
    NSDictionary *dic =@{
        @"chatId":msg[@"chatId"],
        @"userId":self.userid,
        @"msgId":msg[@"id"],
        @"type":msg[@"type"]
    };
    NSDictionary *sendInfo = @{
        @"code":SendCode_RECMsg,
        @"message":dic,
    };
    NSError *error;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:sendInfo options:0 error:&error];
    if (!jsonData) {
        NSLog(@"Got an error: %@", error);
    } else {
        NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
//        NSLog(@"jsonString:%@",jsonString);
        [self sendMsg:jsonString];
    }
}

//收到已读消息
-(void)onRead:(NSDictionary *)dis{
    [ChatsStore.shareInstance updatereadTime:dis];
}


//异地登录
-(void)logoutAct{
    NSLog(@"logoutAct");
    [UserNetApi logout:nil succ:^(int code, NSDictionary * res) {
//        NSLog(@"res:%@",res);
        [[NSNotificationCenter defaultCenter] postNotificationName: nkonLogoutSucc object:nil];
    } fail:^(NSError * _Nonnull error) {
        NSLog(@"");
    }];
}



@end
