//
//  TInputController.m
//  UIKit
//
//  Created by kennethmiao on 2018/9/18.
//  Copyright © 2018 Tencent. All rights reserved.
//

#import "TUIInputController.h"
#import <AVFoundation/AVFoundation.h>
#import <TIMCommon/NSString+TUIEmoji.h>
#import <TIMCommon/TIMCommonModel.h>
#import <TIMCommon/TIMDefine.h>
#import <TUICore/TUICore.h>
#import <TUICore/TUIDarkModel.h>
#import <TUICore/TUIThemeManager.h>
#import "TUIChatDataProvider.h"
#import "TUIChatModifyMessageHelper.h"
#import "TUICloudCustomDataTypeCenter.h"
#import "TUIFaceMessageCell.h"
#import "TUIInputMoreCell.h"
#import "TUIMenuCell.h"
#import "TUIMenuCellData.h"
#import "TUIMessageDataProvider.h"
#import "TUITextMessageCell.h"
#import "TUIVoiceMessageCell.h"
#import <TIMCommon/TIMCommonMediator.h>
#import <TIMCommon/TUIEmojiMeditorProtocol.h>


@interface TUIInputController () <TUIInputBarDelegate, TUIMenuViewDelegate, TUIFaceViewDelegate, TUIMoreViewDelegate>
@property(nonatomic, assign) InputStatus status;
@property(nonatomic, assign) CGRect keyboardFrame;

@property(nonatomic, copy) void (^modifyRootReplyMsgBlock)(TUIMessageCellData *);
@end

@implementation TUIInputController
- (void)viewDidLoad {
    [super viewDidLoad];
    [self setupViews];
    
    _inputBar.frame = CGRectMake(16, CGRectGetMaxY(self.replyPreviewBar.frame), self.view.frame.size.width - 32, TTextView_Height);
    [_inputBar setNeedsLayout];
    _menuView.frame = CGRectMake(16, _inputBar.frame.origin.y + _inputBar.frame.size.height, self.view.frame.size.width - 32, TMenuView_Menu_Height);
    [_menuView setNeedsLayout];
    _faceSegementScrollView.frame = CGRectMake(0, _menuView.frame.origin.y + _menuView.frame.size.height, self.view.frame.size.width, TFaceView_Height);
    [_faceSegementScrollView setNeedsLayout];
    _moreView.frame = CGRectMake(0, _inputBar.frame.origin.y + _inputBar.frame.size.height, self.view.frame.size.width, _moreView.frame.size.height);
    [_moreView setNeedsLayout];
}
- (void)viewWillAppear:(BOOL)animated {
    [_inputBar setNeedsLayout];
    [_menuView setNeedsLayout];
    [_faceSegementScrollView setNeedsLayout];
    [_moreView setNeedsLayout];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(inputMessageStatusChanged:) name:@"kTUINotifyMessageStatusChanged" object:nil];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    for (UIGestureRecognizer *gesture in self.view.window.gestureRecognizers) {
        NSLog(@"gesture = %@", gesture);
        gesture.delaysTouchesBegan = NO;
        NSLog(@"delaysTouchesBegan = %@", gesture.delaysTouchesBegan ? @"YES" : @"NO");
        NSLog(@"delaysTouchesEnded = %@", gesture.delaysTouchesEnded ? @"YES" : @"NO");
    }
    self.navigationController.interactivePopGestureRecognizer.delaysTouchesBegan = NO;
}

- (void)viewDidDisappear:(BOOL)animated {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)setupViews {
    self.view.backgroundColor = TUIChatDynamicColor(@"chat_input_controller_bg_color", @"#EBF0F6");
    _status = Input_Status_Input;

    _inputBar = [[TUIInputBar alloc] initWithFrame:CGRectZero];
    _inputBar.delegate = self;
    [self.view addSubview:_inputBar];
}

