//
//  TUIRepliesDetailViewController.m
//  TUIChat
//
//  Created by wyl on 2022/4/27.
//  Copyright © 2023 Tencent. All rights reserved.
//

#import "TUIRepliesDetailViewController.h"
#import <TIMCommon/TUIMessageCell.h>
#import "TUIChatDataProvider.h"
#import "TUIMessageDataProvider.h"
#import "TUITextMessageCell.h"
#import "TUITextMessageCellData.h"
#import "TUIChatConfig.h"

#import <TIMCommon/TIMDefine.h>
#import <TIMCommon/TUISystemMessageCell.h>
#import <TUICore/TUICore.h>
#import <TUICore/TUIDarkModel.h>
#import <TUICore/TUIGlobalization.h>
#import <TUICore/TUIThemeManager.h>
#import "TUIFaceMessageCell.h"
#import "TUIFileMessageCell.h"
#import "TUIFileViewController.h"
#import "TUIImageMessageCell.h"
#import "TUIJoinGroupMessageCell.h"
#import "TUILinkCell.h"
#import "TUIMediaView.h"
#import "TUIMergeMessageCell.h"
#import "TUIMergeMessageListController.h"
#import "TUIMessageDataProvider.h"
#import "TUIReferenceMessageCell.h"
#import "TUIReplyMessageCell.h"
#import "TUIReplyMessageCellData.h"
#import "TUITextMessageCell.h"
#import "TUIVideoMessageCell.h"
#import "TUIVoiceMessageCell.h"
#import "TUIMessageCellConfig.h"

@interface TUIRepliesDetailViewController () <TUIInputControllerDelegate,
                                              UITableViewDelegate,
                                              UITableViewDataSource,
                                              TUIMessageBaseDataProviderDataSource,
                                              TUIMessageCellDelegate,
                                              TUINotificationProtocol,
                                              V2TIMAdvancedMsgListener>

@property(nonatomic, strong) TUIMessageCellData *cellData;
@property(nonatomic, strong) TUIMessageDataProvider *msgDataProvider;

@property(nonatomic, strong) UIView *headerView;
@property(nonatomic, strong) UITableView *tableView;
@property(nonatomic, strong) NSArray<V2TIMMessage *> *imMsgs;
@property(nonatomic, strong) NSMutableArray<TUIMessageCellData *> *uiMsgs;
@property(nonatomic, assign) BOOL responseKeyboard;
@property(nonatomic, strong) TUIChatConversationModel *conversationData;
@property(nonatomic, strong) TUIMessageCellConfig *messageCellConfig;

@property(nonatomic, strong) TUIMessageCellLayout *originCellLayout;
@property TMsgDirection direction;
@property(nonatomic, assign) BOOL showName;
@property(nonatomic, assign) BOOL showMessageTime;
@property(nonatomic) BOOL isMsgNeedReadReceipt;

@end

@implementation TUIRepliesDetailViewController
- (instancetype)initWithCellData:(TUIMessageCellData *)data conversationData:(TUIChatConversationModel *)conversationData {
    self = [super init];
    self.cellData = data;
    [self setConversation:conversationData];
    return self;
}
- (void)viewDidLoad {
    [super viewDidLoad];

    [self setupViews];

    [self setupInputViewController];

    [[V2TIMManager sharedInstance] addAdvancedMsgListener:self];

    [TUICore registerEvent:TUICore_TUIPluginNotify
                    subKey:TUICore_TUIPluginNotify_DidChangePluginViewSubKey
                    object:self];
}
- (void)viewWillAppear:(BOOL)animated {
    [self updateRootMsg];

    [self applyData];

    [self updateTableViewConstraint];

}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    self.responseKeyboard = YES;
    self.isMsgNeedReadReceipt = YES;
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    self.responseKeyboard = NO;
    [self revertRootMsg];
    if (self.willCloseCallback) {
        self.willCloseCallback();
    }
}
- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];

    if (self.inputController.status == Input_Status_Input || self.inputController.status == Input_Status_Input_Keyboard) {
        CGPoint offset = self.tableView.contentOffset;
        __weak typeof(self) weakSelf = self;
        dispatch_async(dispatch_get_main_queue(), ^{
          __strong typeof(weakSelf) strongSelf = weakSelf;
          strongSelf.responseKeyboard = YES;
          [UIApplication.sharedApplication.keyWindow endEditing:YES];
          [strongSelf inputController:strongSelf.inputController didChangeHeight:CGRectGetMaxY(strongSelf.inputController.inputBar.frame) + Bottom_SafeHeight];
          [strongSelf.tableView setContentOffset:offset];
        });
    }
}

