#import "AutoCompleteView.h"
#import "DictionaryAutoCompleteObject.h"

#import "MLPAutoCompleteTextField/MLPAutoCompleteTextField.h"
#import <React/RCTConvert.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTUtils.h>
#import "UIView+React.h"

@implementation AutoCompleteView
{
    RCTEventDispatcher *_eventDispatcher;
    NSMutableArray *_reactSubviews;
    BOOL _jsRequestingFirstResponder;
    NSInteger _nativeEventCount;
    NSInteger _mostRecentEventCount;
}

- (void) setSuggestions:(NSArray *)completions {
    if (self.handler) {
        if (self.cellComponent !=nil) {
            NSMutableArray *mutableJsonObjects = [NSMutableArray new];
            for(NSDictionary *json in completions){
                DictionaryAutoCompleteObject *jsonObject = [[DictionaryAutoCompleteObject alloc] initWithDictionnary:json];
                [mutableJsonObjects addObject:jsonObject];
            }
      
          self.handler([NSArray arrayWithArray:mutableJsonObjects]);
        } else {
          self.handler(completions);
        }
    }
}

- (void) setMostRecentEventCount:(NSInteger)mostRecentEventCount {
    if (mostRecentEventCount > 0) {
        _mostRecentEventCount = mostRecentEventCount;
    }
}

- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
{
    if ((self = [super initWithFrame:CGRectZero])) {
        RCTAssert(eventDispatcher, @"eventDispatcher is a required parameter");
        _eventDispatcher = eventDispatcher;
        [self addTarget:self action:@selector(textFieldDidChange) forControlEvents:UIControlEventEditingChanged];
        [self addTarget:self action:@selector(textFieldBeginEditing) forControlEvents:UIControlEventEditingDidBegin];
        [self addTarget:self action:@selector(textFieldEndEditing) forControlEvents:UIControlEventEditingDidEnd];
        [self addTarget:self action:@selector(textFieldSubmitEditing) forControlEvents:UIControlEventEditingDidEndOnExit];
        _reactSubviews = [NSMutableArray new];
    }
    return self;
}

RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)


- (void)setText:(NSString *)text
{
    NSInteger eventLag = _nativeEventCount - _mostRecentEventCount;
    if (eventLag == 0 && ![text isEqualToString:self.text]) {
        UITextRange *selection = self.selectedTextRange;
        super.text = text;
        self.selectedTextRange = selection; // maintain cursor position/selection - this is robust to out of bounds
    } else if (eventLag > RCTTextUpdateLagWarningThreshold) {
        RCTLogWarn(@"Native TextInput(%@) is %zd events ahead of JS - try to make your JS faster.", self.text, eventLag);
    }
}

static void RCTUpdatePlaceholder(AutoCompleteView *self)
{
    if (self.placeholder.length > 0 && self.placeholderTextColor) {
        self.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.placeholder
                                                                     attributes:@{
                                                                                  NSForegroundColorAttributeName : self.placeholderTextColor
                                                                                  }];
    } else if (self.placeholder.length) {
        self.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.placeholder];
    }
}

- (void)setPlaceholderTextColor:(UIColor *)placeholderTextColor
{
    _placeholderTextColor = placeholderTextColor;
    RCTUpdatePlaceholder(self);
}

- (void)setPlaceholder:(NSString *)placeholder
{
    super.placeholder = placeholder;
    RCTUpdatePlaceholder(self);
}

- (NSArray *)reactSubviews
{
    // TODO: do we support subviews of textfield in React?
    // In any case, we should have a better approach than manually
    // maintaining array in each view subclass like this
    return _reactSubviews;
}

- (void)removeReactSubview:(UIView *)subview
{
    // TODO: this is a bit broken - if the TextField inserts any of
    // its own views below or between React's, the indices won't match
    [_reactSubviews removeObject:subview];
    [subview removeFromSuperview];
}

- (void)insertReactSubview:(UIView *)view atIndex:(NSInteger)atIndex
{
    // TODO: this is a bit broken - if the TextField inserts any of
    // its own views below or between React's, the indices won't match
    [_reactSubviews insertObject:view atIndex:atIndex];
    [super insertSubview:view atIndex:atIndex];
}

- (CGRect)caretRectForPosition:(UITextPosition *)position
{
    if (_caretHidden) {
        return CGRectZero;
    }
    return [super caretRectForPosition:position];
}

- (CGRect)textRectForBounds:(CGRect)bounds
{
    CGRect rect = [super textRectForBounds:bounds];
    return UIEdgeInsetsInsetRect(rect, _contentInset);
}

- (CGRect)editingRectForBounds:(CGRect)bounds
{
    return [self textRectForBounds:bounds];
}

- (void)setAutoCorrect:(BOOL)autoCorrect
{
    self.autocorrectionType = (autoCorrect ? UITextAutocorrectionTypeYes : UITextAutocorrectionTypeNo);
}

- (BOOL)autoCorrect
{
    return self.autocorrectionType == UITextAutocorrectionTypeYes;
}

- (void)textFieldDidChange
{
    _nativeEventCount++;
    [_eventDispatcher sendTextEventWithType:RCTTextEventTypeChange
                                   reactTag:self.reactTag
                                       text:self.text
                                        key:nil
                                 eventCount:_nativeEventCount];
}

- (void)textFieldEndEditing
{
    [_eventDispatcher sendTextEventWithType:RCTTextEventTypeEnd
                                   reactTag:self.reactTag
                                       text:self.text
                                        key:nil
                                 eventCount:_nativeEventCount];
}
- (void)textFieldSubmitEditing
{
    [_eventDispatcher sendTextEventWithType:RCTTextEventTypeSubmit
                                   reactTag:self.reactTag
                                       text:self.text
                                        key:nil
                                 eventCount:_nativeEventCount];
}

- (void)textFieldBeginEditing
{
    if (_selectTextOnFocus) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self selectAll:nil];
        });
    }
    [_eventDispatcher sendTextEventWithType:RCTTextEventTypeFocus
                                   reactTag:self.reactTag
                                       text:self.text
                                        key:nil
                                 eventCount:_nativeEventCount];
}

- (BOOL)becomeFirstResponder
{
    _jsRequestingFirstResponder = YES;
    BOOL result = [super becomeFirstResponder];
    _jsRequestingFirstResponder = NO;
    return result;
}

- (BOOL)resignFirstResponder
{
    BOOL result = [super resignFirstResponder];
    if (result)
    {
        [_eventDispatcher sendTextEventWithType:RCTTextEventTypeBlur
                                       reactTag:self.reactTag
                                           text:self.text
                                            key:nil
                                     eventCount:_nativeEventCount];
    }
    return result;
}

- (BOOL)canBecomeFirstResponder
{
    return _jsRequestingFirstResponder;
}

@end
