// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterTextInputPlugin.h"

#import <Foundation/Foundation.h>
#import <objc/message.h>

#include <algorithm>
#include <memory>

#include "flutter/fml/platform/darwin/string_range_sanitization.h"
#include "flutter/shell/platform/common/text_editing_delta.h"
#include "flutter/shell/platform/common/text_input_model.h"
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterCodecs.h"
#import "flutter/shell/platform/darwin/macos/framework/Headers/FlutterAppDelegate.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterTextInputSemanticsObject.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h"

static NSString* const kTextInputChannel = @"flutter/textinput";

// See https://api.flutter.dev/flutter/services/SystemChannels/textInput-constant.html
static NSString* const kSetClientMethod = @"TextInput.setClient";
static NSString* const kShowMethod = @"TextInput.show";
static NSString* const kHideMethod = @"TextInput.hide";
static NSString* const kClearClientMethod = @"TextInput.clearClient";
static NSString* const kSetEditingStateMethod = @"TextInput.setEditingState";
static NSString* const kSetEditableSizeAndTransform = @"TextInput.setEditableSizeAndTransform";
static NSString* const kSetCaretRect = @"TextInput.setCaretRect";
static NSString* const kUpdateEditStateResponseMethod = @"TextInputClient.updateEditingState";
static NSString* const kUpdateEditStateWithDeltasResponseMethod =
    @"TextInputClient.updateEditingStateWithDeltas";
static NSString* const kPerformAction = @"TextInputClient.performAction";
static NSString* const kPerformSelectors = @"TextInputClient.performSelectors";
static NSString* const kMultilineInputType = @"TextInputType.multiline";

static NSString* const kTextAffinityDownstream = @"TextAffinity.downstream";
static NSString* const kTextAffinityUpstream = @"TextAffinity.upstream";

static NSString* const kTextInputAction = @"inputAction";
static NSString* const kEnableDeltaModel = @"enableDeltaModel";
static NSString* const kTextInputType = @"inputType";
static NSString* const kTextInputTypeName = @"name";

static NSString* const kSelectionBaseKey = @"selectionBase";
static NSString* const kSelectionExtentKey = @"selectionExtent";
static NSString* const kSelectionAffinityKey = @"selectionAffinity";
static NSString* const kSelectionIsDirectionalKey = @"selectionIsDirectional";
static NSString* const kComposingBaseKey = @"composingBase";
static NSString* const kComposingExtentKey = @"composingExtent";
static NSString* const kTextKey = @"text";
static NSString* const kTransformKey = @"transform";

/**
 * The affinity of the current cursor position. If the cursor is at a position representing
 * a line break, the cursor may be drawn either at the end of the current line (upstream)
 * or at the beginning of the next (downstream).
 */
typedef NS_ENUM(NSUInteger, FlutterTextAffinity) {
  kFlutterTextAffinityUpstream,
  kFlutterTextAffinityDownstream
};

/*
 * Updates a range given base and extent fields.
 */
static flutter::TextRange RangeFromBaseExtent(NSNumber* base,
                                              NSNumber* extent,
                                              const flutter::TextRange& range) {
  if (base == nil || extent == nil) {
    return range;
  }
  if (base.intValue == -1 && extent.intValue == -1) {
    return flutter::TextRange(0, 0);
  }
  return flutter::TextRange([base unsignedLongValue], [extent unsignedLongValue]);
}

@interface NSEvent (KeyEquivalentMarker)

// Internally marks that the event was received through performKeyEquivalent:.
// When text editing is active, keyboard events that have modifier keys pressed
// are received through performKeyEquivalent: instead of keyDown:. If such event
// is passed to TextInputContext but doesn't result in a text editing action it
// needs to be forwarded by FlutterKeyboardManager to the next responder.
- (void)markAsKeyEquivalent;

// Returns YES if the event is marked as a key equivalent.
- (BOOL)isKeyEquivalent;

@end

@implementation NSEvent (KeyEquivalentMarker)

// This field doesn't need a value because only its address is used as a unique identifier.
static char markerKey;