- (void)dealloc {
    NSLog(@"%s dealloc", __FUNCTION__);
    [TUICore unRegisterEventByObject:self];
}

- (void)applyData {
    NSArray *messageModifyReplies = self.cellData.messageModifyReplies;
    NSMutableArray *msgIDArray = [NSMutableArray array];
    if (messageModifyReplies.count > 0) {
        for (NSDictionary *dic in messageModifyReplies) {
            if (dic) {
                NSString *messageID = dic[@"messageID"];
                if (IS_NOT_EMPTY_NSSTRING(messageID)) {
                    [msgIDArray addObject:messageID];
                }
            }
        }
    }

    // When the only reply is retracted, go back to the previous controller
    if (msgIDArray.count <= 0) {
        [self.navigationController popViewControllerAnimated:YES];
    }

    __weak typeof(self) weakSelf = self;
    [TUIChatDataProvider findMessages:msgIDArray
                             callback:^(BOOL succ, NSString *_Nonnull error_message, NSArray *_Nonnull msgs) {
                               __strong typeof(weakSelf) strongSelf = weakSelf;
                               if (succ) {
                                   if (msgs.count > 0) {
                                       strongSelf.imMsgs = msgs;
                                       strongSelf.uiMsgs = [self transUIMsgFromIMMsg:msgs];
                                       dispatch_async(dispatch_get_main_queue(), ^{
                                         if (strongSelf.uiMsgs.count != 0) {
                                             [strongSelf.tableView reloadData];
                                             [strongSelf.tableView layoutIfNeeded];
                                             dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 
                                                                          (int64_t)(0.1 * NSEC_PER_SEC)),
                                                            dispatch_get_main_queue(), ^{
                                                 [strongSelf scrollToBottom:NO];
                                             });
                                         }
                                       });
                                   }
                               }
                             }];
}

- (void)updateTableViewConstraint {
    CGFloat textViewHeight = TUIChatConfig.defaultConfig.enableMainPageInputBar? TTextView_Height:0;
    CGFloat height = textViewHeight + Bottom_SafeHeight;
    CGRect msgFrame = self.tableView.frame;
    msgFrame.size.height = self.view.frame.size.height - height;
    self.tableView.frame = msgFrame;
}

