// 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/FlutterKeyboardManager.h"

@interface FlutterKeyboardManager ()

/**
 * The owner set by initWithOwner.
 */
@property(nonatomic, weak) NSResponder* owner;

/**
 * The primary responders added by addPrimaryResponder.
 */
@property(nonatomic) NSMutableArray<id<FlutterKeyPrimaryResponder>>* primaryResponders;

/**
 * The secondary responders added by addSecondaryResponder.
 */
@property(nonatomic) NSMutableArray<id<FlutterKeySecondaryResponder>>* secondaryResponders;

- (void)dispatchToSecondaryResponders:(NSEvent*)event;

@end

@implementation FlutterKeyboardManager

- (nonnull instancetype)initWithOwner:(NSResponder*)weakOwner {
  self = [super init];
  if (self != nil) {
    _owner = weakOwner;
    _primaryResponders = [[NSMutableArray alloc] init];
    _secondaryResponders = [[NSMutableArray alloc] init];
  }
  return self;
}

- (void)addPrimaryResponder:(nonnull id<FlutterKeyPrimaryResponder>)responder {
  [_primaryResponders addObject:responder];
}

- (void)addSecondaryResponder:(nonnull id<FlutterKeySecondaryResponder>)responder {
  [_secondaryResponders addObject:responder];
}

- (void)handleEvent:(nonnull NSEvent*)event {
  // Be sure to add a handling method in propagateKeyEvent if you allow more
  // event types here.
  if (event.type != NSEventTypeKeyDown && event.type != NSEventTypeKeyUp &&
      event.type != NSEventTypeFlagsChanged) {
    return;
  }
  // Having no primary responders require extra logic, but since Flutter adds
  // all primary responders in hard-code, this is a situation that Flutter will
  // never meet.
  NSAssert([_primaryResponders count] >= 0, @"At least one primary responder must be added.");

  __weak __typeof__(self) weakSelf = self;
  __block int unreplied = [_primaryResponders count];
  __block BOOL anyHandled = false;
  FlutterAsyncKeyCallback replyCallback = ^(BOOL handled) {
    unreplied -= 1;
    NSAssert(unreplied >= 0, @"More primary responders replied than possible.");
    anyHandled = anyHandled || handled;
    if (unreplied == 0 && !anyHandled) {
      [weakSelf dispatchToSecondaryResponders:event];
    }
  };

  for (id<FlutterKeyPrimaryResponder> responder in _primaryResponders) {
    [responder handleEvent:event callback:replyCallback];
  }
}

#pragma mark - Private

- (void)dispatchToSecondaryResponders:(NSEvent*)event {
  for (id<FlutterKeySecondaryResponder> responder in _secondaryResponders) {
    if ([responder handleKeyEvent:event]) {
      return;
    }
  }
  switch (event.type) {
    case NSEventTypeKeyDown:
      if ([_owner.nextResponder respondsToSelector:@selector(keyDown:)]) {
        [_owner.nextResponder keyDown:event];
      }
      break;
    case NSEventTypeKeyUp:
      if ([_owner.nextResponder respondsToSelector:@selector(keyUp:)]) {
        [_owner.nextResponder keyUp:event];
      }
      break;
    case NSEventTypeFlagsChanged:
      if ([_owner.nextResponder respondsToSelector:@selector(flagsChanged:)]) {
        [_owner.nextResponder flagsChanged:event];
      }
      break;
    default:
      NSAssert(false, @"Unexpected key event type (got %lu).", event.type);
  }
}

@end