- (void)keyboardWillHide:(NSNotification *)notification {
    if (_delegate && [_delegate respondsToSelector:@selector(inputController:didChangeHeight:)]) {
        CGFloat inputContainerBottom = [self getInputContainerBottom];
        [_delegate inputController:self didChangeHeight:inputContainerBottom + Bottom_SafeHeight];
    }
    if (_status == Input_Status_Input_Keyboard) {
        _status = Input_Status_Input;
    }
}

- (void)keyboardWillShow:(NSNotification *)notification {
    if (_status == Input_Status_Input_Face) {
        [self hideFaceAnimation];
    } else if (_status == Input_Status_Input_More) {
        [self hideMoreAnimation];
    } else {
        //[self hideFaceAnimation:NO];
        //[self hideMoreAnimation:NO];
    }
    _status = Input_Status_Input_Keyboard;
}

- (void)keyboardWillChangeFrame:(NSNotification *)notification {
    CGRect keyboardFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    if (_delegate && [_delegate respondsToSelector:@selector(inputController:didChangeHeight:)]) {
        CGFloat inputContainerBottom = [self getInputContainerBottom];
        [_delegate inputController:self didChangeHeight:keyboardFrame.size.height + inputContainerBottom];
    }
    self.keyboardFrame = keyboardFrame;
}

- (void)hideFaceAnimation {
    self.faceSegementScrollView.hidden = NO;
    self.faceSegementScrollView.alpha = 1.0;
    self.menuView.hidden = NO;
    self.menuView.alpha = 1.0;
    __weak typeof(self) ws = self;
    [UIView animateWithDuration:0.3
        delay:0
        options:UIViewAnimationOptionCurveEaseOut
        animations:^{
          ws.faceSegementScrollView.alpha = 0.0;
          ws.menuView.alpha = 0.0;
        }
        completion:^(BOOL finished) {
          ws.faceSegementScrollView.hidden = YES;
          ws.faceSegementScrollView.alpha = 1.0;
          ws.menuView.hidden = YES;
          ws.menuView.alpha = 1.0;
          [ws.menuView removeFromSuperview];
          [ws.faceSegementScrollView removeFromSuperview];
        }];
}

- (void)showFaceAnimation {
    [self.view addSubview:self.faceSegementScrollView];
    [self.view addSubview:self.menuView];
    __weak typeof(self) ws = self;
    [self.faceSegementScrollView updateRecentView];
    [self.faceSegementScrollView setAllFloatCtrlViewAllowSendSwitch:(self.inputBar.inputTextView.text.length > 0)?YES:NO];
    self.faceSegementScrollView.onScrollCallback = ^(NSInteger indexPage) {
        [ws.menuView scrollToMenuIndex:indexPage];
    };
    self.inputBar.inputBarTextChanged = ^(UITextView *textview) {
        if(textview.text.length > 0) {
            [ws.faceSegementScrollView setAllFloatCtrlViewAllowSendSwitch:YES];
        }
        else {
            [ws.faceSegementScrollView setAllFloatCtrlViewAllowSendSwitch:NO];
        }
    };
    
    
    self.faceSegementScrollView.hidden = NO;
    CGRect frame = self.menuView.frame;
    frame.origin.y = self.view.window.frame.size.height;
    self.menuView.frame = frame;
    self.menuView.hidden = NO;
    frame = self.faceSegementScrollView.frame;
    frame.origin.y = self.menuView.frame.origin.y + self.menuView.frame.size.height;
    self.faceSegementScrollView.frame = frame;

    [UIView animateWithDuration:0.3
                          delay:0
                        options:UIViewAnimationOptionCurveEaseOut
                     animations:^{
                       CGRect newFrame = ws.menuView.frame;
                       newFrame.origin.y = CGRectGetMaxY(ws.inputBar.frame);  // ws.inputBar.frame.origin.y + ws.inputBar.frame.size.height;
                       ws.menuView.frame = newFrame;

                       newFrame = ws.faceSegementScrollView.frame;
                       newFrame.origin.y = ws.menuView.frame.origin.y + ws.menuView.frame.size.height;
                       ws.faceSegementScrollView.frame = newFrame;
                     }
                     completion:nil];
}