- (void)setupViews {
    self.title = TIMCommonLocalizableString(TUIKitRepliesDetailTitle);
    self.view.backgroundColor = TUIChatDynamicColor(@"chat_controller_bg_color", @"#FFFFFF");
    self.tableView.scrollsToTop = NO;
    self.tableView.delegate = self;
    self.tableView.dataSource = self;
    [self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
    self.tableView.contentInset = UIEdgeInsetsMake(5, 0, 0, 0);
    [self.messageCellConfig bindTableView:self.tableView];
}

- (void)setupInputViewController {
    _inputController = [[TUIInputController alloc] init];
    _inputController.delegate = self;
    _inputController.view.frame =
        CGRectMake(0, self.view.frame.size.height - TTextView_Height - Bottom_SafeHeight, self.view.frame.size.width, TTextView_Height + Bottom_SafeHeight);
    _inputController.view.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;
    _inputController.inputBar.isFromReplyPage = YES;
    [self addChildViewController:_inputController];
    [self.view addSubview:_inputController.view];
    TUIFaceGroup *group = TIMConfig.defaultConfig.faceGroups[0];
    [_inputController.faceSegementScrollView setItems:(id) @[ group ] delegate:(id)_inputController];
    TUIMenuCellData *data = [[TUIMenuCellData alloc] init];
    data.path = group.menuPath;
    data.isSelected = YES;
    [_inputController.menuView setData:(id) @[ data ]];
    _inputController.view.hidden = !TUIChatConfig.defaultConfig.enableMainPageInputBar;
    CGFloat margin = 0;
    CGFloat padding = 10;
    _inputController.inputBar.inputTextView.frame =
        CGRectMake(margin, _inputController.inputBar.inputTextView.frame.origin.y,
                   _inputController.inputBar.frame.size.width - _inputController.inputBar.faceButton.frame.size.width - margin * 2 - padding,
                   _inputController.inputBar.inputTextView.frame.size.height);

    _inputController.inputBar.faceButton.frame =
        CGRectMake(_inputController.inputBar.frame.size.width - _inputController.inputBar.faceButton.frame.size.width - margin,
                   _inputController.inputBar.faceButton.frame.origin.y, _inputController.inputBar.faceButton.frame.size.width,
                   _inputController.inputBar.faceButton.frame.size.height);

    if (_inputController.inputBar.micButton) {
        _inputController.inputBar.micButton.alpha = 0;
    }
    if (_inputController.inputBar.moreButton) {
        _inputController.inputBar.moreButton.alpha = 0;
    }
    [_inputController.inputBar defaultLayout];
}

- (void)updateRootMsg {
    self.originCellLayout = self.cellData.cellLayout;
    self.direction = self.cellData.direction;
    self.showName = self.cellData.showName;
    self.showMessageTime = self.cellData.showMessageTime;

    TUIMessageCellData *data = self.cellData;
    TUIMessageCellLayout *layout = TUIMessageCellLayout.incommingMessageLayout;
    if ([data isKindOfClass:TUITextMessageCellData.class]) {
        layout = TUIMessageCellLayout.incommingTextMessageLayout;
    }
    if ([data isKindOfClass:TUIReferenceMessageCellData.class]) {
        layout = TUIMessageCellLayout.incommingTextMessageLayout;
    }
    if ([data isKindOfClass:TUIVoiceMessageCellData.class]) {
        layout = [TUIMessageCellLayout incommingVoiceMessageLayout];
    }
    self.cellData.cellLayout = layout;
    self.cellData.direction = MsgDirectionIncoming;
    self.cellData.showName = YES;
    self.cellData.showMessageModifyReplies = NO;
    self.cellData.showMessageTime = YES;
}
- (void)revertRootMsg {
    self.cellData.cellLayout = self.originCellLayout;
    self.cellData.direction = self.direction;
    self.cellData.showName = self.showName;
    self.cellData.showMessageModifyReplies = YES;
    self.cellData.showMessageTime = self.showMessageTime;
}

- (NSMutableArray *)transUIMsgFromIMMsg:(NSArray *)msgs {
    NSMutableArray *uiMsgs = [NSMutableArray array];
    for (NSInteger k = 0; k < msgs.count; k++) {
        V2TIMMessage *msg = msgs[k];
        TUIMessageCellData *data = [TUITextMessageCellData getCellData:msg];
        TUIMessageCellLayout *layout = TUIMessageCellLayout.incommingMessageLayout;
        if ([data isKindOfClass:TUITextMessageCellData.class]) {
            layout = TUIMessageCellLayout.incommingTextMessageLayout;
        }
        data.cellLayout = layout;
        data.direction = MsgDirectionIncoming;
        data.showName = YES;
        if (data) {
            data.innerMessage = msg;
            [uiMsgs addObject:data];
        }
    }

    NSArray *sortedArray = [uiMsgs sortedArrayUsingComparator:^NSComparisonResult(TUIMessageCellData *obj1, TUIMessageCellData *obj2) {
      if ([obj1.innerMessage.timestamp timeIntervalSince1970] == [obj2.innerMessage.timestamp timeIntervalSince1970]) {
          return obj1.innerMessage.seq > obj2.innerMessage.seq;
      } else {
          return [obj1.innerMessage.timestamp compare:obj2.innerMessage.timestamp];
      }
    }];

    uiMsgs = [NSMutableArray arrayWithArray:sortedArray];

    return uiMsgs;
}

#pragma mark - tableView

- (UITableView *)tableView {
    if (!_tableView) {
        CGRect rect = self.view.bounds;
        _tableView = [[UITableView alloc] initWithFrame:rect style:UITableViewStylePlain];
        if (@available(iOS 15.0, *)) {
            _tableView.sectionHeaderTopPadding = 0;
        }
        [self.view addSubview:_tableView];
    }
    return _tableView;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 2;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    if (section == 1) {
        return 20;
    }
    return 0;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    if (section == 1) {
        UIView *view = [[UIView alloc] init];
        view.backgroundColor = [UIColor clearColor];
        return view;
    }
    return nil;
}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
    if (section == 0) {
        return 0.5;
    }
    return 0;
}
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
    if (section == 0) {
        UIView *line = [[UIView alloc] initWithFrame:CGRectMake(0, 0, Screen_Width, 0.5)];
        line.backgroundColor = TIMCommonDynamicColor(@"separator_color", @"#DBDBDB");
        return line;
    }
    return nil;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if (section == 0) {
        return 1;
    }
    return _uiMsgs.count;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.section == 0) {
        return [self.messageCellConfig getHeightFromMessageCellData:self.cellData];
    } else {
        if (indexPath.row < self.uiMsgs.count) {
            TUIMessageCellData *cellData = self.uiMsgs[indexPath.row];
            return [self.messageCellConfig getHeightFromMessageCellData:cellData];
        } else {
            return 0;
        }
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.section == 0) {
        TUIMessageCell *cell = nil;
        TUIMessageCellData *data = self.cellData;
        cell = [tableView dequeueReusableCellWithIdentifier:data.reuseId forIndexPath:indexPath];
        cell.delegate = self;
        [cell fillWithData:data];
        [cell notifyBottomContainerReadyOfData:nil];
        return cell;
    }
    TUIMessageCellData *data = _uiMsgs[indexPath.row];
    data.showMessageTime = YES;
    data.showCheckBox = NO;
    TUIMessageCell *cell = nil;

    cell = [tableView dequeueReusableCellWithIdentifier:data.reuseId forIndexPath:indexPath];
    [cell fillWithData:_uiMsgs[indexPath.row]];
    cell.delegate = self;
    [cell notifyBottomContainerReadyOfData:nil];
    if ([cell isKindOfClass:TUIBubbleMessageCell.class]) {
        TUIBubbleMessageCell *bubbleCell = (TUIBubbleMessageCell *)cell;
        if (bubbleCell.bubbleView) {
            bubbleCell.bubbleView.image = nil;
        }
    }
    return cell;
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
    [self.inputController reset];
}
#pragma mark - TUIInputControllerDelegate