- (void)markAsKeyEquivalent {
  objc_setAssociatedObject(self, &markerKey, @true, OBJC_ASSOCIATION_RETAIN);
}

- (BOOL)isKeyEquivalent {
  return [objc_getAssociatedObject(self, &markerKey) boolValue] == YES;
}

@end

/**
 * Private properties of FlutterTextInputPlugin.
 */
@interface FlutterTextInputPlugin ()

/**
 * A text input context, representing a connection to the Cocoa text input system.
 */
@property(nonatomic) NSTextInputContext* textInputContext;

/**
 * The channel used to communicate with Flutter.
 */
@property(nonatomic) FlutterMethodChannel* channel;

/**
 * The FlutterViewController to manage input for.
 */
@property(nonatomic, weak) FlutterViewController* flutterViewController;

/**
 * Whether the text input is shown in the view.
 *
 * Defaults to TRUE on startup.
 */
@property(nonatomic) BOOL shown;

/**
 * The current state of the keyboard and pressed keys.
 */
@property(nonatomic) uint64_t previouslyPressedFlags;

/**
 * The affinity for the current cursor position.
 */
@property FlutterTextAffinity textAffinity;

/**
 * ID of the text input client.
 */
@property(nonatomic, nonnull) NSNumber* clientID;

/**
 * Keyboard type of the client. See available options:
 * https://api.flutter.dev/flutter/services/TextInputType-class.html
 */
@property(nonatomic, nonnull) NSString* inputType;

/**
 * An action requested by the user on the input client. See available options:
 * https://api.flutter.dev/flutter/services/TextInputAction-class.html
 */
@property(nonatomic, nonnull) NSString* inputAction;

/**
 * Set to true if the last event fed to the input context produced a text editing command
 * or text output. It is reset to false at the beginning of every key event, and is only
 * used while processing this event.
 */
@property(nonatomic) BOOL eventProducedOutput;

/**
 * Whether to enable the sending of text input updates from the engine to the
 * framework as TextEditingDeltas rather than as one TextEditingValue.
 * For more information on the delta model, see:
 * https://master-api.flutter.dev/flutter/services/TextInputConfiguration/enableDeltaModel.html
 */
@property(nonatomic) BOOL enableDeltaModel;

/**
 * Used to gather multiple selectors performed in one run loop turn. These
 * will be all sent in one platform channel call so that the framework can process
 * them in single microtask.
 */
@property(nonatomic) NSMutableArray* pendingSelectors;

/**
 * Handles a Flutter system message on the text input channel.
 */
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result;

/**
 * Updates the text input model with state received from the framework via the
 * TextInput.setEditingState message.
 */
- (void)setEditingState:(NSDictionary*)state;

/**
 * Informs the Flutter framework of changes to the text input model's state by
 * sending the entire new state.
 */
- (void)updateEditState;

/**
 * Informs the Flutter framework of changes to the text input model's state by
 * sending only the difference.
 */
- (void)updateEditStateWithDelta:(const flutter::TextEditingDelta)delta;

/**
 * Updates the stringValue and selectedRange that stored in the NSTextView interface
 * that this plugin inherits from.
 *
 * If there is a FlutterTextField uses this plugin as its field editor, this method
 * will update the stringValue and selectedRange through the API of the FlutterTextField.
 */
- (void)updateTextAndSelection;

/**
 * Return the string representation of the current textAffinity as it should be
 * sent over the FlutterMethodChannel.
 */
- (NSString*)textAffinityString;

/**
 * Allow overriding run loop mode for test.
 */
@property(readwrite, nonatomic) NSString* customRunLoopMode;

@end

@implementation FlutterTextInputPlugin {
  /**
   * The currently active text input model.
   */
  std::unique_ptr<flutter::TextInputModel> _activeModel;

  /**
   * Transform for current the editable. Used to determine position of accent selection menu.
   */
  CATransform3D _editableTransform;

  /**
   * Current position of caret in local (editable) coordinates.
   */
  CGRect _caretRect;
}

