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

#import "TUIInputBar_Minimalist.h"
#import <TIMCommon/NSString+TUIEmoji.h>
#import <TIMCommon/NSTimer+TUISafe.h>
#import <TIMCommon/TIMDefine.h>
#import <TUICore/TUICore.h>
#import <TUICore/TUIDarkModel.h>
#import <TUICore/TUIGlobalization.h>
#import <TUICore/TUITool.h>
#import <TUICore/UIView+TUILayout.h>
#import "ReactiveObjC/ReactiveObjC.h"
#import "TUIAudioRecorder.h"
#import "TUIChatConfig.h"

@interface TUIInputBar_Minimalist () <UITextViewDelegate, TUIAudioRecorderDelegate>

@property(nonatomic, strong) NSDate *recordStartTime;
@property(nonatomic, strong) TUIAudioRecorder *recorder;
@property(nonatomic, strong) NSTimer *recordTimer;

@property(nonatomic, assign) BOOL isFocusOn;
@property(nonatomic, strong) NSTimer *sendTypingStatusTimer;
@property(nonatomic, assign) BOOL allowSendTypingStatusByChangeWord;
@end

@implementation TUIInputBar_Minimalist

- (void)dealloc {
    if (_sendTypingStatusTimer) {
        [_sendTypingStatusTimer invalidate];
        _sendTypingStatusTimer = nil;
    }
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [self setupViews];
        [self defaultLayout];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onThemeChanged) name:TUIDidApplyingThemeChangedNotfication object:nil];
    }
    return self;
}

- (void)setupViews {
    self.backgroundColor = RGBA(255, 255, 255, 1);

    _lineView = [[UIView alloc] init];
    _lineView.backgroundColor = TIMCommonDynamicColor(@"separator_color", @"#FFFFFF");

    _moreButton = [[UIButton alloc] init];
    [_moreButton addTarget:self action:@selector(clickMoreBtn:) forControlEvents:UIControlEventTouchUpInside];
    [_moreButton setImage:[[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"TypeSelectorBtnHL_Black")]
                 forState:UIControlStateNormal];
    [_moreButton setImage:[[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"TypeSelectorBtnHL_Black")]
                 forState:UIControlStateHighlighted];
    [self addSubview:_moreButton];

    _inputTextView = [[TUIResponderTextView_Minimalist alloc] init];
    _inputTextView.delegate = self;
    [_inputTextView setFont:kTUIInputNoramlFont];
    _inputTextView.backgroundColor = TUIChatDynamicColor(@"chat_input_bg_color", @"#FFFFFF");
    _inputTextView.textColor = TUIChatDynamicColor(@"chat_input_text_color", @"#000000");
    UIEdgeInsets ei = UIEdgeInsetsMake(kScale390(9), kScale390(16), kScale390(9), kScale390(30));
    _inputTextView.textContainerInset = rtlEdgeInsetsWithInsets(ei);
    _inputTextView.textAlignment = isRTL()?NSTextAlignmentRight: NSTextAlignmentLeft;
    [_inputTextView setReturnKeyType:UIReturnKeySend];
    [self addSubview:_inputTextView];

    _keyboardButton = [[UIButton alloc] init];
    [_keyboardButton addTarget:self action:@selector(clickKeyboardBtn:) forControlEvents:UIControlEventTouchUpInside];
    [_keyboardButton setImage:TUIChatBundleThemeImage(@"chat_ToolViewKeyboard_img", @"ToolViewKeyboard") forState:UIControlStateNormal];
    [_keyboardButton setImage:TUIChatBundleThemeImage(@"chat_ToolViewKeyboardHL_img", @"ToolViewKeyboardHL") forState:UIControlStateHighlighted];
    _keyboardButton.hidden = YES;
    [self addSubview:_keyboardButton];

    _faceButton = [[UIButton alloc] init];
    [_faceButton addTarget:self action:@selector(clickFaceBtn:) forControlEvents:UIControlEventTouchUpInside];
    [_faceButton setImage:[[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"ToolViewEmotion")] forState:UIControlStateNormal];
    [_faceButton setImage:[[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"ToolViewEmotion")]
                 forState:UIControlStateHighlighted];
    [self addSubview:_faceButton];

    _micButton = [[UIButton alloc] init];
    [_micButton addTarget:self action:@selector(recordBtnDown:) forControlEvents:UIControlEventTouchDown];
    [_micButton addTarget:self action:@selector(recordBtnUp:) forControlEvents:UIControlEventTouchUpInside];
    [_micButton addTarget:self action:@selector(recordBtnCancel:) forControlEvents:UIControlEventTouchUpOutside | UIControlEventTouchCancel];
    [_micButton addTarget:self action:@selector(recordBtnDragExit:) forControlEvents:UIControlEventTouchDragExit];
    [_micButton addTarget:self action:@selector(recordBtnDragEnter:) forControlEvents:UIControlEventTouchDragEnter];
    [_micButton setImage:[[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"ToolViewInputVoice")]
                forState:UIControlStateNormal];
    [self addSubview:_micButton];

    _cameraButton = [[UIButton alloc] init];
    [_cameraButton addTarget:self action:@selector(clickCameraBtn:) forControlEvents:UIControlEventTouchUpInside];
    [_cameraButton setImage:[[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"ToolViewInputCamera")]
                   forState:UIControlStateNormal];
    [_cameraButton setImage:[[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"ToolViewInputCamera")]
                   forState:UIControlStateHighlighted];
    [self addSubview:_cameraButton];

    [self initRecordView];
}