- (void)inputController:(TUIInputController *)inputController didChangeHeight:(CGFloat)height {
    if (!self.responseKeyboard) {
        return;
    }

    if (self.inputController.replyData == nil) {
        [self onRelyMessage:self.cellData];
    }
    [UIView animateWithDuration:0.3
                          delay:0
                        options:UIViewAnimationOptionCurveEaseOut
                     animations:^{
                       CGRect msgFrame = self.tableView.frame;
                       msgFrame.size.height = self.view.frame.size.height - height;
                       self.tableView.frame = msgFrame;

                       CGRect inputFrame = self.inputController.view.frame;
                       inputFrame.origin.y = msgFrame.origin.y + msgFrame.size.height;
                       inputFrame.size.height = height;
                       self.inputController.view.frame = inputFrame;

                       [self scrollToBottom:NO];
                     }
                     completion:nil];
}

- (void)inputController:(TUIInputController *)inputController didSendMessage:(V2TIMMessage *)msg {
    [self sendMessage:msg];
}

- (void)inputController:(TUIInputController *)inputController didSelectMoreCell:(TUIInputMoreCell *)cell {
    cell.disableDefaultSelectAction = NO;

    if (cell.disableDefaultSelectAction) {
        return;
    }
}

- (void)sendMessage:(V2TIMMessage *)message {
    TUIMessageCellData *cellData = nil;
    if (!cellData) {
        cellData = [TUIMessageDataProvider getCellData:message];
    }
    if (cellData) {
        cellData.innerMessage.needReadReceipt = self.isMsgNeedReadReceipt;
        [self sendUIMessage:cellData];
    }
}

- (void)sendUIMessage:(TUIMessageCellData *)cellData {
    @weakify(self);
    [self.parentPageDataProvider sendUIMsg:cellData
        toConversation:self.conversationData
        willSendBlock:^(BOOL isReSend, TUIMessageCellData *_Nonnull dateUIMsg) {
          @strongify(self);

          int delay = 1;
          if ([cellData isKindOfClass:[TUIImageMessageCellData class]]) {
              delay = 0;
          }

          @weakify(self);
          dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            @strongify(self);
            if (cellData.status == Msg_Status_Sending) {
                [self changeMsg:cellData status:Msg_Status_Sending_2];
            }
          });
        }
        SuccBlock:^{
          @strongify(self);
          [self changeMsg:cellData status:Msg_Status_Succ];
          [self scrollToBottom:YES];
        }
        FailBlock:^(int code, NSString *desc) {
          @strongify(self);
          [TUITool makeToastError:code msg:desc];
          [self changeMsg:cellData status:Msg_Status_Fail];
        }];
}

