//
//  ChatController.m
//  AIIM
//
//  Created by gan on 2025/4/6.
//

#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
#import <Photos/Photos.h>
#import <PhotosUI/PhotosUI.h>
#import <MobileCoreServices/MobileCoreServices.h>
#import <UniformTypeIdentifiers/UniformTypeIdentifiers.h>
#import "ChatController.h"
#import "FriendController.h"
#import "GroupController.h"
#import "ChatsStore.h"
#import "ChatListStore.h"
#import "FriendNetApi.h"
#import "FileNetApi.h"
#import "GroupNetApi.h"
#import "UserNetApi.h"
#import "GWebSocket.h"
#import "UDManager.h"
#import "CryptoAES.h"
#import "GDBManager.h"
#import "chatpopView.h"
#import "config.h"
#import "JSGController.h"
#import "SDWebImage/SDWebImage.h"
#import "ChatMessageModel.h"
#import "ChatFileModel.h"
#import "AppDelegate.h"

#import "HistoryPreloader.h"
#import "chatCellView.h"
#import "CameraViewController.h"
#import "ForwardViewController.h"
#import "ChatBatchView.h"
#import "ChatQuoteView.h"
#import "ChatAtMemberView.h"
#import "PopupView.h"
#import "MentionTextView.h"
#import "TopPopupView.h"

#import "OSSManager.h"

static const CGFloat kQuoteViewHeight = 46.0f;
@interface ChatController()<UITextViewDelegate,ChatsStoreDelegate,UITableViewDelegate,UITableViewDataSource,chatpopViewDelegate,PHPickerViewControllerDelegate,UINavigationControllerDelegate,UIDocumentPickerDelegate,UIScrollViewDelegate,OSSManagerDelegate>

@property (weak, nonatomic) IBOutlet UILabel *titlelb;
@property (weak, nonatomic) IBOutlet UITableView *_tableView;

@property(nonatomic, strong) MentionTextView *inputView;
//@property(nonatomic, strong) UITextView *inputView;
@property (weak, nonatomic) IBOutlet UIView *bottonView;
@property (weak, nonatomic) IBOutlet UIButton *yuyinctr;
@property (weak, nonatomic) IBOutlet UIButton *fasngBt;
@property (weak, nonatomic) IBOutlet UIButton *gengduoBt;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *inputViewBottom;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *bottomViewHeight;

@property (nonatomic, strong) HistoryPreloader * preloader;

//录音
@property(nonatomic, strong) UIButton *AVRecordBt;
@property (nonatomic,strong) AVAudioRecorder *recorder;
@property (nonatomic,strong) NSString *AudiofilePath;
@property (nonatomic,strong) NSString *AudiofileName;
@property (nonatomic) NSInteger rcdL;
@property (strong, nonatomic) NSTimer *heatBeat;
@property (nonatomic,strong) AVPlayer *player;


@property (nonatomic) CGFloat keyboardHeight;
@property (nonatomic) BOOL isfriend;
@property (nonatomic) BOOL keybarShow;
@property (nonatomic) BOOL canloadhistory;
@property (nonatomic) BOOL canloadhistoryMore;
@property (nonatomic) CGFloat offset;

@property (nonatomic,strong) NSString *username;
@property (nonatomic,strong) NSString *useravatar;
@property (nonatomic,strong) UITextView *textV;
@property (nonatomic,strong) chatpopView *popView;
@property (nonatomic,strong) UIView *markView;
@property (nonatomic, strong) ChatBatchView * batchView;
@property (nonatomic, strong) ChatQuoteView * quoteView;
@property (nonatomic, assign) BOOL isQuoteMessage;

@property (strong, nonatomic) NSTimer *timer;


@property (nonatomic, strong) NSDictionary * groupInfo;

@property (nonatomic,strong) NSMutableArray *messageArray;
@property (nonatomic, strong) NSMutableArray * forwordMsgArray;
@property (nonatomic, strong) NSMutableArray * atSomeoneArray;
@property (nonatomic, assign) BOOL isBatchMode;

@property (nonatomic, assign) BOOL showLoading;
@property (nonatomic, assign) BOOL isInit;


@end

@implementation ChatController
- (UIStatusBarStyle)preferredStatusBarStyle {
    return UIStatusBarStyleLightContent;
}

-(void)viewDidLoad{
    [super viewDidLoad];
    [self.navigationController setNavigationBarHidden:YES animated:NO];
    [self._tableView registerClass:chatCellView.class forCellReuseIdentifier:@"chatCellView"];
    
    self._tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    self._tableView.backgroundColor = [UIColor clearColor];
    self._tableView.delegate=self;
    self._tableView.dataSource = self;
    _isfriend=true;
    _isInit = YES;
    
    CGFloat safeBottom = [UIDevice safeDistanceBottom];
    UIView *temp = [[UIView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, 60+safeBottom)];
    temp.backgroundColor = UIColor.blackColor;
    [_bottonView insertSubview:temp atIndex:0];
    
    //输入框
    _inputView = [[MentionTextView alloc] initWithFrame:CGRectMake(54, 10, self.view.frame.size.width - 180, 40)];
    _inputView.backgroundColor = globalColor(GCTypeDark2);
    _inputView.layer.cornerRadius = 4.0;
    _inputView.textColor = [UIColor blackColor];
    _inputView.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
    [_bottonView addSubview:_inputView];
    _inputView.delegate = self; // 设置代理
    _inputView.scrollEnabled = NO; // 禁止滚动，使内容自适应高度
    [_inputView setup];
    //删除@用户名
    weakSelf(self);
    _inputView.mentionDeleteHandler = ^(NSString * _Nonnull deletedMention, NSUInteger index) {
//        NSLog(@"第%ld---%@",index,deletedMention);
//        NSLog(@"weakself.atSomeoneArray:%@",weakself.atSomeoneArray);
        if ([deletedMention isEqualToString:@"@所有人"]) {
            return;
        }
        [weakself removeAtList:index];
    };
    
    [_inputView mas_makeConstraints:^(MASConstraintMaker *make) {
//        make.height.mas_equalTo(40);
        make.left.equalTo(self.yuyinctr.mas_right).mas_offset(10);
        make.right.equalTo(self.gengduoBt.mas_left).mas_offset(-10);
        make.bottom.mas_offset(-10);
        make.top.mas_offset(10);
    }];
    
    
    //录音按钮
    _AVRecordBt = [[UIButton alloc] initWithFrame:CGRectMake(54, 10, self.view.frame.size.width - 180, 40)];
    [_bottonView addSubview:_AVRecordBt];
    _AVRecordBt.alpha = 0;
    _AVRecordBt.layer.backgroundColor = globalColor(GCTypeDark2).CGColor;
    _AVRecordBt.layer.cornerRadius = 4.0;
    [_AVRecordBt setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [_AVRecordBt setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
    [_AVRecordBt setTitle:@" 按住 说话" forState:UIControlStateNormal];
    [_AVRecordBt addTarget:self action:@selector(longTarget) forControlEvents:UIControlEventTouchDown];
    [_AVRecordBt addTarget:self action:@selector(UpInside) forControlEvents:UIControlEventTouchUpInside];
    
    [self.bottonView addSubview:self.quoteView];
    [self.quoteView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.mas_equalTo(_inputView.mas_left);
        make.size.mas_equalTo(CGSizeMake(SCREEN_WIDTH-180, 30));
        make.top.mas_equalTo(self.inputView.mas_bottom).offset(8);
    }];
    
    // 注册键盘显示通知
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                selector:@selector(keyboardWillShow:)
                                                    name:UIKeyboardWillShowNotification object:nil];
    // 注册键盘隐藏通知
    [[NSNotificationCenter defaultCenter] addObserver:self
                                            selector:@selector(keyboardWillHide:)
                                                name:UIKeyboardWillHideNotification object:nil];
    //nkonNewMessageNote
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(othersChatMessageAlert:)
                                                 name:nkonNewMessageNote
                                               object:nil];
    
    [self inidatastate];
    _textV=[[UITextView alloc] init];
    
    _markView=[[UIView alloc] init];
    [self.view addSubview:_markView];
    
    NSArray *nibs = [[NSBundle mainBundle] loadNibNamed:@"chatpopView" owner:self options:nil];
    _popView = [nibs objectAtIndex:0];
    [self.view addSubview:_popView];
    _popView.delegate= self;
    [self initpopbottonView];
    [self setupPreloader];
    
    NSDictionary *userinfo = [UDManager.shareInstance getDDManager:dkuserinfo];
    NSLog(@"viewDidLoad userinfo:%@",userinfo);
    self.userId = userinfo[@"id"];
    self.username = userinfo[@"name"];
    self.useravatar = userinfo[@"avatar"];
    
    ChatsStore.shareInstance.delegate = self;
    ChatsStore.shareInstance.chatId = self.chatId;
    ChatsStore.shareInstance.userid =self.userId;
    ChatListStore.shareInstance.chatId = self.chatId;
    [ChatsStore.shareInstance getchatReadTime:self.chatId];
    [OSSManager sharedManager].delegate = self;
    
    _showLoading = YES;
    NSString *type=@"";
    if(self.type==0){
        type=@"0";
        [ChatsStore.shareInstance reloadData:self.chatId type:self.type];
    }
    else if(self.type==1){
        type=@"1";
//        [ChatsStore.shareInstance reloadQunData:@"1871105598206210050" type:self.type];
        [ChatsStore.shareInstance getGroupUserList:self.chatId];
        [self getGroupInfo];
    }
    _canloadhistory=true;
    
    NSDictionary *chatMsg=@{
        @"chatId":self.chatId,
        @"name":self.titlename?:@"",
        @"avatar":self.avatar?:@"",
        @"type":type
    };
//    NSLog(@"self.chatId:%@",self.chatId);
    [ChatListStore.shareInstance chatDidOpen:chatMsg];
    
    [GWebSocket.shareInstance chekWebSocket];
}

-(void)reloadAllData{
    [self.messageArray removeAllObjects];
    self.msgList = @[];
    [__tableView reloadData];
    
    _titlelb.text = self.titlename;
    
    ChatsStore.shareInstance.delegate = self;
    [OSSManager sharedManager].delegate = self;
    ChatsStore.shareInstance.chatId = self.chatId;
    ChatsStore.shareInstance.userid =self.userId;
    ChatListStore.shareInstance.chatId = self.chatId;
    [ChatsStore.shareInstance getchatReadTime:self.chatId];
    NSString *type=@"";
    if(self.type==0){
        type=@"0";
        [ChatsStore.shareInstance reloadData:self.chatId type:self.type];
    }
    else if(self.type==1){
        type=@"1";
//        [ChatsStore.shareInstance reloadQunData:@"1871105598206210050" type:self.type];
        [ChatsStore.shareInstance getGroupUserList:self.chatId];
        [self getGroupInfo];
    }
    _canloadhistory=true;
    
    NSDictionary *chatMsg=@{
        @"chatId":self.chatId,
        @"name":self.titlename?:@"",
        @"avatar":self.avatar?:@"",
        @"type":type
    };
//    NSLog(@"self.chatId:%@",self.chatId);
    [ChatListStore.shareInstance chatDidOpen:chatMsg];
    [GWebSocket.shareInstance chekWebSocket];
    [self movetoBotton];
}