- (instancetype)initWithViewController:(FlutterViewController*)viewController {
  // The view needs a non-zero frame.
  self = [super initWithFrame:NSMakeRect(0, 0, 1, 1)];
  if (self != nil) {
    _flutterViewController = viewController;
    _channel = [FlutterMethodChannel methodChannelWithName:kTextInputChannel
                                           binaryMessenger:viewController.engine.binaryMessenger
                                                     codec:[FlutterJSONMethodCodec sharedInstance]];
    _shown = FALSE;
    // NSTextView does not support _weak reference, so this class has to
    // use __unsafe_unretained and manage the reference by itself.
    //
    // Since the dealloc removes the handler, the pointer should
    // be valid if the handler is ever called.
    __unsafe_unretained FlutterTextInputPlugin* unsafeSelf = self;
    [_channel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
      [unsafeSelf handleMethodCall:call result:result];
    }];
    _textInputContext = [[NSTextInputContext alloc] initWithClient:unsafeSelf];
    _previouslyPressedFlags = 0;

    // Initialize with the zero matrix which is not
    // an affine transform.
    _editableTransform = CATransform3D();
    _caretRect = CGRectNull;
  }
  return self;
}

- (BOOL)isFirstResponder {
  if (!self.flutterViewController.viewLoaded) {
    return false;
  }
  return [self.flutterViewController.view.window firstResponder] == self;
}

- (void)dealloc {
  [_channel setMethodCallHandler:nil];
}

#pragma mark - Private

- (void)resignAndRemoveFromSuperview {
  if (self.superview != nil) {
    // With accessiblity enabled TextInputPlugin is inside _client, so take the
    // nextResponder from the _client.
    NSResponder* nextResponder = _client != nil ? _client.nextResponder : self.nextResponder;
    [self.window makeFirstResponder:nextResponder];
    [self removeFromSuperview];
  }
}

- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
  BOOL handled = YES;
  NSString* method = call.method;
  if ([method isEqualToString:kSetClientMethod]) {
    if (!call.arguments[0] || !call.arguments[1]) {
      result([FlutterError
          errorWithCode:@"error"
                message:@"Missing arguments"
                details:@"Missing arguments while trying to set a text input client"]);
      return;
    }
    NSNumber* clientID = call.arguments[0];
    if (clientID != nil) {
      NSDictionary* config = call.arguments[1];

      _clientID = clientID;
      _inputAction = config[kTextInputAction];
      _enableDeltaModel = [config[kEnableDeltaModel] boolValue];
      NSDictionary* inputTypeInfo = config[kTextInputType];
      _inputType = inputTypeInfo[kTextInputTypeName];
      self.textAffinity = kFlutterTextAffinityUpstream;

      _activeModel = std::make_unique<flutter::TextInputModel>();
    }
  } else if ([method isEqualToString:kShowMethod]) {
    // Ensure the plugin is in hierarchy. Only do this with accessibility disabled.
    // When accessibility is enabled cocoa will reparent the plugin inside
    // FlutterTextField in [FlutterTextField startEditing].
    if (_client == nil) {
      [_flutterViewController.view addSubview:self];
    }
    [self.window makeFirstResponder:self];
    _shown = TRUE;
  } else if ([method isEqualToString:kHideMethod]) {
    [self resignAndRemoveFromSuperview];
    _shown = FALSE;
  } else if ([method isEqualToString:kClearClientMethod]) {
    [self resignAndRemoveFromSuperview];
    // If there's an active mark region, commit it, end composing, and clear the IME's mark text.
    if (_activeModel && _activeModel->composing()) {
      _activeModel->CommitComposing();
      _activeModel->EndComposing();
    }
    [_textInputContext discardMarkedText];

    _clientID = nil;
    _inputAction = nil;
    _enableDeltaModel = NO;
    _inputType = nil;
    _activeModel = nullptr;
  } else if ([method isEqualToString:kSetEditingStateMethod]) {
    NSDictionary* state = call.arguments;
    [self setEditingState:state];

    // Close the loop, since the framework state could have been updated by the
    // engine since it sent this update, and needs to now be made to match the
    // engine's version of the state.
    if (!_enableDeltaModel) {
      [self updateEditState];
    } else {
      // Send an "empty" delta. The client can compare the old_text with their
      // current text and update with that if the race condition described above
      // occurs.
      [self updateEditStateWithDelta:flutter::TextEditingDelta(_activeModel->GetText().c_str(),
                                                               flutter::TextRange(0, 0), "")];
    }
  } else if ([method isEqualToString:kSetEditableSizeAndTransform]) {
    NSDictionary* state = call.arguments;
    [self setEditableTransform:state[kTransformKey]];
  } else if ([method isEqualToString:kSetCaretRect]) {
    NSDictionary* rect = call.arguments;
    [self updateCaretRect:rect];
  } else {
    handled = NO;
  }
  result(handled ? nil : FlutterMethodNotImplemented);
}