- (void)scrollToBottom:(BOOL)animated {
    if (self.uiMsgs.count > 0) {
        [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self.uiMsgs.count - 1 inSection:1]
                              atScrollPosition:UITableViewScrollPositionBottom
                                      animated:animated];
    }
}

- (void)changeMsg:(TUIMessageCellData *)msg status:(TMsgStatus)status {
    msg.status = status;
    NSInteger index = [self.uiMsgs indexOfObject:msg];
    if ([self.tableView numberOfRowsInSection:0] > index) {
        TUIMessageCell *cell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0]];
        [cell fillWithData:msg];
    } else {
        NSLog(@"lack of cell");
    }

    [[NSNotificationCenter defaultCenter] postNotificationName:@"kTUINotifyMessageStatusChanged"
                                                        object:nil
                                                      userInfo:@{
                                                          @"msg" : msg,
                                                          @"status" : [NSNumber numberWithUnsignedInteger:status],
                                                          @"msgSender" : self,
                                                      }];
}

#pragma mark - Message reply

- (void)onRelyMessage:(nonnull TUIMessageCellData *)data {
    NSString *desc = @"";
    desc = [self replyReferenceMessageDesc:data];

    TUIReplyPreviewData *replyData = [[TUIReplyPreviewData alloc] init];
    replyData.msgID = data.msgID;
    replyData.msgAbstract = desc;
    replyData.sender = data.senderName;
    replyData.type = (NSInteger)data.innerMessage.elemType;
    replyData.originMessage = data.innerMessage;
    self.inputController.replyData = replyData;
}
- (NSString *)replyReferenceMessageDesc:(TUIMessageCellData *)data {
    NSString *desc = @"";
    if (data.innerMessage.elemType == V2TIM_ELEM_TYPE_FILE) {
        desc = data.innerMessage.fileElem.filename;
    } else if (data.innerMessage.elemType == V2TIM_ELEM_TYPE_MERGER) {
        desc = data.innerMessage.mergerElem.title;
    } else if (data.innerMessage.elemType == V2TIM_ELEM_TYPE_CUSTOM) {
        desc = [TUIMessageDataProvider getDisplayString:data.innerMessage];
    } else if (data.innerMessage.elemType == V2TIM_ELEM_TYPE_TEXT) {
        desc = data.innerMessage.textElem.text;
    }
    return desc;
}

#pragma mark - TUIMessageCellDelegate
- (void)onSelectMessage:(TUIMessageCell *)cell {
    if (TUIChatConfig.defaultConfig.eventConfig.chatEventListener &&
        [TUIChatConfig.defaultConfig.eventConfig.chatEventListener respondsToSelector:@selector(onMessageClicked:messageCellData:)]) {
        BOOL result = [TUIChatConfig.defaultConfig.eventConfig.chatEventListener onMessageClicked:cell messageCellData:cell.messageData];
        if (result) {
            return;
        }
    }
    if ([cell isKindOfClass:[TUIImageMessageCell class]]) {
        [self showImageMessage:(TUIImageMessageCell *)cell];
    }
    if ([cell isKindOfClass:[TUIVoiceMessageCell class]]) {
        [self playVoiceMessage:(TUIVoiceMessageCell *)cell];
    }
    if ([cell isKindOfClass:[TUIVideoMessageCell class]]) {
        [self showVideoMessage:(TUIVideoMessageCell *)cell];
    }
    if ([cell isKindOfClass:[TUIFileMessageCell class]]) {
        [self showFileMessage:(TUIFileMessageCell *)cell];
    }
    if ([cell isKindOfClass:[TUIMergeMessageCell class]]) {
        TUIMergeMessageListController *mergeVc = [[TUIMergeMessageListController alloc] init];
        mergeVc.mergerElem = [(TUIMergeMessageCell *)cell mergeData].mergerElem;
        mergeVc.delegate = self.delegate;
        [self.navigationController pushViewController:mergeVc animated:YES];
    }
    if ([cell isKindOfClass:[TUILinkCell class]]) {
        [self showLinkMessage:(TUILinkCell *)cell];
    }
    //    if ([cell isKindOfClass:[TUIReplyMessageCell class]]) {
    //        [self showReplyMessage:(TUIReplyMessageCell *)cell];
    //    }
    //    if ([cell isKindOfClass:[TUIReferenceMessageCell class]]) {
    //        [self showReplyMessage:(TUIReplyMessageCell *)cell];
    //    }

    if ([self.delegate respondsToSelector:@selector(messageController:onSelectMessageContent:)]) {
        [self.delegate messageController:nil onSelectMessageContent:cell];
    }
}