- (void)dealloc {
//    NSLog(@"dealloc-----:%@",self);
    [self.preloader stopMonitoring];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    ChatsStore.shareInstance.delegate = nil;
    [OSSManager sharedManager].delegate = nil;
    ChatsStore.shareInstance.chatId = nil;
}
-(void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];
    _titlelb.text = self.titlename;

}

-(void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    
}


- (ChatBatchView *)batchView{
    if (!_batchView) {
        _batchView = [[ChatBatchView alloc] initWithFrame:CGRectMake(0, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_X_BTM+64)];
        [self.view addSubview:_batchView];
    }
    return _batchView;
}

- (ChatQuoteView *)quoteView{
    if (!_quoteView) {
        _quoteView = [[ChatQuoteView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH-180, 30)];
        _quoteView.hidden = YES;
        [_quoteView.closeBtn addTarget:nil action:@selector(closeQuoteView) forControlEvents:UIControlEventTouchUpInside];
//        [_quoteView.closeBtn jk_addActionHandler:^(NSInteger tag) {
//            [self closeQuoteView];
//        }];
    }
    return _quoteView;
}

-(NSMutableArray *)messageArray{
    if (!_messageArray) {
        _messageArray = [NSMutableArray array];
    }
    return _messageArray;
}

-(NSMutableArray *)forwordMsgArray{
    if (!_forwordMsgArray) {
        _forwordMsgArray = [NSMutableArray array];
    }
    return _forwordMsgArray;
}

-(NSMutableArray *)atSomeoneArray{
    if (!_atSomeoneArray) {
        _atSomeoneArray = [NSMutableArray array];
    }
    return _atSomeoneArray;
}

-(void)inidatastate{
    [FriendNetApi isfriend:self.chatId succ:^(int code, NSDictionary * res) {
        NSLog(@"isfriend:%@",[res[@"data"] class]);
        BOOL state = res[@"data"];
        if(state){
            NSLog(@"isfriend1:");
            self.isfriend = true;
        }
        else{
            NSLog(@"isfriend2:");
            self.isfriend=false;
        }
    } fail:^(NSError * _Nonnull error) {
        
    }];
}

-(void)initpopbottonView{
    [self hidBottonView];
//    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
//    // 将手势添加到主视图上
//    [self.view addGestureRecognizer:tap];
    
    UITapGestureRecognizer *tapbotton = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissBotton)];
    // 将手势添加到主视图上
    [_markView addGestureRecognizer:tapbotton];
    _keybarShow=false;
}


- (IBAction)fanhui:(id)sender {
    NSLog(@"fanhui-------");
    [self dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction)rightBt:(id)sender {
    if (self.type==0) {
        UIStoryboard *board = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
        FriendController *friendctr = [board instantiateViewControllerWithIdentifier:@"FriendController"];
        UINavigationController *uiNavC = [[UINavigationController alloc] initWithRootViewController:friendctr];
        uiNavC.modalPresentationStyle = UIModalPresentationFullScreen;
        friendctr.friendMsg = nil;
        friendctr.friendId = self.chatId;
        [self presentViewController :uiNavC animated:YES completion:nil];
    }
    else{
        UIStoryboard *board = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
        GroupController *friendctr = [board instantiateViewControllerWithIdentifier:@"GroupController"];
        UINavigationController *uiNavC = [[UINavigationController alloc] initWithRootViewController:friendctr];
        uiNavC.modalPresentationStyle = UIModalPresentationFullScreen;
        friendctr.groupMsg = nil;
        friendctr.groupId = self.chatId;
        [self presentViewController :uiNavC animated:YES completion:nil];
    }
    
}

- (IBAction)yuyinBt:(id)sender {
    if(_AVRecordBt.alpha==1){
        _AVRecordBt.alpha = 0;
        _inputView.alpha = 1;
        [_yuyinctr setImage:[UIImage imageNamed:@"yuyin"] forState:UIControlStateNormal];
        [self dismissKeyboard];
    }
    else{
        _AVRecordBt.alpha = 1;
        _inputView.alpha = 0;
        [_yuyinctr setImage:[UIImage imageNamed:@"jianpan"] forState:UIControlStateNormal];
    }
}
- (IBAction)biaoqingBt:(id)sender {
    
}

- (IBAction)gengduo:(id)sender {
    [self showBottonView];
}


- (IBAction)fasongBt:(id)sender {
    NSLog(@"fasongBt:1");
    if(_isfriend){
        NSLog(@"fasongBt:2");
        [self sendtextData];
    }
    else{//提示不是好友
        NSLog(@"fasongBt:3");
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"不是好友关系" preferredStyle:UIAlertControllerStyleAlert];
        [self presentViewController:alert animated:NO completion:nil];
        NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.5 target:self selector:@selector(dismissAlert:) userInfo:alert repeats:NO];

    }
    
    //[app showAlert:@"警告" msg:@"不是好友关系" timelate:2];
}

- (void)dismissAlert:(NSTimer *)timer {
    UIAlertController *alert = [timer userInfo];
    [alert dismissViewControllerAnimated:YES completion:nil];
    alert = nil;
}

#pragma mark 群信息
- (void)getGroupInfo{
    [GroupNetApi getGroupInfo:self.chatId succ:^(int code, NSDictionary * _Nullable result) {
//        NSLog(@"GroupInfo:----%@",result);
        self.groupInfo = result[@"data"];
        self.titlename = self.groupInfo[@"name"];
        self.titlelb.text = self.groupInfo[@"name"];
    } fail:^(NSError * _Nonnull error) {
        NSLog(@"error:%@",error);
    }];
}

#pragma mark ChatsStoreDelegate

-(void)getlocalData{
    [ChatsStore.shareInstance reloadData:self.chatId type:self.type];
}

-(void)ChatsChange:(NSArray *)msgList type:(NSInteger)typpe{
//    NSLog(@"msgList:%@",msgList);
    if([msgList count]==0){
        return;
    }
    
    if(self.msgList.count>0){
        NSArray *array = msgList.copy;
        NSMutableArray *marray = [NSMutableArray new];
//        [marray addObjectsFromArray:self.msgList];
        [marray addObjectsFromArray:array];
        NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray:marray];
        NSMutableArray *uniqueArray = [orderedSet.array mutableCopy];
        self.msgList = [ChatsStore.shareInstance arraysort:uniqueArray];
    }
    else{
        self.msgList = msgList.copy;
        NSMutableArray *array = [NSMutableArray new];
        [array addObjectsFromArray:self.msgList];
        NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray:array];
        NSMutableArray *uniqueArray = [orderedSet.array mutableCopy];
        self.msgList = [ChatsStore.shareInstance arraysort:uniqueArray];
    }
    
//    NSLog(@"self.msgList11:%@",self.msgList);
    NSMutableArray * tempArray = [NSMutableArray array];
    for (NSDictionary * msg in self.msgList) {
//        NSLog(@"msg:%@",msg);
        ChatMessageModel *message = [ChatMessageModel modelWithDictionary:msg];
        if (message.avatar.length==0 && message.isSender) {
            message.avatar = self.useravatar;
        }else if (message.avatar.length==0 && !message.isSender) {
            message.avatar = self.avatar;
        }
        if ([message.chatId isEqualToString:self.chatId]) {
            [tempArray addObject:message];
        }
    }
//    NSLog(@"----222---:coun-------:%lu",(unsigned long)tempArray.count);
    NSMutableArray * indexPathArray = [NSMutableArray array];
    BOOL isHistoryRecord = NO;
    if (self.messageArray.count == 0) {
        
        [self.messageArray removeAllObjects];
        [self.messageArray addObjectsFromArray:tempArray];
//        NSLog(@"----222---:count ==%lu",(unsigned long)self.messageArray.count);
        //禁用隐式动画 加载历史消息
        [CATransaction begin];
        [CATransaction setDisableActions:YES];
        [self._tableView reloadData];
        NSIndexPath *lastRowIndexPath = [NSIndexPath indexPathForRow:([self._tableView numberOfRowsInSection:0] - 1) inSection:0];
        [self._tableView scrollToRowAtIndexPath:lastRowIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO];
        [CATransaction commit];
        [self.preloader startMonitoring];
        [self faSongYidu];
        _canloadhistory = true;
        return;
    }else{
        
        for (ChatMessageModel *message in tempArray) {
            BOOL isContain = NO;
//            NSLog(@"----333---:%ld",(long)message.localtime);
            for (ChatMessageModel * localMessage in self.messageArray) {
                if (localMessage.localtime==message.localtime) {
                    isContain = YES;
                    if (![message.url isEqualToString:localMessage.url] || ![message.readStatus isEqualToString:localMessage.readStatus]||localMessage.messageType!=message.messageType) {
                        [localMessage exchangeModelWithModel:message];
//                        NSLog(@"----11---:%@",message.content);
                        dispatch_async(dispatch_get_main_queue(), ^{
                            [CATransaction begin];
                            [CATransaction setDisableActions:YES];
                            NSIndexPath *reloadIndexPath = [NSIndexPath indexPathForRow:[self.messageArray indexOfObject:localMessage] inSection:0];
                            [self._tableView beginUpdates];
                            [self._tableView reloadRowsAtIndexPaths:@[reloadIndexPath] withRowAnimation:UITableViewRowAnimationNone];
                            [self._tableView endUpdates];
                            [CATransaction commit];
                        });
                    }else{
                        [localMessage exchangeModelWithModel:message];
//                        NSLog(@"----222---:%@",message.content);
                    }
                }
                else{
//                    NSLog(@"1122211------");
                }
            
            }
            
            if (!isContain) {
//                NSLog(@"!isContain");
                
                ChatMessageModel *lastObj = self.messageArray.lastObject;
                
                if (lastObj.timestamp > message.timestamp) {
                    //插入历史消息
                    
                    for (ChatMessageModel * localMessage in self.messageArray) {
                        if(localMessage.timestamp>message.timestamp){
                            NSInteger index = [self.messageArray indexOfObject:localMessage];
//                            NSLog(@"插入历史消息1------:%@",message.content);
//                            NSLog(@"index:%ld",(long)index);
                            
                            [self.messageArray insertObject:message atIndex:index];
                            NSIndexPath *newIndexPath = [NSIndexPath indexPathForRow:index inSection:0];
                            [indexPathArray addObject:newIndexPath];
                            break;
                        }
                    }
                }else{
//                    NSLog(@"插入历史消息2------:%@",message.content);
                    isHistoryRecord = NO;
                    [self.messageArray addObject:message];
                    NSIndexPath *newIndexPath = [NSIndexPath indexPathForRow:self.messageArray.count-1 inSection:0];
                    [indexPathArray addObject:newIndexPath];
                }
            }
            else{
//                NSLog(@"插入历史消息6------:%@",message.content);
            }
        }
    }
    
    if (indexPathArray.count == 0) {
        if(msgList.count>0){
            _canloadhistory = true;
        }
        else{
            _canloadhistory = false;
        }
        return;
    }
    