- (void)initRecordView {
    _recordView = [[UIView alloc] init];
    _recordView.backgroundColor = RGBA(255, 255, 255, 1);
    _recordView.hidden = YES;
    [self addSubview:_recordView];

    _recordDeleteView = [[UIImageView alloc] init];
    [_recordView addSubview:_recordDeleteView];

    _recordBackgroudView = [[UIView alloc] init];
    [_recordView addSubview:_recordBackgroudView];

    _recordTimeLabel = [[UILabel alloc] init];
    _recordTimeLabel.textColor = [UIColor whiteColor];
    _recordTimeLabel.font = [UIFont systemFontOfSize:14];
    [_recordView addSubview:_recordTimeLabel];

    _recordAnimateViews = [NSMutableArray array];
    for (int i = 0; i < 6; i++) {
        UIImageView *recordAnimateView = [[UIImageView alloc] init];
        [recordAnimateView setImage:[[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"voice_record_animation")]];
        [_recordView addSubview:recordAnimateView];
        [_recordAnimateViews addObject:recordAnimateView];
    }

    _recordAnimateCoverView = [[UIImageView alloc] init];
    [_recordView addSubview:_recordAnimateCoverView];

    _recordTipsView = [[UIView alloc] init];
    _recordTipsView.backgroundColor = [UIColor whiteColor];
    _recordTipsView.frame = CGRectMake(0, -56, Screen_Width, 56);
    [_recordView addSubview:_recordTipsView];

    _recordTipsLabel = [[UILabel alloc] init];
    _recordTipsLabel.textColor = RGBA(102, 102, 102, 1);
    _recordTipsLabel.textColor = [UIColor blackColor];
    _recordTipsLabel.text = TIMCommonLocalizableString(TUIKitInputRecordTipsTitle);
    _recordTipsLabel.textAlignment = NSTextAlignmentCenter;
    _recordTipsLabel.font = [UIFont systemFontOfSize:14];
    _recordTipsLabel.frame = CGRectMake(0, 10, Screen_Width, 22);
    [_recordTipsView addSubview:_recordTipsLabel];

    [self setRecordStatus:TUIRecordStatus_Init];
}

- (void)setRecordStatus:(TUIRecordStatus)status {
    switch (status) {
        case TUIRecordStatus_Init:
        case TUIRecordStatus_Record:
        case TUIRecordStatus_Cancel: {
            _recordDeleteView.frame = CGRectMake(kScale390(16), _recordDeleteView.mm_y, 24, 24);
            if (isRTL()){
                [_recordDeleteView resetFrameToFitRTL];
            }
            _recordDeleteView.image = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"voice_record_delete")];
            _recordBackgroudView.backgroundColor = RGBA(20, 122, 255, 1);
            _recordAnimateCoverView.backgroundColor = _recordBackgroudView.backgroundColor;
            _recordAnimateCoverView.frame = self.recordAnimateCoverViewFrame;
            _recordTimeLabel.text = @"0:00";
            _recordTipsLabel.text = TIMCommonLocalizableString(TUIKitInputRecordTipsTitle);

            if (TUIRecordStatus_Record == status) {
                _recordView.hidden = NO;
            } else {
                _recordView.hidden = YES;
            }
        } break;
        case TUIRecordStatus_Delete: {
            _recordDeleteView.frame = CGRectMake(0, _recordDeleteView.mm_y, 20, 24);
            if (isRTL()){
                [_recordDeleteView resetFrameToFitRTL];
            }
            _recordDeleteView.image = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"voice_record_delete_ready")];
            _recordBackgroudView.backgroundColor = RGBA(255, 88, 76, 1);
            _recordAnimateCoverView.backgroundColor = _recordBackgroudView.backgroundColor;
            _recordTipsLabel.text = TIMCommonLocalizableString(TUIKitInputRecordCancelTipsTitle);

            _recordView.hidden = NO;
        } break;
        default:
            break;
    }
}