#pragma mark - V2TIMAdvancedMsgListener

- (void)onRecvNewMessage:(V2TIMMessage *)msg {
    V2TIMMessage *imMsg = msg;
    if (imMsg == nil || ![imMsg isKindOfClass:V2TIMMessage.class]) {
        return;
    }
    if ([imMsg.msgID isEqualToString:self.cellData.msgID] ) {
        TUIMessageCellData *cellData = [TUIMessageDataProvider getCellData:imMsg];
        self.cellData.messageModifyReplies = cellData.messageModifyReplies;
        [self applyData];
    }

}
- (void)onRecvMessageModified:(V2TIMMessage *)msg {
    V2TIMMessage *imMsg = msg;
    if (imMsg == nil || ![imMsg isKindOfClass:V2TIMMessage.class]) {
        return;
    }
    if ([imMsg.msgID isEqualToString:self.cellData.msgID] ) {
        TUIMessageCellData *cellData = [TUIMessageDataProvider getCellData:imMsg];
        self.cellData.messageModifyReplies = cellData.messageModifyReplies;
        [self applyData];
    }

}

#pragma mark - dataProviderDataChange
- (void)dataProviderDataSourceWillChange:(TUIMessageDataProvider *)dataProvider {
}

- (void)dataProviderDataSourceChange:(TUIMessageDataProvider *)dataProvider
                            withType:(TUIMessageBaseDataProviderDataSourceChangeType)type
                             atIndex:(NSUInteger)index
                           animation:(BOOL)animation {
}

- (void)dataProviderDataSourceDidChange:(TUIMessageDataProvider *)dataProvider {
    
}

- (void)dataProvider:(TUIMessageBaseDataProvider *)dataProvider onRemoveHeightCache:(TUIMessageCellData *)cellData {
    if (cellData) {
        [self.messageCellConfig removeHeightCacheOfMessageCellData:cellData];
    }
}

#pragma mark - action

- (void)showImageMessage:(TUIImageMessageCell *)cell {
    CGRect frame = [cell.thumb convertRect:cell.thumb.bounds toView:[UIApplication sharedApplication].delegate.window];
    TUIMediaView *mediaView = [[TUIMediaView alloc] initWithFrame:CGRectMake(0, 0, Screen_Width, Screen_Height)];
    [mediaView setThumb:cell.thumb frame:frame];
    [mediaView setCurMessage:cell.messageData.innerMessage allMessages:@[ self.cellData.innerMessage ]];
    [[UIApplication sharedApplication].keyWindow addSubview:mediaView];
}

- (void)playVoiceMessage:(TUIVoiceMessageCell *)cell {
    TUIVoiceMessageCellData *uiMsg = (TUIVoiceMessageCellData *)self.cellData;
    if (uiMsg == cell.voiceData) {
        [uiMsg playVoiceMessage];
        cell.voiceReadPoint.hidden = YES;
    } else {
        [uiMsg stopVoiceMessage];
    }
}

- (void)showVideoMessage:(TUIVideoMessageCell *)cell {
    CGRect frame = [cell.thumb convertRect:cell.thumb.bounds toView:[UIApplication sharedApplication].delegate.window];
    TUIMediaView *mediaView = [[TUIMediaView alloc] initWithFrame:CGRectMake(0, 0, Screen_Width, Screen_Height)];
    [mediaView setThumb:cell.thumb frame:frame];
    [mediaView setCurMessage:cell.messageData.innerMessage allMessages:@[ self.cellData.innerMessage ]];
    __weak typeof(self) weakSelf = self;
    mediaView.onClose = ^{
      [weakSelf.tableView reloadData];
    };
    [[UIApplication sharedApplication].keyWindow addSubview:mediaView];
}

- (void)showFileMessage:(TUIFileMessageCell *)cell {
    if (self.filePreviewDelegate && [self.filePreviewDelegate respondsToSelector:@selector(didTapInFileCell:)]) {
        [self.filePreviewDelegate didTapInFileCell: [cell fileData]];
    } else {
        TUIFileViewController *file = [[TUIFileViewController alloc] init];
        file.data = [cell fileData];
        [self.navigationController pushViewController:file animated:YES];
    }
}