- (void)setEditableTransform:(NSArray*)matrix {
  CATransform3D* transform = &_editableTransform;

  transform->m11 = [matrix[0] doubleValue];
  transform->m12 = [matrix[1] doubleValue];
  transform->m13 = [matrix[2] doubleValue];
  transform->m14 = [matrix[3] doubleValue];

  transform->m21 = [matrix[4] doubleValue];
  transform->m22 = [matrix[5] doubleValue];
  transform->m23 = [matrix[6] doubleValue];
  transform->m24 = [matrix[7] doubleValue];

  transform->m31 = [matrix[8] doubleValue];
  transform->m32 = [matrix[9] doubleValue];
  transform->m33 = [matrix[10] doubleValue];
  transform->m34 = [matrix[11] doubleValue];

  transform->m41 = [matrix[12] doubleValue];
  transform->m42 = [matrix[13] doubleValue];
  transform->m43 = [matrix[14] doubleValue];
  transform->m44 = [matrix[15] doubleValue];
}

- (void)updateCaretRect:(NSDictionary*)dictionary {
  NSAssert(dictionary[@"x"] != nil && dictionary[@"y"] != nil && dictionary[@"width"] != nil &&
               dictionary[@"height"] != nil,
           @"Expected a dictionary representing a CGRect, got %@", dictionary);
  _caretRect = CGRectMake([dictionary[@"x"] doubleValue], [dictionary[@"y"] doubleValue],
                          [dictionary[@"width"] doubleValue], [dictionary[@"height"] doubleValue]);
}

- (void)setEditingState:(NSDictionary*)state {
  NSString* selectionAffinity = state[kSelectionAffinityKey];
  if (selectionAffinity != nil) {
    _textAffinity = [selectionAffinity isEqualToString:kTextAffinityUpstream]
                        ? kFlutterTextAffinityUpstream
                        : kFlutterTextAffinityDownstream;
  }

  NSString* text = state[kTextKey];

  flutter::TextRange selected_range = RangeFromBaseExtent(
      state[kSelectionBaseKey], state[kSelectionExtentKey], _activeModel->selection());
  _activeModel->SetSelection(selected_range);

  flutter::TextRange composing_range = RangeFromBaseExtent(
      state[kComposingBaseKey], state[kComposingExtentKey], _activeModel->composing_range());

  const bool wasComposing = _activeModel->composing();
  _activeModel->SetText([text UTF8String], selected_range, composing_range);
  if (composing_range.collapsed() && wasComposing) {
    [_textInputContext discardMarkedText];
  }
  [_client startEditing];

  [self updateTextAndSelection];
}

- (NSDictionary*)editingState {
  if (_activeModel == nullptr) {
    return nil;
  }

  NSString* const textAffinity = [self textAffinityString];

  int composingBase = _activeModel->composing() ? _activeModel->composing_range().base() : -1;
  int composingExtent = _activeModel->composing() ? _activeModel->composing_range().extent() : -1;

  return @{
    kSelectionBaseKey : @(_activeModel->selection().base()),
    kSelectionExtentKey : @(_activeModel->selection().extent()),
    kSelectionAffinityKey : textAffinity,
    kSelectionIsDirectionalKey : @NO,
    kComposingBaseKey : @(composingBase),
    kComposingExtentKey : @(composingExtent),
    kTextKey : [NSString stringWithUTF8String:_activeModel->GetText().c_str()]
  };
}