//    NSLog(@"----222444---:count ==%lu",(unsigned long)self.messageArray.count);
    
    if (isHistoryRecord) {
        // 执行插入操作（禁用动画）
        for (NSIndexPath * index in indexPathArray) {
            if (index.row>=self.messageArray.count) {
                return;
            }
        }
        [CATransaction begin];
        [CATransaction setDisableActions:YES];
        [self._tableView beginUpdates];
        [self._tableView insertRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationNone];
        [self._tableView endUpdates];
        
        [CATransaction commit];
        [self.preloader resetScrollState];
        if(msgList.count>0){
            _canloadhistory = true;
        }
        else{
            _canloadhistory = false;
        }
    }else{
        [CATransaction begin];
        [CATransaction setDisableActions:YES];
        
        [self._tableView beginUpdates];
        [self._tableView insertRowsAtIndexPaths:indexPathArray
                              withRowAnimation:UITableViewRowAnimationNone];
        [self._tableView endUpdates];
        [CATransaction commit];
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            //插入新消息时，判断是否在底部附近，在底部附近则滚动至底部，不在底部则不打断用户浏览
            CGFloat visibleHeight = self._tableView.bounds.size.height - self._tableView.contentInset.top - self._tableView.contentInset.bottom;
            CGFloat yOffset = self._tableView.contentOffset.y;
            CGFloat threshold = MAX(20, visibleHeight * 0.8); // 距离底部20点或20%可见高度
//            NSLog(@"threshold:%f,%f",threshold,self._tableView.contentSize.height - yOffset - visibleHeight);
            BOOL shouldScrollToBottom = (self._tableView.contentSize.height - yOffset - visibleHeight) <= threshold;
            if (shouldScrollToBottom) {
                [CATransaction begin];
                [CATransaction setDisableActions:YES];
                NSIndexPath *lastRowIndexPath = [NSIndexPath indexPathForRow:([self._tableView numberOfRowsInSection:0] - 1) inSection:0];
                [self._tableView scrollToRowAtIndexPath:lastRowIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO];
                [CATransaction commit];
            }
        });
        [self faSongYidu];
        if(msgList.count>0){
            _canloadhistory = true;
        }
        else{
            _canloadhistory = false;
        }
    }
    
    if(self.messageArray.count>20){
        _showLoading = false;
    }
    else{
        _showLoading = true;
    }

    if (_isInit) {
        _isInit = NO;
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [self movetoBotton];
        });
    }
}

-(void)movetoBotton{
//    NSLog(@"movetoBotton------movetoBotton");
    if (self.messageArray.count>0) {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSIndexPath *lastRowIndexPath = [NSIndexPath indexPathForRow:([self._tableView numberOfRowsInSection:0] - 1) inSection:0];
            //NSLog(@"lastRowIndexPath:%ld",(long)lastRowIndexPath.row);
            [self._tableView scrollToRowAtIndexPath:lastRowIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO];
        });
    }
}

#pragma mark  chatpopViewDelegate

-(void)actionNote:(NSString *)note{
    [self hidBottonView];
    if([note isEqualToString:@"1"]){//发送图片
        [self showImagePicker:1];
    }
    if([note isEqualToString:@"2"]){//发送视频
        [self showImagePicker:2];
    }
    if([note isEqualToString:@"3"]){//发送文件
        [self showfilePicker];
    }
    if([note isEqualToString:@"4"]){//语音
        [self showWebRtcVidio:4];
    }
    if([note isEqualToString:@"5"]){//视频
        [self showWebRtcVidio:5];
    }
    if([note isEqualToString:@"6"]){//拍摄
        [self takePhoto];
    }
}


#pragma mark preload
-(void)setupPreloader{
    //预加载管理器
    NSLog(@"setupPreloader");
    self.preloader = [[HistoryPreloader alloc] init];
    self.preloader.tableView = self._tableView;
    self.preloader.threshold = 700;
    weakSelf(self);
    self.preloader.loadBlock = ^{
        
        if (!weakself.canloadhistory) {
            return;
        }
        [weakself loadhistoryData];
    };

    self.preloader.toofast = ^{
        if (weakself.showLoading) {
        }else{
            weakself.showLoading = YES;
//            [MBProgressHUD showLoadingWithText:@"數據解密中。。。。"  inView:weakself.view hideAfterDelay:2];
        }
    };
    
}

-(void)loadhistoryData{
    if(self.messageArray.count>0){
        NSLog(@"loadhistoryData-------");
        _canloadhistory = false;
        if(self.type==0){
            ChatMessageModel *eldata = self.messageArray[0];
            NSInteger time =eldata.timestamp;
            [ChatsStore.shareInstance loadNextData:self.chatId timestp:time];
        }
        else if(self.type==1){
            ChatMessageModel *eldata = self.messageArray[0];
            NSInteger time =eldata.timestamp;
            [ChatsStore.shareInstance loadQunNextData:self.chatId timestp:time];
        }
    }
}

#pragma mark UITableViewDelegate,UITableViewDataSource
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return self.messageArray.count;
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    if(self.messageArray.count<indexPath.row){
        return nil;
    }
    
    static NSString *cellID = @"chatCellView";
    chatCellView *cell =[tableView dequeueReusableCellWithIdentifier:cellID];
    if(cell==nil){
        cell=[[chatCellView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
    }
    cell.parentViewController = self;
    cell.isHistory = false;
    ChatMessageModel *message = self.messageArray[indexPath.row];
//    NSLog(@"---:%ld,%@",(long)message.localtime,message.content);
    weakSelf(self);
    cell.bubbleCellLongPressMenuBlock = ^(NSInteger index) {
        switch (index) {
            case 0:
                NSLog(@"-------复制------");
                [weakself copyMessageContent:message.content];
                break;
            case 1:
                NSLog(@"------删除------");
                [weakself deleteMyMsg:message.formerMessage];
                break;
            case 2:
                NSLog(@"-----转发-------");
                [weakself forwardMsg:@[message.formerMessage] isMultiple:NO];
                
                break;
            case 3:
                NSLog(@"-----收藏-------");
                [weakself addFavorites:message.formerMessage];
                break;
            case 4:
                NSLog(@"------撤回------");
                [weakself messageCallback:message.formerMessage];
                break;
            case 5:
                NSLog(@"------多选------");
                [weakself batchProcess];
                break;
            case 6:
                NSLog(@"------引用------");
                [weakself quoteMessage:message];
                break;
            case 7:
                NSLog(@"------保存------");
                [weakself saveFile:message];
                break;
//            case 8:
//                NSLog(@"------文件视频图片重新上传------");
//                [weakself resendFile:message];
//                break;
            case 99:
//                NSLog(@"------长按开始------");
                [weakself dismissKeyboard];
                break;
                
            default:
                break;
        }
    };
    cell.batchSelectedStateBlock = ^(BOOL isSelected) {
        if (isSelected) {
            
            NSMutableDictionary *dic =message.formerMessage.mutableCopy;
            NSString *coontent = dic[@"content"]?:@"";
            coontent =[CryptoAES.shareInstance encryptStringL:coontent];
            [dic setObject:coontent forKey:@"content"];
            [weakself.forwordMsgArray addObject:dic];
        }else{
            [weakself.forwordMsgArray removeObject:message.formerMessage];
        }
        NSLog(@"weakself.forwordMsgArray:%@",weakself.forwordMsgArray);
    };
    cell.avatarTapBlock = ^(ChatMessageModel * _Nonnull message) {
//        if (message.isSender) {
//            return;
//        }
//        //前往用户信息页
//        UIStoryboard *board = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
//        FriendController *friendctr = [board instantiateViewControllerWithIdentifier:@"FriendController"];
//        friendctr.friendMsg = nil;
//        friendctr.friendId = message.fromId;
//        
//        UINavigationController *uiNavC = [[UINavigationController alloc] initWithRootViewController:friendctr];
//        uiNavC.modalPresentationStyle = UIModalPresentationFullScreen;
//        
//        [weakself presentViewController :uiNavC animated:YES completion:nil];
    };
    
    [cell setResendMessageBlock:^(ChatMessageModel *message) {
        if (message.isUploadFile) {
            [weakself resendFile:message];
        } else {
            [weakself resendMsg:message.formerMessage];
        }
    }];
    
    return cell;
}




- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    ChatMessageModel *message = self.messageArray[indexPath.row];
//    NSLog(@"heightForRowAtIndexPath-----");
    return [chatCellView cellHeightForMessage:message];
}

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
    chatCellView * currentCell = (chatCellView *)cell;
    ChatMessageModel *message = self.messageArray[indexPath.row];
    currentCell.messageModel = message;
//    NSLog(@"willDisplayCell-----");
    currentCell.batchState = self.isBatchMode;
}

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    if(_keybarShow){
        [self dismissKeyboard];
        return;
    }
}


-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
    // 计算距离顶部的距离
//    CGFloat offsetY = scrollView.contentOffset.y;
//    CGFloat contentHeight = scrollView.contentSize.height;
//    CGFloat frameHeight = scrollView.frame.size.height;
////    NSLog(@"scrollViewDidScroll:offsetY:%f,contentHeight:%f,frameHeight:%f",offsetY,contentHeight,frameHeight);
//    // 预加载阈值（距离顶部300pt时触发）
//    CGFloat threshold = 300.0;
////    NSLog(@"scrollViewDidScroll:%f",offsetY);
//    if (offsetY > threshold&&!_canloadhistory) {
//        _canloadhistory=true;
//        _offset =offsetY;
//        return;
//    }
//    if(_offset-offsetY>400){
//        _canloadhistoryMore=false;
//    }
//    
//    if(_canloadhistory&&offsetY < threshold){
////        NSLog(@"-----1------1");
//        if(!_canloadhistoryMore){
////            NSLog(@"-----1------2");
//            _ishistory=true;
//            [self loadhistoryData];
//        }
//    }
    
    
}


-(void)saveFile:(ChatMessageModel *)msgMdl{
    
    NSString *localPath =msgMdl.localurl;
    if (localPath && [[NSFileManager defaultManager] fileExistsAtPath:localPath]) {
        NSLog(@"本地路径");
        NSString *fileExtension = [[msgMdl.localurl pathExtension] lowercaseString];
        if([self isVideoFile:fileExtension]){
            NSURL *fileURL = [NSURL fileURLWithPath:localPath];
            [self saveVideoToPhotoLibrary:fileURL];
        }
        else{
            [self saveFileToLibrary:localPath];
        }
    }
    else{
        [MBProgressHUD showWithText:@"文件尚未加载完成，请稍后重试"];
    }
    
    
}

- (BOOL)isVideoFile:(NSString *)fileExtension {
    NSArray *videoExtensions = @[@"mp4", @"mov", @"m4v", @"avi", @"mkv", @"flv", @"wmv"];
    return [videoExtensions containsObject:fileExtension];
}


- (void)saveVideoToPhotoLibrary:(NSURL *)videoURL {
    // 检查 PHPhotoLibrary 的授权状态
    [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
        if (status == PHAuthorizationStatusAuthorized) {
            // 授权成功，保存视频
            [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
                // 创建资产更改请求
                PHAssetChangeRequest *assetChangeRequest = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:videoURL];
                // 可以设置其他属性，如位置信息等
                // [assetChangeRequest setLocation:location];
            } completionHandler:^(BOOL success, NSError *error) {
                if (success) {
                    NSLog(@"视频保存成功");
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [self showNot:@"保存到手机成功"];
                    });
                    
                } else {
                    NSLog(@"视频保存失败: %@", error.localizedDescription);
                }
            }];
        } else {
            // 授权失败或未授权，处理用户未授权的情况
            NSLog(@"请在设置中授权访问相册");
        }
    }];
}