- (void)hideMoreAnimation {
    self.moreView.hidden = NO;
    self.moreView.alpha = 1.0;
    __weak typeof(self) ws = self;
    [UIView animateWithDuration:0.3
        delay:0
        options:UIViewAnimationOptionCurveEaseOut
        animations:^{
          ws.moreView.alpha = 0.0;
        }
        completion:^(BOOL finished) {
          ws.moreView.hidden = YES;
          ws.moreView.alpha = 1.0;
          [ws.moreView removeFromSuperview];
        }];
}

- (void)showMoreAnimation {
    [self.view addSubview:self.moreView];

    self.moreView.hidden = NO;
    CGRect frame = self.moreView.frame;
    frame.origin.y = self.view.window.frame.size.height;
    self.moreView.frame = frame;
    __weak typeof(self) ws = self;
    [UIView animateWithDuration:0.3
                          delay:0
                        options:UIViewAnimationOptionCurveEaseOut
                     animations:^{
                       CGRect newFrame = ws.moreView.frame;
                       newFrame.origin.y = ws.inputBar.frame.origin.y + ws.inputBar.frame.size.height;
                       ws.moreView.frame = newFrame;
                     }
                     completion:nil];
}

- (void)inputBarDidTouchVoice:(TUIInputBar *)textView {
    if (_status == Input_Status_Input_Talk) {
        return;
    }
    [_inputBar.inputTextView resignFirstResponder];
    [self hideFaceAnimation];
    [self hideMoreAnimation];
    _status = Input_Status_Input_Talk;
    if (_delegate && [_delegate respondsToSelector:@selector(inputController:didChangeHeight:)]) {
        CGFloat inputContainerBottom = [self getInputContainerBottom];
        [_delegate inputController:self didChangeHeight:inputContainerBottom + Bottom_SafeHeight];
    }
}

- (void)inputBarDidTouchMore:(TUIInputBar *)textView {
    if (_status == Input_Status_Input_More) {
        return;
    }
    if (_status == Input_Status_Input_Face) {
        [self hideFaceAnimation];
    }
    [_inputBar.inputTextView resignFirstResponder];
    [self showMoreAnimation];
    _status = Input_Status_Input_More;
    if (_delegate && [_delegate respondsToSelector:@selector(inputController:didChangeHeight:)]) {
        [_delegate inputController:self didChangeHeight:CGRectGetMaxY(_inputBar.frame) + self.moreView.frame.size.height + Bottom_SafeHeight];
    }
    
    if (_delegate && [_delegate respondsToSelector:@selector(inputControllerDidClickMore:)]) {
        [_delegate inputControllerDidClickMore:self];
    }
}

- (void)inputBarDidTouchFace:(TUIInputBar *)textView {
    if ([TIMConfig defaultConfig].faceGroups.count == 0) {
        return;
    }
    
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    
    if (_status == Input_Status_Input_More) {
        [self hideMoreAnimation];
    }
    [_inputBar.inputTextView resignFirstResponder];
    _status = Input_Status_Input_Face;
    if (_delegate && [_delegate respondsToSelector:@selector(inputController:didChangeHeight:)]) {
        [_delegate inputController:self
                   didChangeHeight:CGRectGetMaxY(_inputBar.frame) + self.faceSegementScrollView.frame.size.height + self.menuView.frame.size.height ];
    }
    [self showFaceAnimation];
}

- (void)inputBarDidTouchKeyboard:(TUIInputBar *)textView {
    if (_status == Input_Status_Input_More) {
        [self hideMoreAnimation];
    }
    if (_status == Input_Status_Input_Face) {
        [self hideFaceAnimation];
    }
    _status = Input_Status_Input_Keyboard;
    [_inputBar.inputTextView becomeFirstResponder];
}