- (void)updateEditState {
  if (_activeModel == nullptr) {
    return;
  }

  NSDictionary* state = [self editingState];
  [_channel invokeMethod:kUpdateEditStateResponseMethod arguments:@[ self.clientID, state ]];
  [self updateTextAndSelection];
}

- (void)updateEditStateWithDelta:(const flutter::TextEditingDelta)delta {
  NSUInteger selectionBase = _activeModel->selection().base();
  NSUInteger selectionExtent = _activeModel->selection().extent();
  int composingBase = _activeModel->composing() ? _activeModel->composing_range().base() : -1;
  int composingExtent = _activeModel->composing() ? _activeModel->composing_range().extent() : -1;

  NSString* const textAffinity = [self textAffinityString];

  NSDictionary* deltaToFramework = @{
    @"oldText" : @(delta.old_text().c_str()),
    @"deltaText" : @(delta.delta_text().c_str()),
    @"deltaStart" : @(delta.delta_start()),
    @"deltaEnd" : @(delta.delta_end()),
    @"selectionBase" : @(selectionBase),
    @"selectionExtent" : @(selectionExtent),
    @"selectionAffinity" : textAffinity,
    @"selectionIsDirectional" : @(false),
    @"composingBase" : @(composingBase),
    @"composingExtent" : @(composingExtent),
  };

  NSDictionary* deltas = @{
    @"deltas" : @[ deltaToFramework ],
  };

  [_channel invokeMethod:kUpdateEditStateWithDeltasResponseMethod
               arguments:@[ self.clientID, deltas ]];
  [self updateTextAndSelection];
}

- (void)updateTextAndSelection {
  NSAssert(_activeModel != nullptr, @"Flutter text model must not be null.");
  NSString* text = @(_activeModel->GetText().data());
  int start = _activeModel->selection().base();
  int extend = _activeModel->selection().extent();
  NSRange selection = NSMakeRange(MIN(start, extend), ABS(start - extend));
  // There may be a native text field client if VoiceOver is on.
  // In this case, this plugin has to update text and selection through
  // the client in order for VoiceOver to announce the text editing
  // properly.
  if (_client) {
    [_client updateString:text withSelection:selection];
  } else {
    self.string = text;
    [self setSelectedRange:selection];
  }
}

- (NSString*)textAffinityString {
  return (self.textAffinity == kFlutterTextAffinityUpstream) ? kTextAffinityUpstream
                                                             : kTextAffinityDownstream;
}

- (BOOL)handleKeyEvent:(NSEvent*)event {
  if (event.type == NSEventTypeKeyUp ||
      (event.type == NSEventTypeFlagsChanged && event.modifierFlags < _previouslyPressedFlags)) {
    return NO;
  }
  _previouslyPressedFlags = event.modifierFlags;
  if (!_shown) {
    return NO;
  }

  _eventProducedOutput = NO;
  BOOL res = [_textInputContext handleEvent:event];
  // NSTextInputContext#handleEvent returns YES if the context handles the event. One of the reasons
  // the event is handled is because it's a key equivalent. But a key equivalent might produce a
  // text command (indicated by calling doCommandBySelector) or might not (for example, Cmd+Q). In
  // the latter case, this command somehow has not been executed yet and Flutter must dispatch it to
  // the next responder. See https://github.com/flutter/flutter/issues/106354 .
  if (event.isKeyEquivalent && !_eventProducedOutput) {
    return NO;
  }
  return res;
}

#pragma mark -
#pragma mark NSResponder

- (void)keyDown:(NSEvent*)event {
  [self.flutterViewController keyDown:event];
}

- (void)keyUp:(NSEvent*)event {
  [self.flutterViewController keyUp:event];
}