- (void)applyBorderTheme {
    if (_recordBackgroudView) {
        [_recordBackgroudView.layer setMasksToBounds:YES];
        [_recordBackgroudView.layer setCornerRadius:_recordBackgroudView.mm_h / 2.0];
    }

    if (_inputTextView) {
        [_inputTextView.layer setMasksToBounds:YES];
        [_inputTextView.layer setCornerRadius:_inputTextView.mm_h / 2.0];
        [_inputTextView.layer setBorderWidth:0.5f];
        [_inputTextView.layer setBorderColor:RGBA(221, 221, 221, 1).CGColor];
    }
}
- (void)defaultLayout {
    _lineView.frame = CGRectMake(0, 0, Screen_Width, TLine_Heigh);

    CGFloat iconSize = 24;
    _moreButton.frame = CGRectMake(kScale390(16), kScale390(13), iconSize, iconSize);
    _cameraButton.frame = CGRectMake(Screen_Width - kScale390(16) - iconSize, 13, iconSize, iconSize);
    _micButton.frame = CGRectMake(Screen_Width - kScale390(56) - iconSize, 13, iconSize, iconSize);
    
    CGFloat faceSize = 19;
    _faceButton.frame = CGRectMake(_micButton.mm_x - kScale390(50), 15, faceSize, faceSize);
    
    _keyboardButton.frame = _faceButton.frame;
    _inputTextView.frame = CGRectMake(kScale390(56), 7, Screen_Width - kScale390(152), 36);

    _recordView.frame = CGRectMake(0, _inputTextView.mm_y, self.mm_w, _inputTextView.mm_h);
    _recordDeleteView.frame = CGRectMake(kScale390(16), 4, iconSize, iconSize);
    _recordBackgroudView.frame = CGRectMake(kScale390(54), 0, self.mm_w - kScale390(70), _recordView.mm_h);
    _recordTimeLabel.frame = CGRectMake(kScale390(70), kScale390(7), 32, 22);

    CGFloat animationStartX = kScale390(112);
    CGFloat animationY = 8;
    CGFloat animationSize = 20;
    CGFloat animationSpace = kScale390(8);
    CGFloat animationCoverWidth = 0;
    for (int i = 0; i < self.recordAnimateViews.count; ++i) {
        UIView *animationView = self.recordAnimateViews[i];
        animationView.frame = CGRectMake(animationStartX + (animationSize + animationSpace) * i, animationY, animationSize, animationSize);
        animationCoverWidth = (animationSize + animationSpace) * (i + 1);
    }
    _recordAnimateCoverViewFrame = CGRectMake(animationStartX, animationY, animationCoverWidth, animationSize);
    _recordAnimateCoverView.frame = self.recordAnimateCoverViewFrame;
    [self applyBorderTheme];
    
    if(isRTL()) {
        for (UIView *subviews in self.subviews) {
            [subviews resetFrameToFitRTL];
        }
        for (UIView *subview in _recordView.subviews) {
            [subview resetFrameToFitRTL];
        }
    }
}

- (void)layoutButton:(CGFloat)height {
    CGRect frame = self.frame;
    CGFloat offset = height - frame.size.height;
    frame.size.height = height;
    self.frame = frame;

    if (_delegate && [_delegate respondsToSelector:@selector(inputBar:didChangeInputHeight:)]) {
        [_delegate inputBar:self didChangeInputHeight:offset];
    }
}

- (void)clickCameraBtn:(UIButton *)sender {
    _micButton.hidden = NO;
    _keyboardButton.hidden = YES;
    _inputTextView.hidden = NO;
    _faceButton.hidden = NO;
    [self setRecordStatus:TUIRecordStatus_Cancel];
    if (_delegate && [_delegate respondsToSelector:@selector(inputBarDidTouchCamera:)]) {
        [_delegate inputBarDidTouchCamera:self];
    }
}