-(void)showNot:(NSString *)str{
    [MBProgressHUD showWithText:str];
}


-(void)saveFileToLibrary:(NSString *)fileUrl{
    NSURL *fileURL = [NSURL fileURLWithPath:fileUrl];

    UIDocumentInteractionController *documentController = [UIDocumentInteractionController interactionControllerWithURL:fileURL];
    [documentController presentOptionsMenuFromRect:CGRectZero inView:self.view animated:YES];
}




#pragma mark UITextViewDelegate
- (void)textViewDidChange:(UITextView *)textView {
    
    CGFloat maxHeight = 160;
    CGFloat maxWidth = self.view.frame.size.width - 190;
    CGSize newSize = [textView sizeThatFits:CGSizeMake(maxWidth, MAXFLOAT)];
    if(newSize.height>maxHeight){
        _inputView.scrollEnabled = YES; // 允许滚动，出现滚动条
    }
    else{
        _inputView.scrollEnabled = NO; // 禁止滚动，使内容自适应高度
        [self movetoBotton];
    }
    CGFloat height = MAX(40, MIN(maxHeight, newSize.height));
    self.bottomViewHeight.constant = height+20;
}


- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    // 计算新文本的长度
    NSInteger newLength = textView.text.length - range.length + text.length;
    NSLog(@"shouldChangeTextInRange---");
    // 若新文本长度超出最大长度，则不允许输入
    if (newLength > 1000) {
        [MBProgressHUD showWithText:@"超出最大文本长度，请重新输入"];
        if (textView.text.length == 0) {
            return NO;
        }
        // 截取最大长度的文本
        NSString *substring = [textView.text substringToIndex:1000];
        textView.text = substring;
        return NO;
    }
    
    if ([text isEqualToString:@"@"] && self.type == 1) {
        NSLog(@"用户输入了@符号");
        // 可以在这里添加你需要执行的代码
        [textView resignFirstResponder];
        [self showAtMemberView];
    }
    
    if ([text isEqualToString:@""] && self.type == 1) { // 删除操作
        // 处理连续删除特殊字符的情况
        if (range.length == 1) {
            NSRange deleteRange = range;
            NSString *deletedChar = [textView.text substringWithRange:deleteRange];
            
            // 如果删除的是连字符，尝试删除整个mention
            if ([deletedChar isEqualToString:@"-"]) {
                if ([self.inputView deleteMentionAtCursorPosition]) {
                    return NO;
                }
            }
        }
        NSLog(@"1111111");
        // 正常删除处理
        if ([self.inputView deleteMentionAtCursorPosition]) {
            NSLog(@"deleteMentionAtCursorPosition");
            return NO;
        }
    }
    
    return YES;
}

- (void)keyboardWillShow:(NSNotification *)notification {
    // 获取键盘的动画持续时间和动画曲线
    NSDictionary *userInfo = [notification userInfo];
    double duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
//    UIViewAnimationCurve curve = [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
//    
    // 获取键盘的高度
    CGRect keyboardEndFrame = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    _keyboardHeight = keyboardEndFrame.size.height;
    NSLog(@"_keyboardHeight:%f",_keyboardHeight);
    // 根据需要调整视图大小或位置（例如，移动某个视图）
    // 示例：将一个视图向下移动以适应键盘高度

    CGFloat safeBottom = [UIDevice safeDistanceBottom];
    CGFloat offsetY = _keyboardHeight - safeBottom;
    
    _gengduoBt.alpha = 1;
    _fasngBt.alpha = 1;
    _keybarShow=true;
    [UIView animateWithDuration:duration
                          delay:0
                        options:UIViewAnimationOptionCurveEaseInOut
                     animations:^{
        self.inputViewBottom.constant = offsetY;
        [self.view setNeedsLayout];
        [self.view layoutIfNeeded];
    } completion:^(BOOL finished) {
        [self movetoBotton];
    }];
    
}
 
- (void)keyboardWillHide:(NSNotification *)notification {
    // 获取键盘的动画持续时间和动画曲线
    NSDictionary *userInfo = [notification userInfo];
    double duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    UIViewAnimationCurve curve = [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
    
    NSLog(@"_keyboardHeight:%f",_keyboardHeight);
    [UIView animateWithDuration:duration
                         delay:0.0
                       options:(curve << 16)
                    animations:^{
        self.inputViewBottom.constant = 0;
        [self.view setNeedsLayout];
        [self.view layoutIfNeeded];
    } completion:^(BOOL finished) {
        [self movetoBotton];
    }];
    if(_inputView.text.length>0){
        _gengduoBt.alpha = 1;
        _fasngBt.alpha = 1;
    }
    else{
        _gengduoBt.alpha = 1;
        _fasngBt.alpha = 1;
    }
    _keybarShow=false;
}



-(void)dismissKeyboard{
    [self.view endEditing:YES];
}

-(void)fasongwanwenzi{
    CGRect newFrame = _inputView.frame;
    newFrame.size.height =40;
    _inputView.scrollEnabled = NO; // 禁止滚动，使内容自适应高度
    _inputView.frame =newFrame;
    CGRect viewFrame = _bottonView.frame;
    viewFrame.size.height = 62;
    
    if (self.isQuoteMessage) {
        self.quoteView.hidden = YES;
        CGRect audioBtnFrame = self.yuyinctr.frame;
        self.yuyinctr.frame = CGRectMake(audioBtnFrame.origin.x, audioBtnFrame.origin.y+kQuoteViewHeight, audioBtnFrame.size.height, audioBtnFrame.size.height);
        CGRect moreFunctionBtnFrame = self.gengduoBt.frame;
        self.gengduoBt.frame = CGRectMake(moreFunctionBtnFrame.origin.x, moreFunctionBtnFrame.origin.y+kQuoteViewHeight, moreFunctionBtnFrame.size.width, moreFunctionBtnFrame.size.height);
        CGRect sendBtnFrame = self.fasngBt.frame;
        self.fasngBt.frame = CGRectMake(sendBtnFrame.origin.x, sendBtnFrame.origin.y+kQuoteViewHeight, sendBtnFrame.size.width, sendBtnFrame.size.height);
    }
    
    if(_keybarShow){
        viewFrame.origin.y =self.view.frame.size.height-_keyboardHeight-viewFrame.size.height;
        CGRect tframe = self._tableView.frame;
        tframe.size.height = viewFrame.origin.y-tframe.origin.y;
        self._tableView.frame = tframe;
        [self movetoBotton];
    }
    else{
        // 恢复视图原始位置或大小
        viewFrame.origin.y = self.view.frame.size.height-viewFrame.size.height-34;
        CGRect tframe = self._tableView.frame;
        tframe.size.height = viewFrame.origin.y-tframe.origin.y;
        self._tableView.frame = tframe;
        [self movetoBotton];
    }
    _bottonView.frame = viewFrame;
}

#pragma mark 发送数据
-(void)sendtextData{
    NSLog(@"sendtextData1");
    NSString *msg = _inputView.text;
    msg = [msg stringByReplacingOccurrencesOfString:@"\r" withString:@""];
    msg = [msg stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    msg = [msg stringByReplacingOccurrencesOfString:@"\t" withString:@""];
    msg = [msg stringByReplacingOccurrencesOfString:@" "  withString:@""];
    if (msg.length==0) {
        NSLog(@"空内容");
        return;
    }
    [self fasongwanwenzi];
    NSLog(@"sendtextData2");
    NSDictionary * quoteMessage;
    if (self.isQuoteMessage) {
//        NSInteger quoteIndex = [self.messageArray indexOfObject:self.quoteView.model];
//        NSLog(@"quoteIndex:%ld------------",quoteIndex);
        
        quoteMessage = self.quoteView.model.formerMessage;
    }
    
    NSString *content= [CryptoAES.shareInstance encryptStringL:_inputView.text];
//    NSLog(@"content:%@",content);
    NSString *strtime = [self getLocalTime];
    NSString *type = [NSString stringWithFormat:@"%ld",(long)self.type];
    NSDictionary *Lmsgd=@{
        @"messageType":@"0",
        @"chatId":self.chatId,
        @"fromId":self.userId,
        @"fromName":self.username,
        @"fromAvatar":self.useravatar,
        @"content":content,
        @"type":type,
        @"reSend":[NSNumber numberWithBool:false],
        @"extend": @{
            @"atAll":@"false",
            @"atUserIds":@[],
        },
        @"localtime":strtime,
        @"timestamp":strtime,
        @"mine":@"true",
        @"id":strtime,
    };
    
    NSMutableDictionary * tempMsgDict = [NSMutableDictionary dictionaryWithDictionary:Lmsgd];
    NSMutableDictionary * tempExtandDict = [NSMutableDictionary dictionaryWithDictionary:Lmsgd[@"extend"]];
    if (quoteMessage) {
        [tempExtandDict setObject:quoteMessage forKey:@"quoteMessage"];
        [tempMsgDict setObject:tempExtandDict forKey:@"extend"];
    }
    
    if (self.atSomeoneArray.count!=0 && self.type == 1) {
        //@单人或者多人参数插入
        NSMutableArray * atUserIdsArray = [NSMutableArray array];
        for (NSDictionary * user in self.atSomeoneArray) {
            [atUserIdsArray addObject:user[@"id"]];
        }
        [tempExtandDict setObject:atUserIdsArray forKey:@"atUserIds"];
        [tempMsgDict setObject:tempExtandDict forKey:@"extend"];
    }
    
    if ([self.inputView.text containsString:@"@所有人"] && self.type == 1 && [self.groupInfo[@"master"] isEqualToString:self.userId]) {
        [tempExtandDict setObject:@"true" forKey:@"atAll"];
        [tempMsgDict setObject:tempExtandDict forKey:@"extend"];
    }
    
    NSString * tempChatId = self.chatId.mutableCopy;
    [ChatsStore shareInstance].chatId = tempChatId;
    [ChatsStore shareInstance].delegate = self;
    [ChatsStore.shareInstance reciveMsg:tempMsgDict];//预先展示聊天窗信息
//    NSLog(@"sendtextData3");
    NSDictionary *Smsgd=@{
        @"messageType":@"0",
        @"chatId":self.chatId,
        @"fromId":self.userId,
        @"fromName":self.username,
        @"fromAvatar":self.useravatar,
        @"content":content,
        @"type":type,
        @"reSend":[NSNumber numberWithBool:false],
        @"extend": @{
            @"atAll":@"false",
            @"atUserIds":@[],
        },
        @"localtime":strtime,
        @"timestamp":strtime,
    };
    
    NSMutableDictionary * tempSendMsgDict = [NSMutableDictionary dictionaryWithDictionary:Smsgd];
    NSMutableDictionary * tempSendExtandDict = [NSMutableDictionary dictionaryWithDictionary:Smsgd[@"extend"]];
    if (quoteMessage) {
        [tempSendExtandDict setObject:quoteMessage forKey:@"quoteMessage"];
        [tempSendMsgDict setObject:tempSendExtandDict forKey:@"extend"];
    }
    
    if (self.atSomeoneArray.count!=0 && self.type == 1) {
        //@单人或者多人参数插入
        NSMutableArray * atUserIdsArray = [NSMutableArray array];
        for (NSDictionary * user in self.atSomeoneArray) {
            [atUserIdsArray addObject:user[@"id"]];
        }
        [tempSendExtandDict setObject:atUserIdsArray forKey:@"atUserIds"];
        [tempSendMsgDict setObject:tempSendExtandDict forKey:@"extend"];
    }
    
    if ([self.inputView.text containsString:@"@所有人"] && self.type == 1 && [self.groupInfo[@"master"] isEqualToString:self.userId]) {
        [tempSendExtandDict setObject:@"true" forKey:@"atAll"];
        [tempSendMsgDict setObject:tempSendExtandDict forKey:@"extend"];
    }
    
    NSDictionary *sendInfo = @{
        @"code":@"2",
        @"message":tempSendMsgDict,
    };
    
    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); // 输出: {"name":"John","age":25}
//        NSLog(@"----发送文字----");
        [GWebSocket.shareInstance sendMsg:jsonString];
        if (self.isQuoteMessage) {
            self.isQuoteMessage = NO;
        }
        _inputView.text=@"";
        [self textViewDidChange:_inputView];
    }
    if(_keybarShow){
        _gengduoBt.alpha = 1;
        _fasngBt.alpha = 1;
    }
    else{
        _gengduoBt.alpha = 1;
        _fasngBt.alpha = 1;
    }
}