- (BOOL)performKeyEquivalent:(NSEvent*)event {
  if ([_flutterViewController isDispatchingKeyEvent:event]) {
    // When NSWindow is nextResponder, keyboard manager will send to it
    // unhandled events (through [NSWindow keyDown:]). If event has has both
    // control and cmd modifiers set (i.e. cmd+control+space - emoji picker)
    // NSWindow will then send this event as performKeyEquivalent: to first
    // responder, which is FlutterTextInputPlugin. If that's the case, the
    // plugin must not handle the event, otherwise the emoji picker would not
    // work (due to first responder returning YES from performKeyEquivalent:)
    // and there would be endless loop, because FlutterViewController will
    // send the event back to [keyboardManager handleEvent:].
    return NO;
  }
  [event markAsKeyEquivalent];
  [self.flutterViewController keyDown:event];
  return YES;
}

- (void)flagsChanged:(NSEvent*)event {
  [self.flutterViewController flagsChanged:event];
}

- (void)mouseDown:(NSEvent*)event {
  [self.flutterViewController mouseDown:event];
}

- (void)mouseUp:(NSEvent*)event {
  [self.flutterViewController mouseUp:event];
}

- (void)mouseDragged:(NSEvent*)event {
  [self.flutterViewController mouseDragged:event];
}

- (void)rightMouseDown:(NSEvent*)event {
  [self.flutterViewController rightMouseDown:event];
}

- (void)rightMouseUp:(NSEvent*)event {
  [self.flutterViewController rightMouseUp:event];
}

- (void)rightMouseDragged:(NSEvent*)event {
  [self.flutterViewController rightMouseDragged:event];
}

- (void)otherMouseDown:(NSEvent*)event {
  [self.flutterViewController otherMouseDown:event];
}

- (void)otherMouseUp:(NSEvent*)event {
  [self.flutterViewController otherMouseUp:event];
}

- (void)otherMouseDragged:(NSEvent*)event {
  [self.flutterViewController otherMouseDragged:event];
}

- (void)mouseMoved:(NSEvent*)event {
  [self.flutterViewController mouseMoved:event];
}

- (void)scrollWheel:(NSEvent*)event {
  [self.flutterViewController scrollWheel:event];
}

- (NSTextInputContext*)inputContext {
  return _textInputContext;
}

#pragma mark -
#pragma mark NSTextInputClient

- (void)insertTab:(id)sender {
  // Implementing insertTab: makes AppKit send tab as command, instead of
  // insertText with '\t'.
}

- (void)insertText:(id)string replacementRange:(NSRange)range {
  if (_activeModel == nullptr) {
    return;
  }

  _eventProducedOutput |= true;

  if (range.location != NSNotFound) {
    // The selected range can actually have negative numbers, since it can start
    // at the end of the range if the user selected the text going backwards.
    // Cast to a signed type to determine whether or not the selection is reversed.
    long signedLength = static_cast<long>(range.length);
    long location = range.location;
    long textLength = _activeModel->text_range().end();

    size_t base = std::clamp(location, 0L, textLength);
    size_t extent = std::clamp(location + signedLength, 0L, textLength);

    _activeModel->SetSelection(flutter::TextRange(base, extent));
  }

  flutter::TextRange oldSelection = _activeModel->selection();
  flutter::TextRange composingBeforeChange = _activeModel->composing_range();
  flutter::TextRange replacedRange(-1, -1);

  std::string textBeforeChange = _activeModel->GetText().c_str();
  std::string utf8String = [string UTF8String];
  _activeModel->AddText(utf8String);
  if (_activeModel->composing()) {
    replacedRange = composingBeforeChange;
    _activeModel->CommitComposing();
    _activeModel->EndComposing();
  } else {
    replacedRange = range.location == NSNotFound
                        ? flutter::TextRange(oldSelection.base(), oldSelection.extent())
                        : flutter::TextRange(range.location, range.location + range.length);
  }
  if (_enableDeltaModel) {
    [self updateEditStateWithDelta:flutter::TextEditingDelta(textBeforeChange, replacedRange,
                                                             utf8String)];
  } else {
    [self updateEditState];
  }
}