- (void)clickKeyboardBtn:(UIButton *)sender {
    _micButton.hidden = NO;
    _keyboardButton.hidden = YES;
    _inputTextView.hidden = NO;
    _faceButton.hidden = NO;
    [self setRecordStatus:TUIRecordStatus_Cancel];
    [self layoutButton:_inputTextView.frame.size.height + 2 * TTextView_Margin];
    if (_delegate && [_delegate respondsToSelector:@selector(inputBarDidTouchKeyboard:)]) {
        [_delegate inputBarDidTouchKeyboard:self];
    }
}

- (void)clickFaceBtn:(UIButton *)sender {
    _micButton.hidden = NO;
    _faceButton.hidden = YES;
    _keyboardButton.hidden = NO;
    _inputTextView.hidden = NO;
    [self setRecordStatus:TUIRecordStatus_Cancel];
    if (_delegate && [_delegate respondsToSelector:@selector(inputBarDidTouchFace:)]) {
        [_delegate inputBarDidTouchFace:self];
    }
    _keyboardButton.frame = _faceButton.frame;
}

- (void)clickMoreBtn:(UIButton *)sender {
    if (_delegate && [_delegate respondsToSelector:@selector(inputBarDidTouchMore:)]) {
        [_delegate inputBarDidTouchMore:self];
    }
}

- (void)recordBtnDown:(UIButton *)sender {
    [self.recorder record];
}

- (void)recordBtnUp:(UIButton *)sender {
    NSTimeInterval interval = [[NSDate date] timeIntervalSinceDate:_recordStartTime];
    if (interval < 1) {
        [self.recorder cancel];
    } else if (interval > 60) {
        [self.recorder cancel];
    } else {
        [self.recorder stop];
        NSString *path = self.recorder.recordedFilePath;
        if (path) {
            if (_delegate && [_delegate respondsToSelector:@selector(inputBar:didSendVoice:)]) {
                [_delegate inputBar:self didSendVoice:path];
            }
        }
    }
    [self setRecordStatus:TUIRecordStatus_Cancel];
}

- (void)recordBtnCancel:(UIGestureRecognizer *)gesture {
    [self setRecordStatus:TUIRecordStatus_Cancel];
    [self.recorder cancel];
}

- (void)recordBtnDragExit:(UIButton *)sender {
    [self setRecordStatus:TUIRecordStatus_Delete];
}

- (void)recordBtnDragEnter:(UIButton *)sender {
    [self setRecordStatus:TUIRecordStatus_Record];
}

- (void)showHapticFeedback {
    if (@available(iOS 10.0, *)) {
        dispatch_async(dispatch_get_main_queue(), ^{
          UIImpactFeedbackGenerator *generator = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleMedium];
          [generator prepare];
          [generator impactOccurred];
        });

    } else {
        // Fallback on earlier versions
    }
}
#pragma mark - talk

- (void)textViewDidBeginEditing:(UITextView *)textView {
    self.keyboardButton.hidden = YES;
    self.micButton.hidden = NO;
    self.faceButton.hidden = NO;

    self.isFocusOn = YES;
    self.allowSendTypingStatusByChangeWord = YES;

    __weak typeof(self) weakSelf = self;
    self.sendTypingStatusTimer = [NSTimer tui_scheduledTimerWithTimeInterval:4
                                                                     repeats:YES
                                                                       block:^(NSTimer *_Nonnull timer) {
                                                                         __strong typeof(weakSelf) strongSelf = weakSelf;
                                                                         strongSelf.allowSendTypingStatusByChangeWord = YES;
                                                                       }];

    if (self.isFocusOn && [textView.textStorage tui_getPlainString].length > 0) {
        if (_delegate && [_delegate respondsToSelector:@selector(inputTextViewShouldBeginTyping:)]) {
            [_delegate inputTextViewShouldBeginTyping:textView];
        }
    }
}

- (void)textViewDidEndEditing:(UITextView *)textView {
    self.isFocusOn = NO;
    if (_delegate && [_delegate respondsToSelector:@selector(inputTextViewShouldEndTyping:)]) {
        [_delegate inputTextViewShouldEndTyping:textView];
    }
}

