//
//  EGInputLimit.m
//  EGCommon
//
//  Created by donglyu on 2020/4/20.
//  Copyright © 2020 Company. All rights reserved.
//

#import "EGInputLimit.h"
#import <objc/runtime.h>

NSString *const WSInputLimitOnlyNumbersPattern = @"[0-9]+";
NSString *const WSInputLimitOnlyChinesePattern = @"[\u4e00-\u9fa5]+";
NSString *const WSInputLimitOnlyLetterPattern = @"[A-Za-z]+";
/// 处理emoji符号，数值、各语言字母不会处理
NSString *const WSInputLimitFilterEmojiPattern = @"[\U0001f0a0-\U0001f0ff\U0001f170-\U0001f19a\U0001f300-\U0001faff\u2190-\u21FF\u2300-\u23FF\u2500-\u26FF\u2700-\u27BF\u27F0-\u27FF\u2900-\u297F\u2B00-\u2BFF]+";
// 下方是旧正则、部分其他语言的文案不通过，eg: évaluation
//@"[^\\u0020-\\u007E\\u00A0-\\u00BE\\u2E80-\\uA4CF\\uF900-\\uFAFF\\uFE30-\\uFE4F\\uFF00-\\uFFEF\\u0080-\\u009F\\u2000-\\u201f\r\n]";

static inline NSString *WSInputLimitDecimaStylePattern(NSInteger decimalPlace) {
    return [NSString stringWithFormat:@"([1-9][0-9]*|0)(\\.)?([0-9]{1,%ld})?", MAX(1, decimalPlace)];
}


@interface EGInputLimit()
@property (nonatomic, weak, readonly) UITextField *textField;
@property (nonatomic, weak, readonly) UITextView *textView;
@end

@implementation EGInputLimit

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (instancetype)initWithTextField:(UITextField *)textField {
    if (self = [super init]) {
        _textField = textField;
        
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textFieldTextDidChange:) name:UITextFieldTextDidChangeNotification object:_textField];
    }
    return self;
}

- (instancetype)initWithTextView:(UITextView *)textView {
    if (self = [super init]) {
        _textView = textView;
        
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textViewTextDidChange:) name:UITextViewTextDidChangeNotification object:_textView];
    }
    return self;
}

#pragma mark textFieldTextDidChange
- (void)textFieldTextDidChange:(NSNotification *)notifi {
    if (_disable) {
        return;
    }
    UITextField *textField = notifi.object;
    if (textField == _textField) {
        UITextRange *markedTextRange = [_textField markedTextRange];
        UITextPosition *position = [_textField positionFromPosition:markedTextRange.start offset:0];
        if (markedTextRange && position) {
            return;
        }
        
        NSString *result = [self handleText:_textField.text];
        UITextRange* selectedRange = _textField.selectedTextRange;
        _textField.text = result;
        _textField.selectedTextRange = selectedRange;
    }
}

#pragma mark textViewTextDidChange
- (void)textViewTextDidChange:(NSNotification *)notifi {
    if (_disable) {
        return;
    }
    UITextView *textView = notifi.object;
    if (textView == _textView) {
        UITextRange *markedTextRange = [_textView markedTextRange];
        UITextPosition *position = [_textView positionFromPosition:markedTextRange.start offset:0];
        if (markedTextRange && position) {
            return;
        }
        
        NSString *result = [self handleText:_textView.text];
        NSRange selectedRange = _textView.selectedRange;
        _textView.text = result;
        _textView.selectedRange = NSMakeRange(selectedRange.location, 0);
    }
}

- (NSString *)handleText:(NSString *)text {
    if (_onlyNumbers) {
        NSString *result = [self subStringFromText:text withPattern:WSInputLimitOnlyNumbersPattern];
        return result;
    }
    
    if (_onlyChinese) {
        NSString *result = [self subStringFromText:text withPattern:WSInputLimitOnlyChinesePattern];
        return result;
    }
    
    if (_onlyLetter) {
        NSString *result = [self subStringFromText:text withPattern:WSInputLimitOnlyLetterPattern];
        return result;
    }
    
    if (_decimaStyle) {
        NSString *pattern = WSInputLimitDecimaStylePattern(_decimalPlace);
        NSString *result = [self subStringFromText:text withPattern:pattern];
        return result;
    }
    
    if (_allowPattern) {
        NSString *result = [self subStringFromText:text withPattern:_allowPattern];
        return result;
    }
    
    NSString *filterPattern = _filterPattern;
    if (_disableEmoji) {
        filterPattern = WSInputLimitFilterEmojiPattern;
    }
    if (filterPattern) {
        NSRegularExpression *regex = [[NSRegularExpression alloc]initWithPattern:filterPattern options:0 error:NULL];
        NSString *result = [regex stringByReplacingMatchesInString:text
                                                           options:0
                                                             range:NSMakeRange(0, text.length)
                                                      withTemplate:@""];
        result = [self lengthHandle:result];
        return result;
    }
    
    NSString *result = [self lengthHandle:text];
    return result;
}

- (NSString *)subStringFromText:(NSString *)string withPattern:(NSString *)pattern {
    NSRange range = [string rangeOfString:pattern
                                  options:NSRegularExpressionSearch
                                    range:NSMakeRange(0, string.length)];
    NSString *result = @"";
    if (range.location != NSNotFound) {
        result = [string substringWithRange:range];
    }
    result = [self lengthHandle:result];
    return result;
}

- (NSString *)lengthHandle:(NSString *)text {
    __block NSString *filterText = @"";
    __block NSInteger currentChatNum = 0;
    NSInteger maxCharacterNumber = _maxCharacterNumber;
    [text enumerateSubstringsInRange:NSMakeRange(0, text.length)
                             options:NSStringEnumerationByComposedCharacterSequences
                          usingBlock:^(NSString * _Nullable substring, NSRange substringRange, NSRange enclosingRange, BOOL * _Nonnull stop) {
                              if (maxCharacterNumber > 0 && currentChatNum >= maxCharacterNumber) {
                                  *stop = YES;
                              } else {
                                  filterText = [filterText stringByAppendingString:substring];
                                  currentChatNum ++;
                              }
                          }];
    _currentCharNumber = currentChatNum;
    _canEnterCharNumber = MAX(0, _maxCharacterNumber - _currentCharNumber);
    return filterText;
}

@end

@implementation UITextView (WSInputLimit)

- (EGInputLimit *)limit {
    EGInputLimit *limit = objc_getAssociatedObject(self, _cmd);
    if (!limit) {
        limit = [[EGInputLimit alloc]initWithTextView:self];
        objc_setAssociatedObject(self, _cmd, limit, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return limit;
}

@end

@implementation UITextField (WSInputLimit)

- (EGInputLimit *)limit {
    EGInputLimit *limit = objc_getAssociatedObject(self, _cmd);
    if (!limit) {
        limit = [[EGInputLimit alloc]initWithTextField:self];
        objc_setAssociatedObject(self, _cmd, limit, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return limit;
}

@end