- (void)inputBar:(TUIInputBar *)textView didChangeInputHeight:(CGFloat)offset {
    if (_status == Input_Status_Input_Face) {
        [self showFaceAnimation];
    } else if (_status == Input_Status_Input_More) {
        [self showMoreAnimation];
    }
    if (_delegate && [_delegate respondsToSelector:@selector(inputController:didChangeHeight:)]) {
        [_delegate inputController:self didChangeHeight:self.view.frame.size.height + offset];
        if (_referencePreviewBar) {
            CGRect referencePreviewBarFrame = _referencePreviewBar.frame;
            _referencePreviewBar.frame = CGRectMake(referencePreviewBarFrame.origin.x, referencePreviewBarFrame.origin.y + offset,
                                                    referencePreviewBarFrame.size.width, referencePreviewBarFrame.size.height);
        }
    }
}

- (void)inputBar:(TUIInputBar *)textView didSendText:(NSString *)text {
    /**
     * Emoticon internationalization --> restore to actual Chinese key
     */
    NSString *content = [text getInternationalStringWithfaceContent];
    V2TIMMessage *message = [[V2TIMManager sharedInstance] createTextMessage:content];
    [self appendReplyDataIfNeeded:message];
    [self appendReferenceDataIfNeeded:message];
    if (_delegate && [_delegate respondsToSelector:@selector(inputController:didSendMessage:)]) {
        [_delegate inputController:self didSendMessage:message];
    }
}

- (void)inputMessageStatusChanged:(NSNotification *)noti {
    NSDictionary *userInfo = noti.userInfo;
    TUIMessageCellData *msg = userInfo[@"msg"];
    long status = [userInfo[@"status"] intValue];
    if ([msg isKindOfClass:TUIMessageCellData.class] && status == Msg_Status_Succ) {
        dispatch_async(dispatch_get_main_queue(), ^{
          if (self.modifyRootReplyMsgBlock) {
              self.modifyRootReplyMsgBlock(msg);
          }
        });
    }
}

- (void)appendReplyDataIfNeeded:(V2TIMMessage *)message {
    if (self.replyData) {
        V2TIMMessage *parentMsg = self.replyData.originMessage;
        NSMutableDictionary *simpleReply = [NSMutableDictionary dictionary];
        [simpleReply addEntriesFromDictionary:@{
            @"messageID" : self.replyData.msgID ?: @"",
            @"messageAbstract" : [self.replyData.msgAbstract ?: @"" getInternationalStringWithfaceContent],
            @"messageSender" : self.replyData.sender ?: @"",
            @"messageType" : @(self.replyData.type),
            @"messageTime" : @(self.replyData.originMessage.timestamp ? [self.replyData.originMessage.timestamp timeIntervalSince1970] : 0),
            @"messageSequence" : @(self.replyData.originMessage.seq),
            @"version" : @(kMessageReplyVersion),
        }];

        NSMutableDictionary *cloudResultDic = [[NSMutableDictionary alloc] initWithCapacity:5];
        if (parentMsg.cloudCustomData) {
            NSDictionary *originDic = [TUITool jsonData2Dictionary:parentMsg.cloudCustomData];
            if (originDic && [originDic isKindOfClass:[NSDictionary class]]) {
                [cloudResultDic addEntriesFromDictionary:originDic];
            }
            /**
             * Accept the data in the parent, but cannot save messageReplies\messageReact, because the root message topic creator has this field.
             * messageReplies\messageReact cannot be stored in the new message currently sent
             */
            [cloudResultDic removeObjectForKey:@"messageReplies"];
            [cloudResultDic removeObjectForKey:@"messageReact"];
        }
        NSString *messageParentReply = cloudResultDic[@"messageReply"];
        NSString *messageRootID = [messageParentReply valueForKey:@"messageRootID"];
        if (self.replyData.messageRootID.length > 0) {
            messageRootID = self.replyData.messageRootID;
        }
        if (!IS_NOT_EMPTY_NSSTRING(messageRootID)) {
            /**
             * If the original message does not have a messageRootID, you need to use the msgID of the current original message as root
             */
            if (IS_NOT_EMPTY_NSSTRING(parentMsg.msgID)) {
                messageRootID = parentMsg.msgID;
            }
        }
        [simpleReply setObject:messageRootID forKey:@"messageRootID"];
        [cloudResultDic setObject:simpleReply forKey:@"messageReply"];
        NSData *data = [TUITool dictionary2JsonData:cloudResultDic];
        if (data) {
            message.cloudCustomData = data;
        }

        [self exitReplyAndReference:nil];

        __weak typeof(self) weakSelf = self;
        self.modifyRootReplyMsgBlock = ^(TUIMessageCellData *cellData) {
          __strong typeof(self) strongSelf = weakSelf;
          [strongSelf modifyRootReplyMsgByID:messageRootID currentMsg:cellData];
          strongSelf.modifyRootReplyMsgBlock = nil;
        };
    }
}