- (void)doCommandBySelector:(SEL)selector {
  _eventProducedOutput |= selector != NSSelectorFromString(@"noop:");
  if ([self respondsToSelector:selector]) {
    // Note: The more obvious [self performSelector...] doesn't give ARC enough information to
    // handle retain semantics properly. See https://stackoverflow.com/questions/7017281/ for more
    // information.
    IMP imp = [self methodForSelector:selector];
    void (*func)(id, SEL, id) = reinterpret_cast<void (*)(id, SEL, id)>(imp);
    func(self, selector, nil);
  }

  if (selector == @selector(insertNewline:)) {
    // Already handled through text insertion (multiline) or action.
    return;
  }

  // Group multiple selectors received within a single run loop turn so that
  // the framework can process them in single microtask.
  NSString* name = NSStringFromSelector(selector);
  if (_pendingSelectors == nil) {
    _pendingSelectors = [NSMutableArray array];
  }
  [_pendingSelectors addObject:name];

  if (_pendingSelectors.count == 1) {
    __weak NSMutableArray* selectors = _pendingSelectors;
    __weak FlutterMethodChannel* channel = _channel;
    __weak NSNumber* clientID = self.clientID;

    CFStringRef runLoopMode = self.customRunLoopMode != nil
                                  ? (__bridge CFStringRef)self.customRunLoopMode
                                  : kCFRunLoopCommonModes;

    CFRunLoopPerformBlock(CFRunLoopGetMain(), runLoopMode, ^{
      if (selectors.count > 0) {
        [channel invokeMethod:kPerformSelectors arguments:@[ clientID, selectors ]];
        [selectors removeAllObjects];
      }
    });
  }
}

- (void)insertNewline:(id)sender {
  if (_activeModel == nullptr) {
    return;
  }
  if (_activeModel->composing()) {
    _activeModel->CommitComposing();
    _activeModel->EndComposing();
  }
  if ([self.inputType isEqualToString:kMultilineInputType]) {
    [self insertText:@"\n" replacementRange:self.selectedRange];
  }
  [_channel invokeMethod:kPerformAction arguments:@[ self.clientID, self.inputAction ]];
}

- (void)setMarkedText:(id)string
        selectedRange:(NSRange)selectedRange
     replacementRange:(NSRange)replacementRange {
  if (_activeModel == nullptr) {
    return;
  }
  std::string textBeforeChange = _activeModel->GetText().c_str();
  if (!_activeModel->composing()) {
    _activeModel->BeginComposing();
  }

  if (replacementRange.location != NSNotFound) {
    // According to the NSTextInputClient documentation replacementRange is
    // computed from the beginning of the marked text. That doesn't seem to be
    // the case, because in situations where the replacementRange is actually
    // specified (i.e. when switching between characters equivalent after long
    // key press) the replacementRange is provided while there is no composition.
    _activeModel->SetComposingRange(
        flutter::TextRange(replacementRange.location,
                           replacementRange.location + replacementRange.length),
        0);
  }

  flutter::TextRange composingBeforeChange = _activeModel->composing_range();
  flutter::TextRange selectionBeforeChange = _activeModel->selection();

  // Input string may be NSString or NSAttributedString.
  BOOL isAttributedString = [string isKindOfClass:[NSAttributedString class]];
  std::string marked_text = isAttributedString ? [[string string] UTF8String] : [string UTF8String];
  _activeModel->UpdateComposingText(marked_text);

  // Update the selection within the marked text.
  long signedLength = static_cast<long>(selectedRange.length);
  long location = selectedRange.location + _activeModel->composing_range().base();
  long textLength = _activeModel->text_range().end();

  size_t base = std::clamp(location, 0L, textLength);
  size_t extent = std::clamp(location + signedLength, 0L, textLength);
  _activeModel->SetSelection(flutter::TextRange(base, extent));

  if (_enableDeltaModel) {
    [self updateEditStateWithDelta:flutter::TextEditingDelta(textBeforeChange,
                                                             selectionBeforeChange.collapsed()
                                                                 ? composingBeforeChange
                                                                 : selectionBeforeChange,
                                                             marked_text)];
  } else {
    [self updateEditState];
  }
}