-(void)faSongYidu{
    
    if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
        // 应用已经解锁并且在前台
        NSLog(@"应用已经解锁并且在前台viewWillDisappear-----1111");
    }
    else{
        return;
    }
    NSString *strtime = [self getLocalTime];
    NSString *type = [NSString stringWithFormat:@"%ld",(long)self.type];
    NSDictionary *dic =@{
        @"chatId":self.chatId,
        @"userId":self.userId,
        @"type":type,
        @"timestamp":strtime,
    };
    NSDictionary *sendInfo = @{
        @"code":SendCode_READ,
        @"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); // 输出: {"name":"John","age":25}
//        NSLog(@"1--------发送已读时间--------2");
        [GWebSocket.shareInstance sendMsg:jsonString];
    }
}

#pragma mark 弹框
-(void)showBottonView{
    [self dismissKeyboard];
    _markView.frame = self.view.frame;
    CGRect popfram = CGRectMake(0,self.view.frame.size.height-250, self.view.frame.size.width, 250);
    _popView.frame = popfram;
}

-(void)hidBottonView{
    CGRect popfram = CGRectMake(0,self.view.frame.size.height, self.view.frame.size.width, 250);
    _popView.frame = popfram;
    _markView.frame=popfram;
    _markView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5];
    [self movetoBotton];
}

-(void)dismissBotton{
    [self hidBottonView];
}

//重发消息
-(void)resendMsg:(NSDictionary *)msg{
    
    NSMutableDictionary *dic = [msg mutableCopy];
    NSString *resend =dic[@"reSend"];
    NSLog(@"resend:%@",[resend class]);
    if (resend.boolValue) {
        return;
    }
    else{
        NSString * str = msg[@"messageType"];
        if (![str isEqualToString:@"0"]) {
            return;
        }
        [dic setObject:[NSNumber numberWithBool:YES] forKey:@"reSend"];
        NSDictionary * dict = dic.copy;
        [ChatsStore.shareInstance reciveMsg:dict];//预先展示聊天窗信息
        [dic setObject:[NSNull null] forKey:@"id"];
    }
    NSDictionary *sendInfo = @{
        @"code":@"2",
        @"message":dic,
    };
    
    NSError *error;
//    NSLog(@"resendMsg---------:%@",msg[@"localtime"]);
    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];
        [GWebSocket.shareInstance sendMsg:jsonString];
    }
}

#pragma mark 上传图片

-(void)showImagePicker:(NSInteger)state{
    NSLog(@"showImagePicker");
    PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
    if (status == PHAuthorizationStatusAuthorized) {
        // 已经授权，可以访问相册
    } else {
        // 未授权，请求授权
        [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
            if (status == PHAuthorizationStatusAuthorized) {
                // 用户授权了访问相册
                // 在这里执行相册相关的操作
            } else {
                // 用户拒绝授权
                // 可以提供一些用户指导或提示信息
                return;
            }
        }];
    }
    
    PHPickerConfiguration *config = [[PHPickerConfiguration alloc] init];
    if(state==1){
        config.filter = [PHPickerFilter imagesFilter]; // 可以设置过滤器，例如只选择图片或视频等
    }
    else if(state==2){
        config.filter = [PHPickerFilter videosFilter]; // 可以设置过滤器，例如只选择图片或视频等
    }
    config.selectionLimit = 9; // 限制选择数量，设置为1表示只能选择一张图片
    config.preferredAssetRepresentationMode = PHPickerConfigurationAssetRepresentationModeCurrent;
    PHPickerViewController *imagePicker = [[PHPickerViewController alloc] initWithConfiguration:config];
    imagePicker.delegate = self; // 设置代理以接收选择结果
    [self presentViewController:imagePicker animated:YES completion:nil];

}


- (void)picker:(PHPickerViewController *)picker didFinishPicking:(NSArray<PHPickerResult *> *)results {
    [picker dismissViewControllerAnimated:YES completion:nil]; // 关闭选择器视图控制器
    if (results.count == 0) {
        return;
    }
    NSMutableArray * fileArray = [NSMutableArray array];
    for (PHPickerResult * result in results) {
        NSItemProvider *itemProvider = result.itemProvider;
        NSString *typeIdentifier = result.itemProvider.registeredTypeIdentifiers.firstObject;
        if ([result.itemProvider canLoadObjectOfClass:[UIImage class]]) {
            
            [result.itemProvider loadFileRepresentationForTypeIdentifier:typeIdentifier completionHandler:^(NSURL * _Nullable url, NSError * _Nullable error) {
                if (error) {
                    NSLog(@"Error loading file: %@", error);
                    return;
                }
                NSLog(@"File URL: %@", url); // 这里就是文件的 URL 路径
                // 你可以使用这个 URL 进行进一步处理，例如读取文件内容或者将其复制到应用沙盒中的其他位置。
                NSString *savedPath = [self saveFileToDocumentsDirectory:url];
                if(savedPath.length>0){
                    NSURL * fileUrl = [NSURL fileURLWithPath:savedPath];
                    ChatFileModel * model = [[ChatFileModel alloc] initWithURL:fileUrl];
                    model.fileURL = fileUrl;
                    model.filePath = savedPath;
                    [fileArray addObject:model];
                    if (fileArray.count==results.count) {
                        dispatch_async(dispatch_get_main_queue(), ^{
                            [self handleMediaData:fileArray];
                        });
                    }
                }
                else{
                    NSLog(@"-----找不到文件------");
                }
            }];

        }else{
            [result.itemProvider loadFileRepresentationForTypeIdentifier:typeIdentifier completionHandler:^(NSURL * _Nullable url, NSError * _Nullable error) {
                if (error) {
                    NSLog(@"Error loading file: %@", error);
                    return;
                }
                NSLog(@"File URL: %@", url); // 这里就是文件的 URL 路径
                // 你可以使用这个 URL 进行进一步处理，例如读取文件内容或者将其复制到应用沙盒中的其他位置。
                NSString *savedPath = [self saveFileToDocumentsDirectory:url];
                if(savedPath.length>0){
                    NSURL * fileUrl = [NSURL fileURLWithPath:savedPath];
                    ChatFileModel * model = [[ChatFileModel alloc] initWithURL:fileUrl];
                    model.fileURL = fileUrl;
                    model.filePath = savedPath;
                    [fileArray addObject:model];
                    if (fileArray.count==results.count) {
                        dispatch_async(dispatch_get_main_queue(), ^{
                            [self handleMediaData:fileArray];
                        });
                    }
                }
                else{
                    NSLog(@"-----找不到文件------");
                }
            }];
        }
    }
}


#pragma mark - 写入方法
- (NSString *)saveImageToSandbox:(UIImage *)image {
    // 获取沙盒Documents目录
    NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
    
    // 生成唯一文件名
    NSString *fileName = [NSString stringWithFormat:@"%@.jpg", [[NSUUID UUID] UUIDString]];
    NSString *filePath = [documentsPath stringByAppendingPathComponent:fileName];
    
    // 将图片转换为JPEG格式数据
    NSData *imageData = UIImageJPEGRepresentation(image, 0.8);
    
    // 写入文件
    BOOL success = [imageData writeToFile:filePath atomically:YES];
    
    if (success) {
        NSLog(@"图片保存成功，路径: %@", filePath);
        return filePath;
    } else {
        NSLog(@"图片保存失败");
        return nil;
    }
}
- (NSString *)saveVideoDataToDocumentsDirectory:(NSData *)videoData {
    // 1. 生成唯一文件名
    NSString *fileName = [NSString stringWithFormat:@"%@.mp4", [[NSUUID UUID] UUIDString]];
    
    // 2. 获取Documents目录路径
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths firstObject];
    NSString *filePath = [documentsDirectory stringByAppendingPathComponent:fileName];
    
    // 3. 写入数据
    NSError *writeError;
    [videoData writeToFile:filePath options:NSDataWritingAtomic error:&writeError];
    
    if (writeError) {
        NSLog(@"Error writing video data: %@", writeError.localizedDescription);
        return nil;
    }
    
    return filePath;
}

- (NSString *)saveFileToDocumentsDirectory:(NSURL *)fromePath {
    NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
    NSString *destinationPath = [documentsDirectory stringByAppendingPathComponent:fromePath.lastPathComponent]; // 目标文件路径
    
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError *error = nil;
    
    if([[NSFileManager defaultManager] fileExistsAtPath:destinationPath]){
        return destinationPath;
    }
    else{
        BOOL success = [fileManager copyItemAtPath:fromePath.path toPath:destinationPath error:&error];
        if (success) {
            NSLog(@"文件成功复制到本地");
            return destinationPath;
        } else {
            NSLog(@"文件复制失败: %@", error.localizedDescription);
            return @"";
        }
    }
}



#pragma mark -文件选择和处理
-(void)showfilePicker{
    // 创建文档选择器
    NSArray<UTType *> *contentTypes = @[UTTypeItem];
    UIDocumentPickerViewController *documentPicker =  [[UIDocumentPickerViewController alloc] initForOpeningContentTypes:contentTypes
        asCopy:YES];
    documentPicker.allowsMultipleSelection = YES;
    documentPicker.delegate = self;
    [self presentViewController:documentPicker animated:YES completion:nil];
}

#pragma mark - 文件选择回调 UIDocumentPickerDelegate
- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls {
    // 用户选择了一个或多个文件，处理这些文件
    
    if (urls.count > 9) {
        //选择文件最多 9 个
        [MBProgressHUD showWithText:@"一次最多上傳 9 個檔案"];
        
    }
    
    NSMutableArray * fileArray = [NSMutableArray array];
    for (NSURL * url in urls) {
        
        if ([urls indexOfObject:url] > 9) {
            break;
        }
        NSLog(@"url:%@",url);
        
        NSString *savedPath = [self saveFileToDocumentsDirectory:url];
        if(savedPath.length>0){
            NSURL * fileUrl = [NSURL fileURLWithPath:savedPath];
            ChatFileModel * model = [[ChatFileModel alloc] initWithURL:fileUrl];
            model.fileURL = fileUrl;
            model.filePath = savedPath;
            [fileArray addObject:model];
        }
    }
    dispatch_async(dispatch_get_main_queue(), ^{
        [self handleMediaData:fileArray];
    });
   
}