- (void)modifyRootReplyMsgByID:(NSString *)messageRootID currentMsg:(TUIMessageCellData *)messageCellData {
    NSDictionary *simpleCurrentContent = @{
        @"messageID" : messageCellData.innerMessage.msgID ?: @"",
        @"messageAbstract" : [messageCellData.innerMessage.textElem.text ?: @"" getInternationalStringWithfaceContent],
        @"messageSender" : messageCellData.senderName ? : @"",
        @"messageType" : @(messageCellData.innerMessage.elemType),
        @"messageTime" : @(messageCellData.innerMessage.timestamp ? [messageCellData.innerMessage.timestamp timeIntervalSince1970] : 0),
        @"messageSequence" : @(messageCellData.innerMessage.seq),
        @"version" : @(kMessageReplyVersion)
    };
    if (messageRootID) {
        [TUIChatDataProvider findMessages:@[ messageRootID ]
                                 callback:^(BOOL succ, NSString *_Nonnull error_message, NSArray *_Nonnull msgs) {
                                   if (succ) {
                                       if (msgs.count > 0) {
                                           V2TIMMessage *rootMsg = msgs.firstObject;
                                           [[TUIChatModifyMessageHelper defaultHelper] modifyMessage:rootMsg simpleCurrentContent:simpleCurrentContent];
                                       }
                                   }
                                 }];
    }
}

- (void)appendReferenceDataIfNeeded:(V2TIMMessage *)message {
    if (self.referenceData) {
        NSDictionary *dict = @{
            @"messageReply" : @{
                @"messageID" : self.referenceData.msgID ?: @"",
                @"messageAbstract" : [self.referenceData.msgAbstract ?: @"" getInternationalStringWithfaceContent],
                @"messageSender" : self.referenceData.sender ?: @"",
                @"messageType" : @(self.referenceData.type),
                @"messageTime" : @(self.referenceData.originMessage.timestamp ? [self.referenceData.originMessage.timestamp timeIntervalSince1970] : 0),
                @"messageSequence" : @(self.referenceData.originMessage.seq),
                @"version" : @(kMessageReplyVersion)
            }
        };
        NSError *error = nil;
        NSData *data = [NSJSONSerialization dataWithJSONObject:dict options:0 error:&error];
        if (error == nil) {
            message.cloudCustomData = data;
        }
        [self exitReplyAndReference:nil];
    }
}

- (void)inputBar:(TUIInputBar *)textView didSendVoice:(NSString *)path {
    NSURL *url = [NSURL fileURLWithPath:path];
    AVURLAsset *audioAsset = [AVURLAsset URLAssetWithURL:url options:nil];
    float duration = (float)CMTimeGetSeconds(audioAsset.duration);
    int formatDuration = duration > 59 ? 60 : duration + 1 ;
    V2TIMMessage *message = [[V2TIMManager sharedInstance] createSoundMessage:path duration:formatDuration];
    if (message && _delegate && [_delegate respondsToSelector:@selector(inputController:didSendMessage:)]) {
        [_delegate inputController:self didSendMessage:message];
    }
}

- (void)inputBarDidInputAt:(TUIInputBar *)textView {
    if (_delegate && [_delegate respondsToSelector:@selector(inputControllerDidInputAt:)]) {
        [_delegate inputControllerDidInputAt:self];
    }
}

- (void)inputBar:(TUIInputBar *)textView didDeleteAt:(NSString *)atText {
    if (_delegate && [_delegate respondsToSelector:@selector(inputController:didDeleteAt:)]) {
        [_delegate inputController:self didDeleteAt:atText];
    }
}