- (void)textViewDidChange:(UITextView *)textView {
    if (self.allowSendTypingStatusByChangeWord && self.isFocusOn && [textView.textStorage tui_getPlainString].length > 0) {
        if (_delegate && [_delegate respondsToSelector:@selector(inputTextViewShouldBeginTyping:)]) {
            self.allowSendTypingStatusByChangeWord = NO;
            [_delegate inputTextViewShouldBeginTyping:textView];
        }
    }

    if (self.isFocusOn && [textView.textStorage tui_getPlainString].length == 0) {
        if (_delegate && [_delegate respondsToSelector:@selector(inputTextViewShouldEndTyping:)]) {
            [_delegate inputTextViewShouldEndTyping:textView];
        }
    }
    if (self.inputBarTextChanged) {
        self.inputBarTextChanged(_inputTextView);
    }
    CGSize size = [_inputTextView sizeThatFits:CGSizeMake(_inputTextView.frame.size.width, TTextView_TextView_Height_Max)];
    CGFloat oldHeight = _inputTextView.frame.size.height;
    CGFloat newHeight = size.height;

    if (newHeight > TTextView_TextView_Height_Max) {
        newHeight = TTextView_TextView_Height_Max;
    }
    if (newHeight < TTextView_TextView_Height_Min) {
        newHeight = TTextView_TextView_Height_Min;
    }
    if (oldHeight == newHeight) {
        return;
    }

    __weak typeof(self) ws = self;
    [UIView animateWithDuration:0.3
                     animations:^{
                       CGRect textFrame = ws.inputTextView.frame;
                       textFrame.size.height += newHeight - oldHeight;
                       ws.inputTextView.frame = textFrame;
                       [ws layoutButton:newHeight + 2 * TTextView_Margin];
                     }];
}

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    if ([text tui_containsString:@"["] && [text tui_containsString:@"]"]) {
        NSRange selectedRange = textView.selectedRange;
        if (selectedRange.length > 0) {
            [textView.textStorage deleteCharactersInRange:selectedRange];
        }

        NSMutableAttributedString *textChange = [text getAdvancedFormatEmojiStringWithFont:kTUIInputNoramlFont
                                                                                 textColor:kTUIInputNormalTextColor
                                                                            emojiLocations:nil];
        [textView.textStorage insertAttributedString:textChange atIndex:textView.textStorage.length];
        dispatch_async(dispatch_get_main_queue(), ^{
          self.inputTextView.selectedRange = NSMakeRange(self.inputTextView.textStorage.length + 1, 0);
        });
        return NO;
    }

    if ([text isEqualToString:@"\n"]) {
        if (_delegate && [_delegate respondsToSelector:@selector(inputBar:didSendText:)]) {
            NSString *sp = [[textView.textStorage tui_getPlainString] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
            if (sp.length == 0) {
                UIAlertController *ac = [UIAlertController alertControllerWithTitle:TIMCommonLocalizableString(TUIKitInputBlankMessageTitle)
                                                                            message:nil
                                                                     preferredStyle:UIAlertControllerStyleAlert];
                [ac tuitheme_addAction:[UIAlertAction actionWithTitle:TIMCommonLocalizableString(Confirm) style:UIAlertActionStyleDefault handler:nil]];
                [self.mm_viewController presentViewController:ac animated:YES completion:nil];
            } else {
                [_delegate inputBar:self didSendText:[textView.textStorage tui_getPlainString]];
                [self clearInput];
            }
        }
        return NO;
    } else if ([text isEqualToString:@""]) {
        if (textView.textStorage.length > range.location) {
            // Delete the @ message like @xxx at one time
            NSAttributedString *lastAttributedStr = [textView.textStorage attributedSubstringFromRange:NSMakeRange(range.location, 1)];
            NSString *lastStr = [lastAttributedStr tui_getPlainString];
            if (lastStr && lastStr.length > 0 && [lastStr characterAtIndex:0] == ' ') {
                NSUInteger location = range.location;
                NSUInteger length = range.length;

                // corresponds to ascii code
                int at = 64;
                // (space) ascii
                // Space (space) corresponding ascii code
                int space = 32;

                while (location != 0) {
                    location--;
                    length++;
                    // Convert characters to ascii code, copy to int, avoid out of bounds
                    int c = (int)[[[textView.textStorage attributedSubstringFromRange:NSMakeRange(location, 1)] tui_getPlainString] characterAtIndex:0];

                    if (c == at) {
                        NSString *atText = [[textView.textStorage attributedSubstringFromRange:NSMakeRange(location, length)] tui_getPlainString];
                        UIFont *textFont = kTUIInputNoramlFont;
                        NSAttributedString *spaceString = [[NSAttributedString alloc] initWithString:@"" attributes:@{NSFontAttributeName : textFont}];
                        [textView.textStorage replaceCharactersInRange:NSMakeRange(location, length) withAttributedString:spaceString];
                        if (self.delegate && [self.delegate respondsToSelector:@selector(inputBar:didDeleteAt:)]) {
                            [self.delegate inputBar:self didDeleteAt:atText];
                        }
                        return NO;
                    } else if (c == space) {
                        // Avoid "@nickname Hello, nice to meet you (space) "" Press del after a space to over-delete to @
                        break;
                    }
                }
            }
        }
    }
    // Monitor the input of @ character, including full-width/half-width
    else if ([text isEqualToString:@"@"] || [text isEqualToString:@"＠"]) {
        if (self.delegate && [self.delegate respondsToSelector:@selector(inputBarDidInputAt:)]) {
            [self.delegate inputBarDidInputAt:self];
        }
        return NO;
    }
    return YES;
}