- (void)unmarkText {
  if (_activeModel == nullptr) {
    return;
  }
  _activeModel->CommitComposing();
  _activeModel->EndComposing();
  if (_enableDeltaModel) {
    [self updateEditStateWithDelta:flutter::TextEditingDelta(_activeModel->GetText().c_str())];
  } else {
    [self updateEditState];
  }
}

- (NSRange)markedRange {
  if (_activeModel == nullptr) {
    return NSMakeRange(NSNotFound, 0);
  }
  return NSMakeRange(
      _activeModel->composing_range().base(),
      _activeModel->composing_range().extent() - _activeModel->composing_range().base());
}

- (BOOL)hasMarkedText {
  return _activeModel != nullptr && _activeModel->composing_range().length() > 0;
}

- (NSAttributedString*)attributedSubstringForProposedRange:(NSRange)range
                                               actualRange:(NSRangePointer)actualRange {
  if (_activeModel == nullptr) {
    return nil;
  }
  if (actualRange != nil) {
    *actualRange = range;
  }
  NSString* text = [NSString stringWithUTF8String:_activeModel->GetText().c_str()];
  NSString* substring = [text substringWithRange:range];
  return [[NSAttributedString alloc] initWithString:substring attributes:nil];
}

- (NSArray<NSString*>*)validAttributesForMarkedText {
  return @[];
}

// Returns the bounding CGRect of the transformed incomingRect, in screen
// coordinates.
- (CGRect)screenRectFromFrameworkTransform:(CGRect)incomingRect {
  CGPoint points[] = {
      incomingRect.origin,
      CGPointMake(incomingRect.origin.x, incomingRect.origin.y + incomingRect.size.height),
      CGPointMake(incomingRect.origin.x + incomingRect.size.width, incomingRect.origin.y),
      CGPointMake(incomingRect.origin.x + incomingRect.size.width,
                  incomingRect.origin.y + incomingRect.size.height)};

  CGPoint origin = CGPointMake(CGFLOAT_MAX, CGFLOAT_MAX);
  CGPoint farthest = CGPointMake(-CGFLOAT_MAX, -CGFLOAT_MAX);

  for (int i = 0; i < 4; i++) {
    const CGPoint point = points[i];

    CGFloat x = _editableTransform.m11 * point.x + _editableTransform.m21 * point.y +
                _editableTransform.m41;
    CGFloat y = _editableTransform.m12 * point.x + _editableTransform.m22 * point.y +
                _editableTransform.m42;

    const CGFloat w = _editableTransform.m14 * point.x + _editableTransform.m24 * point.y +
                      _editableTransform.m44;

    if (w == 0.0) {
      return CGRectZero;
    } else if (w != 1.0) {
      x /= w;
      y /= w;
    }

    origin.x = MIN(origin.x, x);
    origin.y = MIN(origin.y, y);
    farthest.x = MAX(farthest.x, x);
    farthest.y = MAX(farthest.y, y);
  }

  const NSView* fromView = self.flutterViewController.flutterView;
  const CGRect rectInWindow = [fromView
      convertRect:CGRectMake(origin.x, origin.y, farthest.x - origin.x, farthest.y - origin.y)
           toView:nil];
  NSWindow* window = fromView.window;
  return window ? [window convertRectToScreen:rectInWindow] : rectInWindow;
}

- (NSRect)firstRectForCharacterRange:(NSRange)range actualRange:(NSRangePointer)actualRange {
  // This only determines position of caret instead of any arbitrary range, but it's enough
  // to properly position accent selection popup
  return !self.flutterViewController.viewLoaded || CGRectEqualToRect(_caretRect, CGRectNull)
             ? CGRectZero
             : [self screenRectFromFrameworkTransform:_caretRect];
}

- (NSUInteger)characterIndexForPoint:(NSPoint)point {
  // TODO(cbracken): Implement.
  // Note: This function can't easily be implemented under the system-message architecture.
  return 0;
}

@end