- (void)showLinkMessage:(TUILinkCell *)cell {
    TUILinkCellData *cellData = cell.customData;
    if (cellData.link) {
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:cellData.link]];
    }
}

- (void)setConversation:(TUIChatConversationModel *)conversationData {
    self.conversationData = conversationData;
    if (!self.msgDataProvider) {
        self.msgDataProvider = [[TUIMessageDataProvider alloc] initWithConversationModel:conversationData];
        self.msgDataProvider.dataSource = self;
    }
    [self loadMessage];
}
- (void)loadMessage {
    if (self.msgDataProvider.isLoadingData || self.msgDataProvider.isNoMoreMsg) {
        return;
    }

    [self.msgDataProvider
        loadMessageSucceedBlock:^(BOOL isFirstLoad, BOOL isNoMoreMsg, NSArray<TUIMessageCellData *> *_Nonnull newMsgs) {

        }
        FailBlock:^(int code, NSString *desc) {
          [TUITool makeToastError:code msg:desc];
        }];
}

#pragma mark - TUINotificationProtocol
- (void)onNotifyEvent:(NSString *)key subKey:(NSString *)subKey object:(id)anObject param:(NSDictionary *)param {
    if ([key isEqualToString:TUICore_TUIPluginNotify] &&
        [subKey isEqualToString:TUICore_TUIPluginNotify_DidChangePluginViewSubKey]) {
        TUIMessageCellData *data = param[TUICore_TUIPluginNotify_DidChangePluginViewSubKey_Data];
        NSInteger section = 1;
        if ([data.msgID isEqualToString:self.cellData.msgID] ) {
            //root section
            section = 0;
        }
        [self.messageCellConfig removeHeightCacheOfMessageCellData:data];
        [self reloadAndScrollToBottomOfMessage:data.innerMessage.msgID section:section];
    }
}

- (void)reloadAndScrollToBottomOfMessage:(NSString *)messageID section:(NSInteger)section {
    // Dispatch the task to RunLoop to ensure that they are executed after the UITableView refresh is complete.
    dispatch_async(dispatch_get_main_queue(), ^{
      [self reloadCellOfMessage:messageID section:section];
      dispatch_async(dispatch_get_main_queue(), ^{
        [self scrollCellToBottomOfMessage:messageID section:section];
      });
    });
}

- (void)reloadCellOfMessage:(NSString *)messageID section:(NSInteger)section {
    NSIndexPath *indexPath = [self indexPathOfMessage:messageID section:section];

    // Disable animation when loading to avoid cell jumping.
    if (indexPath == nil) {
        return;
    }
    [UIView performWithoutAnimation:^{
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.tableView reloadRowsAtIndexPaths:@[ indexPath ] withRowAnimation:UITableViewRowAnimationNone];
        });
    }];
}

- (void)scrollCellToBottomOfMessage:(NSString *)messageID section:(NSInteger)section {
    NSIndexPath *indexPath = [self indexPathOfMessage:messageID section:section];

    // Scroll the tableView only if the bottom of the cell is invisible.
    CGRect cellRect = [self.tableView rectForRowAtIndexPath:indexPath];
    CGRect tableViewRect = self.tableView.bounds;
    BOOL isBottomInvisible = cellRect.origin.y < CGRectGetMaxY(tableViewRect) && CGRectGetMaxY(cellRect) > CGRectGetMaxY(tableViewRect);
    if (isBottomInvisible) {
        [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
    }
}

- (NSIndexPath *)indexPathOfMessage:(NSString *)messageID section:(NSInteger)section {
    if (section == 0) {
        return [NSIndexPath indexPathForRow:0 inSection:section];
    } else {
        for (int i = 0; i < self.uiMsgs.count; i++) {
            TUIMessageCellData *data = self.uiMsgs[i];
            if ([data.innerMessage.msgID isEqualToString:messageID]) {
                return [NSIndexPath indexPathForRow:i inSection:section];
            }
        }
    }
    return nil;
}

- (TUIMessageCellConfig *)messageCellConfig {
    if (_messageCellConfig == nil) {
        _messageCellConfig = [[TUIMessageCellConfig alloc] init];
    }
    return _messageCellConfig;
}

@end