#pragma mark 批量处理文件上传
- (void)handleMediaData:(NSArray *)mediaArray{
    
//    NSMutableArray * tempArray = [NSMutableArray array];
        NSArray *sorArray = [self fileArraysort:mediaArray];
        
        for (ChatFileModel * model in sorArray) {
            NSString *strtime = [self getLocalTime];
            [self uploadFile:[NSString stringWithFormat:@"%@",model.fileURL] fpath:model.filePath state:1 act:1 localtime:strtime];
            [self OSSuploadFile:model thrid:strtime];
        }
}




-(void)OSSuploadFile:(ChatFileModel *)model thrid:(NSString *)strtime{

   
    NSString * tempChatId = self.chatId.mutableCopy;
    [ChatsStore shareInstance].chatId = tempChatId;
    [ChatsStore shareInstance].delegate = self;
    
//    断点续传
    [OSSManager.sharedManager asyncResumableUploadFile:model.fileURL.lastPathComponent localFilePath:model.filePath thrid:strtime];

}

-(void)stateChange:(NSDictionary *)changeMsg{
    dispatch_main_async_safe(^{
        NSString *loacaltime = changeMsg[@"thrid"];
        NSString *pcent = changeMsg[@"pcent"];
        NSString *state = changeMsg[@"state"];
        NSLog(@"uploadProgress: %@",pcent);
        if([state isEqualToString:@"1"]){
            [self Ossupdatajidu:loacaltime uploadProgress:pcent.intValue];
        }
    })
}

-(void)resendFile:(ChatMessageModel *)msg{
    
    NSString *strtime = [NSString stringWithFormat:@"%ld",(long)msg.localtime];
    NSString *loaclFile = [NSString stringWithFormat:@"%@",msg.localurl];
    
    if(![[NSFileManager defaultManager] fileExistsAtPath:loaclFile]){
        [MBProgressHUD showWithText:@"文件不存在，請重新選擇"];
        return;
    }
    
   
    NSURL * fileUrl = [NSURL fileURLWithPath:loaclFile];
    ChatFileModel * model = [[ChatFileModel alloc] initWithURL:fileUrl];
    model.fileURL = fileUrl;
    model.filePath = loaclFile;
    
    [self OSSuploadFile:model thrid:strtime];
    
}


-(void)uploadFile:(NSString *)url fpath:(NSString *)path state:(NSInteger)state act:(NSInteger)act localtime:(NSString *)localtime{
    
    NSURL *filePath;
    if([url containsString:@"http"]){
        filePath=[NSURL URLWithString:url]; //
    }
    else{
        NSString *filestr = [[OSSManager sharedManager] fullUploadURLByAppendPath:url];
        filePath=[NSURL URLWithString:filestr]; //
    }
    
    NSString *content=@"【文件】";
    NSString *messageType=MessageType_file;
    NSDictionary *extend;
    if(state==1){//文件类消息
        NSString *kzm = filePath.pathExtension;
        kzm=[kzm lowercaseString];
        if([kzm isEqualToString:@"png"]||[kzm isEqualToString:@"jpg"]||[kzm isEqualToString:@"jpeg"]||[kzm isEqualToString:@"bmp"]){
            content=@"【图片】";
            messageType=MessageType_image;
        }
        if([kzm isEqualToString:@"mp4"]||[kzm isEqualToString:@"avi"]||[kzm isEqualToString:@"wmv"]||[kzm isEqualToString:@"mov"]||[kzm isEqualToString:@"mpeg"]){
            content=@"【视频】";
            messageType=MessageType_video;
        }
    }
    
    content= [CryptoAES.shareInstance encryptStringL:content];
    NSString *type = [NSString stringWithFormat:@"%ld",(long)self.type];
    
    NSDictionary *msgt;
    NSDictionary *msgd;
    if(act==1){
        extend=@{
            @"url":@"",
            @"fileName":filePath.lastPathComponent,
            @"localurl":path,
            @"fileError":[NSNumber numberWithInt:0]
        };
        msgt=@{
            @"messageType":messageType,
            @"chatId":self.chatId,
            @"fromId":self.userId,
            @"fromName":self.username,
            @"fromAvatar":self.useravatar,
            @"content":content,
            @"type":type,
            @"reSend": [NSNumber numberWithBool:false],
            @"extend": extend,
            @"localtime":localtime,
            @"timestamp":localtime,
            @"mine":[NSNumber numberWithBool:YES],
            @"id":localtime,
        };
        msgd=@{
            @"messageType":messageType,
            @"chatId":self.chatId,
            @"fromId":self.userId,
            @"fromName":self.username,
            @"fromAvatar":self.useravatar,
            @"content":content,
            @"type":type,
            @"reSend": [NSNumber numberWithBool:false],
            @"extend": extend,
            @"localtime":localtime,
            @"timestamp":localtime,
            @"mine":[NSNumber numberWithBool:YES],
            @"id":@"",
        };
        NSString * tempChatId = self.chatId.mutableCopy;
        [ChatsStore shareInstance].chatId = tempChatId;
        [ChatsStore shareInstance].delegate = self;
        [ChatsStore.shareInstance reciveMsg:msgt];
        NSDictionary *sendInfo = @{
            @"code":@"2",
            @"message":msgd,
        };
        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);
            NSLog(@"----发送文件消息----%@",localtime);
            //self.ismyTurn = YES;
            //[GWebSocket.shareInstance sendMsg:jsonString];
        }
        [self movetoBotton];
    }
    if(act==2){
        if(url){
            [self uploadFileSucc:url localtime:localtime];
        }
        else{
            
        }
    }
}


-(void)uploadFileSucc:(NSString *)url localtime:(NSString *)localtime{
    
    if(![url containsString:@"http"]){
        url = [[OSSManager sharedManager] fullUploadURLByAppendPath:url];
    }
    NSURL *filePath = [NSURL URLWithString:url];
    
    [GDBManager.shareInstance selectLocalmsgWithLocaltime:localtime succ:^(NSArray * _Nullable array) {
//        NSLog(@"selectLocalmsgWithLocaltime:%@",array);
        if(array){
            if(array.count>0){
                NSDictionary *msg =array[0];
                NSDictionary *extend=msg[@"extend"];
                NSMutableDictionary *mextend = [extend mutableCopy];
                [mextend setObject:url forKey:@"url"];
                [mextend setObject:filePath.lastPathComponent forKey:@"fileName"];
                NSMutableDictionary *mmsg = [msg mutableCopy];
                [mmsg setObject:mextend forKey:@"extend"];
                [mmsg setObject:@"" forKey:@"id"];
                NSDictionary *sendInfo = @{
                    @"code":@"2",
                    @"message":mmsg,
                };
                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);
                    NSLog(@"----发送文件消息2----%@",localtime);
//                    self.ismyTurn = YES;
                    [GWebSocket.shareInstance sendMsg:jsonString];
                }
            }
        }
    } fail:^(NSString * _Nullable error) {
        ;
    }];
    
}

-(void)uploadFilefail:(NSString *)localtime{
    NSLog(@"uploadFilefail----:%@",localtime);
    [GDBManager.shareInstance selectLocalmsgWithLocaltime:localtime succ:^(NSArray * _Nullable array) {
        NSLog(@"selectLocalmsgWithLocaltime:%@",array);
        
        if(array){
            if(array.count>0){
                NSDictionary *msg =array[0];
                NSString *msgtype = msg[@"messageType"];
                
                if (([msgtype isEqualToString:MessageType_Del]||[msgtype isEqualToString:MessageType_CallBack2])) {
                    return;
                }
                NSString *strtime = [self getLocalTime];
                NSDictionary *extend=msg[@"extend"];
                NSMutableDictionary *mextend = [extend mutableCopy];
                [mextend setObject:@"" forKey:@"url"];
                [mextend setObject:@"" forKey:@"fileName"];
                [mextend setObject:[NSNumber numberWithInt:1] forKey:@"fileError"];
                NSMutableDictionary *mmsg = [msg mutableCopy];
                [mmsg setObject:mextend forKey:@"extend"];
                [mmsg setObject:strtime forKey:@"timestamp"];
                [ChatsStore.shareInstance reciveMsg:mmsg];
                NSDictionary *sendInfo = @{
                    @"code":@"2",
                    @"message":mmsg,
                };
                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);
                    NSLog(@"----发送文件失败消息2----%@",localtime);
//                    self.ismyTurn = YES;
                    //[GWebSocket.shareInstance sendMsg:jsonString];
                }
            }
        }
    } fail:^(NSString * _Nullable error) {
        ;
    }];
    
}

-(void)Ossupdatajidu:(NSString *)localtime uploadProgress:(NSInteger )Progress{
    [self updateProgress:Progress localtime:localtime];
}

- (void)updateProgress:(NSInteger )Progress localtime:(NSString *)localtime {
    for (chatCellView *cell in self._tableView.visibleCells) {
        ChatMessageModel *message = cell.messageModel;
        if(message.localtime==localtime.integerValue){
            [cell fileUploadProgressDidChanged:Progress localtime:localtime.integerValue];
        }
    }
}

#pragma mark 录音发送

-(void)longTarget{
    NSLog(@"longTarget----------");
    _AVRecordBt.layer.backgroundColor = globalColor(GCTypeGreen).CGColor;
    [_AVRecordBt setTitle:@" 松开 发送" forState:UIControlStateNormal];
    
    NSDate *now = [NSDate date];
    NSTimeInterval trt = [now timeIntervalSince1970];
    NSInteger time = trt*1000;
    _AudiofileName = [NSString stringWithFormat:@"%ld.mp4",(long)time];
    
    _AudiofilePath = [NSTemporaryDirectory() stringByAppendingPathComponent:_AudiofileName];
    
    NSError *error = nil;
    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
    //[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
    [audioSession setActive:YES error:nil];
    NSMutableDictionary *recordSetting = [[NSMutableDictionary alloc] init];
    [recordSetting setValue:[NSNumber numberWithInt:kAudioFormatMPEG4AAC] forKey:AVFormatIDKey];
    [recordSetting setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey]; //采样率
    [recordSetting setValue:[NSNumber numberWithInt: 2] forKey:AVNumberOfChannelsKey];
    [recordSetting setValue:[NSNumber numberWithInt: AVAudioQualityMedium] forKey:AVEncoderAudioQualityKey];
     
    NSURL *fileURL = [NSURL fileURLWithPath:_AudiofilePath];
    
    _recorder = [[AVAudioRecorder alloc] initWithURL:fileURL settings:recordSetting error:&error];
    if (error) {
        NSLog(@"Error creating recorder: %@", error);
    } else {
        [_recorder prepareToRecord];
        [_recorder record];
    }
    _rcdL=0;
    self.heatBeat = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(heartbeatAction) userInfo:nil repeats:YES];
    [self.heatBeat setFireDate:[NSDate distantPast]];
    [[NSRunLoop currentRunLoop] addTimer:_heatBeat forMode:NSRunLoopCommonModes];
}
-(void)heartbeatAction{
    if(_rcdL==60){
        [_recorder stop];
        _recorder=nil;
        return;
    }
    _rcdL=_rcdL+1;
}