- (void)inputBarDidDeleteBackward:(TUIInputBar *)textView {
    if (textView.inputTextView.text.length == 0) {
        [self exitReplyAndReference:nil];
    }
}

- (void)inputTextViewShouldBeginTyping:(UITextView *)textView {
    if (_delegate && [_delegate respondsToSelector:@selector(inputControllerBeginTyping:)]) {
        [_delegate inputControllerBeginTyping:self];
    }
}

- (void)inputTextViewShouldEndTyping:(UITextView *)textView {
    if (_delegate && [_delegate respondsToSelector:@selector(inputControllerEndTyping:)]) {
        [_delegate inputControllerEndTyping:self];
    }
}

- (void)reset {
    if (_status == Input_Status_Input) {
        return;
    } else if (_status == Input_Status_Input_More) {
        [self hideMoreAnimation];
    } else if (_status == Input_Status_Input_Face) {
        [self hideFaceAnimation];
    }
    _status = Input_Status_Input;
    [_inputBar.inputTextView resignFirstResponder];
    
    [TUICore notifyEvent:TUICore_TUIChatNotify
                  subKey:TUICore_TUIChatNotify_KeyboardWillHideSubKey
                  object:nil
                   param:nil];
    
    if (_delegate && [_delegate respondsToSelector:@selector(inputController:didChangeHeight:)]) {
        CGFloat inputContainerBottom = [self getInputContainerBottom];
        [_delegate inputController:self didChangeHeight:inputContainerBottom + Bottom_SafeHeight];
    }
}

- (void)showReferencePreview:(TUIReferencePreviewData *)data {
    self.referenceData = data;
    [self.referencePreviewBar removeFromSuperview];
    [self.view addSubview:self.referencePreviewBar];
    self.inputBar.lineView.hidden = YES;

    self.referencePreviewBar.previewReferenceData = data;

    self.inputBar.mm_y = 0;

    self.referencePreviewBar.frame = CGRectMake(0, 0, self.view.bounds.size.width, TMenuView_Menu_Height);
    self.referencePreviewBar.mm_y = CGRectGetMaxY(self.inputBar.frame);

    // Set the default position to solve the UI confusion when the keyboard does not become the first responder
    if (self.delegate && [self.delegate respondsToSelector:@selector(inputController:didChangeHeight:)]) {
        [self.delegate inputController:self didChangeHeight:CGRectGetMaxY(self.inputBar.frame) + Bottom_SafeHeight + TMenuView_Menu_Height];
    }

    if (self.status == Input_Status_Input_Keyboard) {
        CGFloat keyboradHeight = self.keyboardFrame.size.height;
        if (self.delegate && [self.delegate respondsToSelector:@selector(inputController:didChangeHeight:)]) {
            [self.delegate inputController:self didChangeHeight:CGRectGetMaxY(self.referencePreviewBar.frame) + keyboradHeight];
        }
    } else if (self.status == Input_Status_Input_Face || self.status == Input_Status_Input_Talk) {
        [self.inputBar changeToKeyboard];
    } else {
        [self.inputBar.inputTextView becomeFirstResponder];
    }
}
- (void)showReplyPreview:(TUIReplyPreviewData *)data {
    self.replyData = data;
    [self.replyPreviewBar removeFromSuperview];
    [self.view addSubview:self.replyPreviewBar];
    self.inputBar.lineView.hidden = YES;

    self.replyPreviewBar.previewData = data;

    self.replyPreviewBar.frame = CGRectMake(0, 0, self.view.bounds.size.width, TMenuView_Menu_Height);
    self.inputBar.mm_y = CGRectGetMaxY(self.replyPreviewBar.frame);

    // Set the default position to solve the UI confusion when the keyboard does not become the first responder
    if (self.delegate && [self.delegate respondsToSelector:@selector(inputController:didChangeHeight:)]) {
        [self.delegate inputController:self didChangeHeight:CGRectGetMaxY(self.inputBar.frame) + Bottom_SafeHeight];
    }

    if (self.status == Input_Status_Input_Keyboard) {
        CGFloat keyboradHeight = self.keyboardFrame.size.height;
        if (self.delegate && [self.delegate respondsToSelector:@selector(inputController:didChangeHeight:)]) {
            [self.delegate inputController:self didChangeHeight:CGRectGetMaxY(self.inputBar.frame) + keyboradHeight];
        }
    } else if (self.status == Input_Status_Input_Face || self.status == Input_Status_Input_Talk) {
        [self.inputBar changeToKeyboard];
    } else {
        [self.inputBar.inputTextView becomeFirstResponder];
    }
}