- (void)onDeleteBackward:(TUIResponderTextView_Minimalist *)textView {
    if (self.delegate && [self.delegate respondsToSelector:@selector(inputBarDidDeleteBackward:)]) {
        [self.delegate inputBarDidDeleteBackward:self];
    }
}

- (void)clearInput {
    [_inputTextView.textStorage deleteCharactersInRange:NSMakeRange(0, _inputTextView.textStorage.length)];
    [self textViewDidChange:_inputTextView];
}

- (NSString *)getInput {
    return [_inputTextView.textStorage tui_getPlainString];
}

- (void)addEmoji:(TUIFaceCellData *)emoji {
    // Create emoji attachment
    TUIEmojiTextAttachment *emojiTextAttachment = [[TUIEmojiTextAttachment alloc] init];
    emojiTextAttachment.faceCellData = emoji;

    // Set tag and image
    emojiTextAttachment.emojiTag = emoji.name;
    emojiTextAttachment.image = [[TUIImageCache sharedInstance] getFaceFromCache:emoji.path];

    // Set emoji size
    emojiTextAttachment.emojiSize = kTIMDefaultEmojiSize;
    NSAttributedString *str = [NSAttributedString attributedStringWithAttachment:emojiTextAttachment];

    NSRange selectedRange = _inputTextView.selectedRange;
    if (selectedRange.length > 0) {
        [_inputTextView.textStorage deleteCharactersInRange:selectedRange];
    }
    // Insert emoji image
    [_inputTextView.textStorage insertAttributedString:str atIndex:_inputTextView.selectedRange.location];

    _inputTextView.selectedRange = NSMakeRange(_inputTextView.selectedRange.location + 1, 0);
    [self resetTextStyle];

    if (_inputTextView.contentSize.height > TTextView_TextView_Height_Max) {
        float offset = _inputTextView.contentSize.height - _inputTextView.frame.size.height;
        [_inputTextView scrollRectToVisible:CGRectMake(0, offset, _inputTextView.frame.size.width, _inputTextView.frame.size.height) animated:YES];
    }
    [self textViewDidChange:_inputTextView];
}

- (void)resetTextStyle {
    // After changing text selection, should reset style.
    NSRange wholeRange = NSMakeRange(0, _inputTextView.textStorage.length);

    [_inputTextView.textStorage removeAttribute:NSFontAttributeName range:wholeRange];

    [_inputTextView.textStorage removeAttribute:NSForegroundColorAttributeName range:wholeRange];

    [_inputTextView.textStorage addAttribute:NSForegroundColorAttributeName value:kTUIInputNormalTextColor range:wholeRange];

    [_inputTextView.textStorage addAttribute:NSFontAttributeName value:kTUIInputNoramlFont range:wholeRange];
    [_inputTextView setFont:kTUIInputNoramlFont];
    _inputTextView.textAlignment = isRTL()?NSTextAlignmentRight: NSTextAlignmentLeft;

}

- (void)backDelete {
    if (_inputTextView.textStorage.length > 0) {
        [_inputTextView.textStorage deleteCharactersInRange:NSMakeRange(_inputTextView.textStorage.length - 1, 1)];
        [self textViewDidChange:_inputTextView];
    }
}