-(void)UpInside{
    _AVRecordBt.layer.backgroundColor = globalColor(GCTypeDark2).CGColor;
    [_AVRecordBt setTitle:@" 按住 说话" forState:UIControlStateNormal];
    NSLog(@"UpInside----------");
    [_recorder stop];
    _recorder=nil;
    NSURL *yuanfileURL = [NSURL fileURLWithPath:_AudiofilePath];
    if(_rcdL<2){//语音太短
        [[NSFileManager defaultManager] removeItemAtURL:yuanfileURL error:nil];
        [self.heatBeat invalidate];
        self.heatBeat = nil;
        [MBProgressHUD showWithText:@"語音太短"];
        return;
    }
    NSLog(@"_AudiofilePath:%@",_AudiofilePath);
    
    NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
    NSString *destinationPath = [documentsDirectory stringByAppendingPathComponent:yuanfileURL.lastPathComponent]; // 目标文件路径
    
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError *error = nil;
    BOOL success = [fileManager copyItemAtPath:_AudiofilePath toPath:destinationPath error:&error];
    if (success) {
        [[NSFileManager defaultManager] removeItemAtURL:yuanfileURL error:nil];
        NSLog(@"文件成功复制到本地");
    } else {
        [[NSFileManager defaultManager] removeItemAtURL:yuanfileURL error:nil];
        NSLog(@"文件复制失败: %@", error.localizedDescription);
        [MBProgressHUD showWithText:@"語音發送異常請重試"];
        return;
    }
    NSLog(@"destinationPath:%@",destinationPath);
    
    
    NSURL *fileURL = [NSURL fileURLWithPath:destinationPath];
    
    ChatFileModel * model = [[ChatFileModel alloc] initWithURL:fileURL];
    model.fileURL = fileURL;
    model.filePath = destinationPath;
    NSString *strtime = [self getLocalTime];

    [self sendYuyinMsg:model.fileURL.lastPathComponent filePth:destinationPath localtime:strtime state:0];
    [self OSSuploadFile:model thrid:strtime];
    
    [self.heatBeat invalidate];
    self.heatBeat = nil;

}

-(void)sendYuyinMsg:(NSString *)fileName filePth:(NSString *)filePtah localtime:(NSString *)loacaltime state:(NSInteger)index{
    NSString *filePath;
    if([fileName containsString:@"http"]){
        filePath=fileName;
    }
    else{
        filePath = [[OSSManager sharedManager] fullUploadURLByAppendPath:fileName];
    }
    NSString *content=@"【语音】";
    NSString *messageType=[NSString stringWithFormat:@"%@",MessageType_voice];
    content= [CryptoAES.shareInstance encryptStringL:content];
    NSString *type = [NSString stringWithFormat:@"%ld",(long)self.type];
    NSString *localId =loacaltime;
    if(index==1){
        localId=@"";
    }
    NSDictionary *dic =@{
        @"id":localId,
        @"messageType":messageType,
        @"chatId":self.chatId,
        @"fromId":self.userId,
        @"fromName":self.username,
        @"fromAvatar":self.useravatar,
        @"reSend":[NSNumber numberWithBool:false],
        @"content":content,
        @"type":type,
        @"localtime":loacaltime,
        @"timestamp":loacaltime,
        @"mine":[NSNumber numberWithBool:YES],
        @"extend":@{
            @"url":@"",
            @"time":[NSString stringWithFormat:@"%ld",self->_rcdL],
            @"localurl":filePtah
        }
    };
    if(index==0){
        [ChatsStore.shareInstance reciveMsg:dic];
    }
    NSDictionary *sendInfo = @{
        @"code":@"2",
        @"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); // 输出: {"name":"John","age":25}
        NSLog(@"----发送语音----");
        if(index==1){
            [GWebSocket.shareInstance sendMsg:jsonString];
        }
        
    }
}


-(void)showWebRtcVidio:(NSInteger)state{
    if(self.type==1){
        [MBProgressHUD showWithText:@"群聊暂时不支持该功能"];
        return;
    }
    BOOL audioOnly=YES;
    if(state==4){
        audioOnly = YES;
    }
    else{
        audioOnly = NO;
    }
    [[AppDelegate sharedInstance] startJSCall:self.chatId room:@"" isCaller:YES audioOnly:audioOnly];
}

#pragma mark take photo or video
- (void)takePhoto{
    // 检查设备是否支持相机
    if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
        CameraViewController *cameraVC = [[CameraViewController alloc] init];
        cameraVC.modalPresentationStyle = UIModalPresentationFullScreen;
        [self presentViewController:cameraVC animated:YES completion:nil];
        
        weakSelf(self);
        cameraVC.takePhotoFinishBlock = ^(UIImage * _Nonnull image) {
            // 保存图片到本地
            NSString *savedPath = [self saveImageToSandbox:image];
            dispatch_async(dispatch_get_main_queue(), ^{
                // 4. 更新UI或处理保存结果
                if (savedPath) {
                    NSURL * fileUrl = [NSURL fileURLWithPath:savedPath];
                    NSString *strtime = [self getLocalTime];
                    
                    //展示自己发的本地图片
                    [self uploadFile:[NSString stringWithFormat:@"%@",fileUrl] fpath:savedPath state:1 act:1 localtime:strtime];
                    [FileNetApi uploadWithFilePath:fileUrl thrid:strtime progress:^(NSString *_Nullable thrid,NSProgress * _Nullable uploadProgress) {
                        
                    } succ:^(int code,NSString *_Nullable thrid, NSDictionary * _Nullable dis) {
                        NSString *reCode =dis[@"code"];
                        if(reCode.intValue==200){
                            NSLog(@"上传成功:%@",dis[@"url"]);
                            [weakself uploadFile:dis[@"url"] fpath:savedPath state:1 act:2 localtime:thrid];
                        }
                        else{
                            NSLog(@"上传失败");
                        }
                    } fail:^(NSString *_Nullable thrid,NSError * _Nonnull error) {
                        NSLog(@"上传失败");
                    }];
                } else {
                    NSLog(@"图片保存失败");
                }
            });
        };
        
        cameraVC.takeVideoFinishBlock = ^(NSURL * _Nonnull videoUrl) {
            ChatFileModel * model = [[ChatFileModel alloc] initWithURL:videoUrl];
//            ChatFileModel * model = [[ChatFileModel alloc] initWithName:[FileInfoUtils getFileNameWithURL:videoUrl] size:[FileInfoUtils getFileSizeStringWithURL:videoUrl error:nil] isOversize:[FileInfoUtils isFileGreaterThan100MB:videoUrl error:nil]];
            model.fileURL = videoUrl;
            model.filePath = [videoUrl path];
//            [weakself handleMediaData:@[model]];
            dispatch_async(dispatch_get_main_queue(), ^{
                [weakself handleMediaData:@[model]];
            });
        };
        
    } else {
        NSLog(@"设备不支持相机");
        [MBProgressHUD showWithText:@"设备不支持相机"];
    }
}


#pragma mark menu Actoin
- (void)copyMessageContent:(NSString *)content{
    UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
    pasteboard.string = content;
    
    [MBProgressHUD showWithText:NSLocalizedString(@"cellact-copysuccese", @"")];
}

- (void)addFavorites:(NSDictionary *)dict{
    NSLog(@"----收藏的消息:%@",dict);
    NSMutableDictionary * favoritesDict = [dict mutableCopy];
    NSString *extend = @"";
    
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:favoritesDict[@"extend"] options:0 error:nil];
    if (!jsonData) {
        NSLog(@"Got an error:");
    } else {
        extend = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    }
    [favoritesDict setValue:extend forKey:@"extend"];
    [UserNetApi addFavorites:favoritesDict succ:^(int code, NSDictionary * _Nullable res) {
//        NSLog(@"------result:%@",res);
        NSString *ecode = res[@"code"];
        if(ecode.intValue==200){
            if ([res jk_hasKey:@"msg"] && ![res[@"msg"] isKindOfClass:NSNull.class]) {
                [MBProgressHUD showWithText:res[@"msg"]];
            }
        }
        else{
            [MBProgressHUD showWithText:NSLocalizedString(@"AppLock_fail", @"收藏失败")];
        }
        
    } fail:^(NSError * _Nonnull error) {
        NSLog(@"error:%@",error);
    }];
}

- (void)deleteMyMsg:(NSDictionary *)dict{
    NSMutableDictionary * msgDict = [NSMutableDictionary dictionaryWithDictionary:dict];
    [msgDict setValue:@"12" forKey:@"messageType"];
    [msgDict setValue:@"删除了一条消息" forKey:@"content"];
    [ChatsStore.shareInstance reciveMsg:msgDict];
    [ChatListStore.shareInstance reciveMsg:msgDict];
//    [self cutDataSource:@[dict]];
//    [ChatsStore.shareInstance deleteMyLocalMsg:dict];

}
//转发
- (void)forwardMsg:(NSArray *)msgArray isMultiple:(BOOL)isMultiple{
//    [MBProgressHUD showWithText:@"功能待完善"];
//    return;
    ForwardViewController * forwordVc = [[ForwardViewController alloc] init];
    forwordVc.fromChatId = self.chatId;
    forwordVc.isMultiple = isMultiple;
    forwordVc.msgArray = msgArray;
    forwordVc.userName =  self.username;
    forwordVc.userAvatar = self.useravatar;
    UINavigationController * navi = [[UINavigationController alloc] initWithRootViewController:forwordVc];
    navi.modalPresentationStyle = UIModalPresentationFullScreen;
    [self presentViewController:navi animated:YES completion:nil];
}

- (void)batchProcess{
    self.isBatchMode = YES;
    [UIView animateWithDuration:0.5 animations:^{
        self.batchView.frame = CGRectMake(0, SCREEN_HEIGHT-SCREEN_X_BTM-64, SCREEN_WIDTH, SCREEN_X_BTM+64);
    }];
    
    weakSelf(self);
    __weak typeof(self.batchView) weakView = self.batchView;
    self.batchView.indexOfBatchClicked = ^(NSInteger index) {
        weakself.isBatchMode = NO;
        if (index == 0) {//关闭
        }else if (index == 1) {
            //合并
            if (weakself.forwordMsgArray.count == 0) {
                [MBProgressHUD showWithText:@"请选择转发的消息"];
                return;
            }
            NSMutableArray * tempForwardArray = weakself.forwordMsgArray.mutableCopy;
            [weakself forwardMsg:tempForwardArray isMultiple:YES];
            [weakself.forwordMsgArray removeAllObjects];
        }else if (index == 2) {
            //逐条
            if (weakself.forwordMsgArray.count == 0) {
                [MBProgressHUD showWithText:@"请选择转发的消息"];
                return;
            }
            NSMutableArray * tempForwardArray = weakself.forwordMsgArray.mutableCopy;
            [weakself forwardMsg:tempForwardArray isMultiple:NO];
            [weakself.forwordMsgArray removeAllObjects];
        }else if (index == 3) {
            //删除
            if (weakself.forwordMsgArray.count == 0) {
                [MBProgressHUD showWithText:@"请选择删除的消息"];
                return;
            }
            
            NSMutableArray * tempForwardArray = weakself.forwordMsgArray.mutableCopy;
            for (NSDictionary * msg in tempForwardArray) {
                [weakself deleteMyMsg:msg];
            }
            [weakself.forwordMsgArray removeAllObjects];
            
        }
        [UIView animateWithDuration:0.5 animations:^{
            weakView.frame = CGRectMake(0, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_X_BTM+64);
        }];
        [weakself.forwordMsgArray removeAllObjects];
        [weakself._tableView reloadData];
    };
    
    [self._tableView reloadData];
}