- (void)exitReplyAndReference:(void (^__nullable)(void))finishedCallback {
    if (self.replyData == nil && self.referenceData == nil) {
        if (finishedCallback) {
            finishedCallback();
        }
        return;
    }
    self.replyData = nil;
    self.referenceData = nil;
    __weak typeof(self) weakSelf = self;
    [UIView animateWithDuration:0.25
        animations:^{
          weakSelf.replyPreviewBar.hidden = YES;
          weakSelf.referencePreviewBar.hidden = YES;
          weakSelf.inputBar.mm_y = 0;

          if (weakSelf.status == Input_Status_Input_Keyboard) {
              CGFloat keyboradHeight = weakSelf.keyboardFrame.size.height;
              if (weakSelf.delegate && [weakSelf.delegate respondsToSelector:@selector(inputController:didChangeHeight:)]) {
                  [weakSelf.delegate inputController:weakSelf didChangeHeight:CGRectGetMaxY(weakSelf.inputBar.frame) + keyboradHeight];
              }
          } else {
              if (weakSelf.delegate && [weakSelf.delegate respondsToSelector:@selector(inputController:didChangeHeight:)]) {
                  [weakSelf.delegate inputController:weakSelf didChangeHeight:CGRectGetMaxY(weakSelf.inputBar.frame) + Bottom_SafeHeight];
              }
          }
        }
        completion:^(BOOL finished) {
          [weakSelf.replyPreviewBar removeFromSuperview];
          [weakSelf.referencePreviewBar removeFromSuperview];
          weakSelf.replyPreviewBar = nil;
          weakSelf.referencePreviewBar = nil;
          [weakSelf hideFaceAnimation];
          weakSelf.inputBar.lineView.hidden = NO;
          if (finishedCallback) {
              finishedCallback();
          }
        }];
}

- (void)menuView:(TUIMenuView *)menuView didSelectItemAtIndex:(NSInteger)index {
    [self.faceSegementScrollView  setPageIndex:index];
}

- (void)menuViewDidSendMessage:(TUIMenuView *)menuView {
    NSString *text = [_inputBar getInput];
    if ([text isEqualToString:@""]) {
        return;
    }
    /**
     * Emoticon internationalization --> restore to actual Chinese key
     */
    NSString *content = [text getInternationalStringWithfaceContent];
    [_inputBar clearInput];
    V2TIMMessage *message = [[V2TIMManager sharedInstance] createTextMessage:content];
    [self appendReplyDataIfNeeded:message];
    [self appendReferenceDataIfNeeded:message];
    if (_delegate && [_delegate respondsToSelector:@selector(inputController:didSendMessage:)]) {
        [_delegate inputController:self didSendMessage:message];
    }
}

- (void)faceView:(TUIFaceView *)faceView scrollToFaceGroupIndex:(NSInteger)index {
    [self.menuView scrollToMenuIndex:index];
}

- (void)faceViewDidBackDelete:(TUIFaceView *)faceView {
    [_inputBar backDelete];
}

- (void)faceViewClickSendMessageBtn {
    [self menuViewDidSendMessage:self.menuView];
}

- (void)faceView:(TUIFaceView *)faceView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
    TUIFaceGroup *group = faceView.faceGroups[indexPath.section];
    TUIFaceCellData *face = group.faces[indexPath.row];
    if (group.isNeedAddInInputBar) {
        [_inputBar addEmoji:face];
        [self updateRecentMenuQueue:face.name];
    } else {
        if (face.name) {
            V2TIMMessage *message = [[V2TIMManager sharedInstance] createFaceMessage:group.groupIndex data:[face.name dataUsingEncoding:NSUTF8StringEncoding]];
            if (_delegate && [_delegate respondsToSelector:@selector(inputController:didSendMessage:)]) {
                [_delegate inputController:self didSendMessage:message];
            }
        }
    }
}