- (void)updateTextViewFrame {
    [self textViewDidChange:[UITextView new]];
}

- (void)changeToKeyboard {
    [self clickKeyboardBtn:self.keyboardButton];
}

- (void)onThemeChanged {
    [self applyBorderTheme];
}

- (void)addDraftToInputBar:(NSAttributedString *)draft {
    [self addWordsToInputBar:draft];
}

- (void)addWordsToInputBar:(NSAttributedString *)words {
    NSRange selectedRange = self.inputTextView.selectedRange;
    if (selectedRange.length > 0) {
        [self.inputTextView.textStorage deleteCharactersInRange:selectedRange];
    }
    // Insert words
    [self.inputTextView.textStorage insertAttributedString:words atIndex:self.inputTextView.selectedRange.location];

    self.inputTextView.selectedRange = NSMakeRange(self.inputTextView.textStorage.length + 1, 0);

    [self resetTextStyle];

    [self updateTextViewFrame];
}
#pragma mark - TUIAudioRecorderDelegate
- (void)audioRecorder:(TUIAudioRecorder *)recorder didCheckPermission:(BOOL)isGranted isFirstTime:(BOOL)isFirstTime {
    if (isFirstTime) {
        if (!isGranted) {
            [self showRequestMicAuthorizationAlert];
        }
        return;
    }

    [self setRecordStatus:TUIRecordStatus_Record];
    _recordStartTime = [NSDate date];
    [self showHapticFeedback];
}

- (void)showRequestMicAuthorizationAlert {
    UIAlertController *ac = [UIAlertController alertControllerWithTitle:TIMCommonLocalizableString(TUIKitInputNoMicTitle)
                                                                message:TIMCommonLocalizableString(TUIKitInputNoMicTips)
                                                         preferredStyle:UIAlertControllerStyleAlert];
    [ac tuitheme_addAction:[UIAlertAction actionWithTitle:TIMCommonLocalizableString(TUIKitInputNoMicOperateLater) style:UIAlertActionStyleCancel handler:nil]];
    [ac tuitheme_addAction:[UIAlertAction actionWithTitle:TIMCommonLocalizableString(TUIKitInputNoMicOperateEnable)
                                                    style:UIAlertActionStyleDefault
                                                  handler:^(UIAlertAction *_Nonnull action) {
                                                    UIApplication *app = [UIApplication sharedApplication];
                                                    NSURL *settingsURL = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
                                                    if ([app canOpenURL:settingsURL]) {
                                                        [app openURL:settingsURL];
                                                    }
                                                  }]];
    dispatch_async(dispatch_get_main_queue(), ^{
      [self.mm_viewController presentViewController:ac animated:YES completion:nil];
    });
}

- (void)audioRecorder:(TUIAudioRecorder *)recorder didRecordTimeChanged:(NSTimeInterval)time {
    float maxDuration = MIN(59.7, [TUIChatConfig defaultConfig].maxAudioRecordDuration);
    NSInteger seconds = maxDuration - time;
    _recordTimeLabel.text = [NSString stringWithFormat:@"%d:%.2d", (int)time / 60, (int)time % 60 + 1];

    CGFloat width = _recordAnimateCoverViewFrame.size.width;
    int interval_ms = (int)(time * 1000);
    int runloop_ms = 5 * 1000;
    CGFloat offset_x = width * (interval_ms % runloop_ms) / runloop_ms;
    _recordAnimateCoverView.frame = CGRectMake(_recordAnimateCoverViewFrame.origin.x + offset_x, _recordAnimateCoverViewFrame.origin.y, width - offset_x,
                                               _recordAnimateCoverViewFrame.size.height);
    if (time > maxDuration) {
        [self.recorder stop];
        [self setRecordStatus:TUIRecordStatus_Cancel];
        NSString *path = self.recorder.recordedFilePath;
        if (path) {
            if (_delegate && [_delegate respondsToSelector:@selector(inputBar:didSendVoice:)]) {
                [_delegate inputBar:self didSendVoice:path];
            }
        }
    }
}

#pragma mark - Getter
- (TUIAudioRecorder *)recorder {
    if (!_recorder) {
        _recorder = [[TUIAudioRecorder alloc] init];
        _recorder.delegate = self;
    }
    return _recorder;
}

@end