- (void)messageCallback:(NSDictionary *)dict{
//    [MBProgressHUD showWithText:@"功能待完善"];
//    return;
    
    NSMutableDictionary * msgDict = [NSMutableDictionary dictionaryWithDictionary:dict];
    
    NSDate *now = [NSDate date];
    NSTimeInterval trt = [now timeIntervalSince1970];
    NSInteger time = trt*1000;
    [msgDict setValue:@"11" forKey:@"messageType"];
    [msgDict setValue:@"撤回了一条消息" forKey:@"content"];
    [msgDict setValue:[NSString stringWithFormat:@"%ld",time] forKey:@"id"];
    
//    self.msgList = [ChatsStore.shareInstance replaydisData:[msgDict copy] inarray:self.msgList];
    
    [ChatsStore.shareInstance reciveMsg:[msgDict copy]];//预先展示聊天窗信息
    [ChatListStore.shareInstance reciveMsg:msgDict];
    NSLog(@"撤回---:%@",msgDict);
    
    NSDictionary *sendInfo = @{
        @"code":@"2",
        @"message":msgDict,
    };
    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); // 输出: {"name":"John","age":25}
        NSLog(@"----撤回消息----");
        [GWebSocket.shareInstance sendMsg:jsonString];
    }
    [self ifisfileMsg:dict];
}
//撤回文件消息，同时取消上传
-(void)ifisfileMsg:(NSDictionary *)msg{
    NSString *messageType = msg[@"messageType"];
    if ([messageType isEqualToString:MessageType_file]||[messageType isEqualToString:MessageType_video]||[messageType isEqualToString:MessageType_image]) {
        NSString *lcotime = msg[@"localtime"];
        [FileNetApi stopUploadTanck:lcotime];
    }
}

- (void)quoteMessage:(ChatMessageModel *)message{
    if (self.isQuoteMessage) {
        self.quoteView.model = message;
        [self.inputView becomeFirstResponder];
        return;
    }
    self.isQuoteMessage = YES;
    self.quoteView.model = message;
    self.quoteView.hidden = NO;
    CGRect buttonViewFrame = self.bottonView.frame;
    self.bottonView.frame = CGRectMake(buttonViewFrame.origin.x, buttonViewFrame.origin.y-kQuoteViewHeight, buttonViewFrame.size.width, buttonViewFrame.size.height+kQuoteViewHeight);
//    CGRect inputViewFrame = self.inputView.frame;
//    self.inputView.frame = CGRectMake(inputViewFrame.origin.x, inputViewFrame.origin.y-kQuoteViewHeight, inputViewFrame.size.width, inputViewFrame.size.height);
    CGRect audioBtnFrame = self.yuyinctr.frame;
    self.yuyinctr.frame = CGRectMake(audioBtnFrame.origin.x, audioBtnFrame.origin.y-kQuoteViewHeight, audioBtnFrame.size.height, audioBtnFrame.size.height);
    CGRect moreFunctionBtnFrame = self.gengduoBt.frame;
    self.gengduoBt.frame = CGRectMake(moreFunctionBtnFrame.origin.x, moreFunctionBtnFrame.origin.y-kQuoteViewHeight, moreFunctionBtnFrame.size.width, moreFunctionBtnFrame.size.height);
    CGRect sendBtnFrame = self.fasngBt.frame;
    self.fasngBt.frame = CGRectMake(sendBtnFrame.origin.x, sendBtnFrame.origin.y-kQuoteViewHeight, sendBtnFrame.size.width, sendBtnFrame.size.height);
    [self.inputView becomeFirstResponder];
}

- (void)closeQuoteView{
    self.isQuoteMessage = NO;
    self.quoteView.hidden = YES;
    CGRect buttonViewFrame = self.bottonView.frame;
    self.bottonView.frame = CGRectMake(buttonViewFrame.origin.x, buttonViewFrame.origin.y+kQuoteViewHeight, buttonViewFrame.size.width, buttonViewFrame.size.height-kQuoteViewHeight);
    self.inputView.frame = CGRectMake(54, 10, self.view.frame.size.width - 180, 40);
    CGRect audioBtnFrame = self.yuyinctr.frame;
    self.yuyinctr.frame = CGRectMake(audioBtnFrame.origin.x, audioBtnFrame.origin.y+kQuoteViewHeight, audioBtnFrame.size.height, audioBtnFrame.size.height);
    CGRect moreFunctionBtnFrame = self.gengduoBt.frame;
    self.gengduoBt.frame = CGRectMake(moreFunctionBtnFrame.origin.x, moreFunctionBtnFrame.origin.y+kQuoteViewHeight, moreFunctionBtnFrame.size.width, moreFunctionBtnFrame.size.height);
    CGRect sendBtnFrame = self.fasngBt.frame;
    self.fasngBt.frame = CGRectMake(sendBtnFrame.origin.x, sendBtnFrame.origin.y+kQuoteViewHeight, sendBtnFrame.size.width, sendBtnFrame.size.height);
    
    CGRect tframe = self._tableView.frame;
    tframe.size.height = self.bottonView.frame.origin.y-tframe.origin.y;
    self._tableView.frame = tframe;
    [self movetoBotton];
}

- (void)cutDataSource:(NSArray *)msgArray{
    
    NSMutableArray * indexPathArray = [NSMutableArray array];
    NSMutableArray * tempArray = [NSMutableArray arrayWithArray:self.messageArray];
    for (NSDictionary * msg in msgArray) {
        for (ChatMessageModel * message in tempArray) {
            if ([message.formerMessage[@"id"] isEqualToString:msg[@"id"]]) {
                NSInteger index = [tempArray indexOfObject:message];
                [self.messageArray removeObjectAtIndex:index];
                NSIndexPath *deleteIndexPath = [NSIndexPath indexPathForRow:index inSection:0];
                [indexPathArray addObject:deleteIndexPath];
            }
        }
    }
    [CATransaction begin];
    [CATransaction setDisableActions:YES];
    [self._tableView beginUpdates];
    [self._tableView deleteRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationAutomatic];
    [self._tableView endUpdates];
    [CATransaction commit];
}

#pragma mark @相关
- (void)showAtMemberView{
    ChatAtMemberView * atView = [[ChatAtMemberView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT-200)];
    atView.memberArray = [ChatsStore shareInstance].groupUserList;
    
    if (self.groupInfo && [self.groupInfo[@"master"] isEqualToString:self.userId]) {
        atView.isGroupMaster = YES;
    }else{
        atView.isGroupMaster = NO;
    }
    
    //[atView jk_setRoundedCorners:UIRectCornerTopLeft|UIRectCornerTopRight radius:10.f];
    PopupView * popup = [[PopupView alloc] init];
    popup.customView = atView;
    popup.position = PopupPositionBottom;
    popup.animationType = PopupAnimationTypeFromBottom; // 从下往上动画
    popup.dismissOnBackgroundTap = YES; // 点击背景关闭
    popup.containerType = PopupContainerTypeWindow; // 添加到window
    [popup showInView:self.view];
    
    weakSelf(self);
    atView.closeAtViewBlock = ^{
        [popup dismiss];
    };
    
    atView.atMembersBlock = ^(NSArray * _Nonnull selectedArray) {
        [popup dismiss];
        for (int i = 0; i < selectedArray.count; i++) {
            NSDictionary * member = selectedArray[i];
            [weakself.inputView insertText:[NSString stringWithFormat:@"@%@ ",member[@"name"]]];
        }
        [weakself.atSomeoneArray addObjectsFromArray:selectedArray];
        [weakself.inputView becomeFirstResponder];
    };
    
    atView.atSingleMemberBlock = ^(NSDictionary * _Nonnull member) {
        [popup dismiss];
        [weakself.inputView insertText:[NSString stringWithFormat:@"@%@ ",member[@"name"]]];
        [weakself.atSomeoneArray addObject:member];
        [weakself.inputView becomeFirstResponder];
    };
    
    atView.atEveryoneBlock = ^{
        [popup dismiss];
        [weakself.inputView insertText:@"@所有人 "];
        [weakself.inputView becomeFirstResponder];
    };
}

-(void)removeAtList:(NSInteger)index{
    if(self.atSomeoneArray.count>index){
        [self.atSomeoneArray removeObjectAtIndex:index];
        [self textViewDidChange:_inputView];
    }
}




#pragma mark 文件大小排序
-(NSArray *_Nullable)fileArraysort:(NSArray *_Nullable)array{
    NSArray *sortedArray = [array sortedArrayUsingComparator:^NSComparisonResult(ChatFileModel *obj1, ChatFileModel *obj2) {
        
        if(obj1.bySize<obj2.bySize){
            return NSOrderedAscending;
        }
        else if(obj1.bySize==obj2.bySize){
            return NSOrderedSame;
        }
        else{
            return NSOrderedDescending;
        }
    }];
    return sortedArray;
}



#pragma mark 其他聊天室的消息弹窗
- (void)othersChatMessageAlert:(NSNotification *)notification {
//    NSLog(@"othersChatMessageAlert---1");
    if ([self isViewLoaded] && self.view.window) {
        NSDictionary * msgDict = notification.object;
        NSMutableDictionary * mutablemsg = msgDict.mutableCopy;
        NSLog(@"othersChatMessageAlert---2:%@",mutablemsg);
        if (msgDict) {
            ChatMessageModel *message = [ChatMessageModel modelWithDictionary:mutablemsg];
            if ([message.chatId isEqualToString:self.chatId] || message.isSender ) {
                return;
            }
            
            if ([message.chatId isEqualToString:self.userId] && message.type == 0) {
                return;
            }
            
            if (message.nickName.length==0) {
                return;
            }
            if (message.content.length==0) {
                if (message.messageType==7) {
                    message.content=NSLocalizedString(@"ChatVtr-guaduan", @"");
                }
                else{
                    return;
                }
            }
            NSLog(@"othersChatMessageAlert---3:%@",message.avatar);
//            weakSelf(self);
            [TopPopupView showWithNickname:message.nickName avatar:message.avatar message:message.content chatId:message.chatId type:message.type clickBlock:^{
//                weakself.chatId = message.chatId;
//                weakself.type = message.type;
//                weakself.titlename = message.nickName;
//                weakself.avatar = message.avatar;
//                [weakself reloadAllData];
            }];
            
        }
    }
}

-(NSString *)getLocalTime{
    if(self.messageArray.count>0){
        ChatMessageModel *lastObj = self.messageArray.lastObject;
        NSDate *now = [NSDate date];
        NSTimeInterval trt = [now timeIntervalSince1970];
        NSInteger time = trt*1000;
        if(time<lastObj.timestamp){
            time =lastObj.timestamp+1;
        }
        NSString *strtime = [NSString stringWithFormat:@"%ld",(long)time];
        return strtime;
    }
    else{
        NSDate *now = [NSDate date];
        NSTimeInterval trt = [now timeIntervalSince1970];
        NSInteger time = trt*1000;
        NSString *strtime = [NSString stringWithFormat:@"%ld",(long)time];
        return strtime;
    }
}


@end