- (void)updateRecentMenuQueue:(NSString *)faceName {
    id<TUIEmojiMeditorProtocol> service = [[TIMCommonMediator share] getObject:@protocol(TUIEmojiMeditorProtocol)];
    return [service updateRecentMenuQueue:faceName];
}

#pragma mark - more view delegate
- (void)moreView:(TUIMoreView *)moreView didSelectMoreCell:(TUIInputMoreCell *)cell {
    if (_delegate && [_delegate respondsToSelector:@selector(inputController:didSelectMoreCell:)]) {
        [_delegate inputController:self didSelectMoreCell:cell];
    }
}

#pragma mark - lazy load

- (TUIFaceSegementScrollView *)faceSegementScrollView {
    if(!_faceSegementScrollView) {
        _faceSegementScrollView = [[TUIFaceSegementScrollView alloc]
            initWithFrame:CGRectMake(0,
                                     _inputBar.frame.origin.y + _inputBar.frame.size.height,
                                     self.view.frame.size.width,
                                     TFaceView_Height)];
        [_faceSegementScrollView setItems:[TIMConfig defaultConfig].faceGroups delegate:self];
    }
    return _faceSegementScrollView;
}
- (TUIMoreView *)moreView {
    if (!_moreView) {
        _moreView =
            [[TUIMoreView alloc] initWithFrame:CGRectMake(0,
                                                          _inputBar.frame.origin.y + _inputBar.frame.size.height,
                                                          _faceSegementScrollView.frame.size.width,
                                                          0)];
        _moreView.delegate = self;
    }
    return _moreView;
}

- (TUIMenuView *)menuView {
    if (!_menuView) {
        _menuView = [[TUIMenuView alloc]
            initWithFrame:CGRectMake(16, _inputBar.frame.origin.y + _inputBar.frame.size.height, self.view.frame.size.width - 32, TMenuView_Menu_Height)];
        _menuView.delegate = self;

        TIMConfig *config = [TIMConfig defaultConfig];
        NSMutableArray *menus = [NSMutableArray array];
        for (NSInteger i = 0; i < config.faceGroups.count; ++i) {
            TUIFaceGroup *group = config.faceGroups[i];
            TUIMenuCellData *data = [[TUIMenuCellData alloc] init];
            data.path = group.menuPath;
            data.isSelected = NO;
            if (i == 0) {
                data.isSelected = YES;
            }
            [menus addObject:data];
        }
        [_menuView setData:menus];
    }
    return _menuView;
}

- (TUIReplyPreviewBar *)replyPreviewBar {
    if (_replyPreviewBar == nil) {
        _replyPreviewBar = [[TUIReplyPreviewBar alloc] init];
        __weak typeof(self) weakSelf = self;
        _replyPreviewBar.onClose = ^{
          __strong typeof(weakSelf) strongSelf = weakSelf;
          [strongSelf exitReplyAndReference:nil];
        };
    }
    return _replyPreviewBar;
}

- (TUIReferencePreviewBar *)referencePreviewBar {
    if (_referencePreviewBar == nil) {
        _referencePreviewBar = [[TUIReferencePreviewBar alloc] init];
        __weak typeof(self) weakSelf = self;
        _referencePreviewBar.onClose = ^{
          __strong typeof(weakSelf) strongSelf = weakSelf;
          [strongSelf exitReplyAndReference:nil];
        };
    }
    return _referencePreviewBar;
}

- (CGFloat)getInputContainerBottom {
    CGFloat inputHeight = CGRectGetMaxY(_inputBar.frame);
    if (_referencePreviewBar) {
        inputHeight = CGRectGetMaxY(_referencePreviewBar.frame);
    }
    return inputHeight;
}

@end
