/*
 *
 * Copyright 2019 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#import <Foundation/Foundation.h>

#import "GRPCInterceptor.h"
#import "private/GRPCTransport+Private.h"

@interface GRPCInterceptorManager () <GRPCInterceptorInterface, GRPCResponseHandler>

@end

@implementation GRPCInterceptorManager {
  id<GRPCInterceptorInterface> _nextInterceptor;
  id<GRPCResponseHandler> _previousInterceptor;
  GRPCInterceptor *_thisInterceptor;
  dispatch_queue_t _dispatchQueue;
  NSArray<id<GRPCInterceptorFactory>> *_factories;
  GRPCTransportID _transportID;
  BOOL _shutDown;
}

- (instancetype)initWithFactories:(NSArray<id<GRPCInterceptorFactory>> *)factories
              previousInterceptor:(id<GRPCResponseHandler>)previousInterceptor
                      transportID:(nonnull GRPCTransportID)transportID {
  if ((self = [super init])) {
    if (factories.count == 0) {
      [NSException raise:NSInternalInconsistencyException
                  format:@"Interceptor manager must have factories"];
    }
    _thisInterceptor = [factories[0] createInterceptorWithManager:self];
    if (_thisInterceptor == nil) {
      return nil;
    }
    _previousInterceptor = previousInterceptor;
    _factories = factories;
    // Generate interceptor
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 || __MAC_OS_X_VERSION_MAX_ALLOWED >= 101300
    if (@available(iOS 8.0, macOS 10.10, *)) {
      _dispatchQueue = dispatch_queue_create(
          NULL,
          dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0));
    } else {
#else
    {
#endif
      _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
    }
    dispatch_set_target_queue(_dispatchQueue, _thisInterceptor.dispatchQueue);
    _transportID = transportID;
  }
  return self;
}

- (void)shutDown {
  // immediately releases reference; should not queue to dispatch queue.
  _nextInterceptor = nil;
  _previousInterceptor = nil;
  _thisInterceptor = nil;
  _shutDown = YES;
}

- (void)createNextInterceptor {
  NSAssert(_nextInterceptor == nil, @"Starting the next interceptor more than once");
  NSAssert(_factories.count > 0, @"Interceptor manager of transport cannot start next interceptor");
  if (_nextInterceptor != nil) {
    NSLog(@"Starting the next interceptor more than once");
    return;
  }
  NSMutableArray<id<GRPCInterceptorFactory>> *interceptorFactories = [NSMutableArray
      arrayWithArray:[_factories subarrayWithRange:NSMakeRange(1, _factories.count - 1)]];
  while (_nextInterceptor == nil) {
    if (interceptorFactories.count == 0) {
      _nextInterceptor = [[GRPCTransportManager alloc] initWithTransportID:_transportID
                                                       previousInterceptor:self];
      break;
    } else {
      _nextInterceptor = [[GRPCInterceptorManager alloc] initWithFactories:interceptorFactories
                                                       previousInterceptor:self
                                                               transportID:_transportID];
      if (_nextInterceptor == nil) {
        [interceptorFactories removeObjectAtIndex:0];
      }
    }
  }
  NSAssert(_nextInterceptor != nil, @"Failed to create interceptor or transport.");
  if (_nextInterceptor == nil) {
    NSLog(@"Failed to create interceptor or transport.");
  }
}

- (void)startNextInterceptorWithRequest:(GRPCRequestOptions *)requestOptions
                            callOptions:(GRPCCallOptions *)callOptions {
  if (_nextInterceptor == nil && !_shutDown) {
    [self createNextInterceptor];
  }
  if (_nextInterceptor == nil) {
    return;
  }
  id<GRPCInterceptorInterface> copiedNextInterceptor = _nextInterceptor;
  dispatch_async(copiedNextInterceptor.dispatchQueue, ^{
    [copiedNextInterceptor startWithRequestOptions:requestOptions callOptions:callOptions];
  });
}

- (void)writeNextInterceptorWithData:(id)data {
  if (_nextInterceptor == nil && !_shutDown) {
    [self createNextInterceptor];
  }
  if (_nextInterceptor == nil) {
    return;
  }
  id<GRPCInterceptorInterface> copiedNextInterceptor = _nextInterceptor;
  dispatch_async(copiedNextInterceptor.dispatchQueue, ^{
    [copiedNextInterceptor writeData:data];
  });
}

- (void)finishNextInterceptor {
  if (_nextInterceptor == nil && !_shutDown) {
    [self createNextInterceptor];
  }
  if (_nextInterceptor == nil) {
    return;
  }
  id<GRPCInterceptorInterface> copiedNextInterceptor = _nextInterceptor;
  dispatch_async(copiedNextInterceptor.dispatchQueue, ^{
    [copiedNextInterceptor finish];
  });
}

- (void)cancelNextInterceptor {
  if (_nextInterceptor == nil && !_shutDown) {
    [self createNextInterceptor];
  }
  if (_nextInterceptor == nil) {
    return;
  }
  id<GRPCInterceptorInterface> copiedNextInterceptor = _nextInterceptor;
  dispatch_async(copiedNextInterceptor.dispatchQueue, ^{
    [copiedNextInterceptor cancel];
  });
}

/** Notify the next interceptor in the chain to receive more messages */
- (void)receiveNextInterceptorMessages:(NSUInteger)numberOfMessages {
  if (_nextInterceptor == nil && !_shutDown) {
    [self createNextInterceptor];
  }
  if (_nextInterceptor == nil) {
    return;
  }
  id<GRPCInterceptorInterface> copiedNextInterceptor = _nextInterceptor;
  dispatch_async(copiedNextInterceptor.dispatchQueue, ^{
    [copiedNextInterceptor receiveNextMessages:numberOfMessages];
  });
}

// Methods to forward GRPCResponseHandler callbacks to the previous object

/** Forward initial metadata to the previous interceptor in the chain */
- (void)forwardPreviousInterceptorWithInitialMetadata:(NSDictionary *)initialMetadata {
  if (_previousInterceptor == nil) {
    return;
  }
  id<GRPCResponseHandler> copiedPreviousInterceptor = _previousInterceptor;
  dispatch_async(copiedPreviousInterceptor.dispatchQueue, ^{
    [copiedPreviousInterceptor didReceiveInitialMetadata:initialMetadata];
  });
}

/** Forward a received message to the previous interceptor in the chain */
- (void)forwardPreviousInterceptorWithData:(id)data {
  if (_previousInterceptor == nil) {
    return;
  }
  id<GRPCResponseHandler> copiedPreviousInterceptor = _previousInterceptor;
  dispatch_async(copiedPreviousInterceptor.dispatchQueue, ^{
    [copiedPreviousInterceptor didReceiveData:data];
  });
}

/** Forward call close and trailing metadata to the previous interceptor in the chain */
- (void)forwardPreviousInterceptorCloseWithTrailingMetadata:(NSDictionary *)trailingMetadata
                                                      error:(NSError *)error {
  if (_previousInterceptor == nil) {
    return;
  }
  id<GRPCResponseHandler> copiedPreviousInterceptor = _previousInterceptor;
  // no more callbacks should be issued to the previous interceptor
  _previousInterceptor = nil;
  dispatch_async(copiedPreviousInterceptor.dispatchQueue, ^{
    [copiedPreviousInterceptor didCloseWithTrailingMetadata:trailingMetadata error:error];
  });
}

/** Forward write completion to the previous interceptor in the chain */
- (void)forwardPreviousInterceptorDidWriteData {
  if (_previousInterceptor == nil) {
    return;
  }
  id<GRPCResponseHandler> copiedPreviousInterceptor = _previousInterceptor;
  dispatch_async(copiedPreviousInterceptor.dispatchQueue, ^{
    [copiedPreviousInterceptor didWriteData];
  });
}

- (dispatch_queue_t)dispatchQueue {
  return _dispatchQueue;
}

- (void)startWithRequestOptions:(GRPCRequestOptions *)requestOptions
                    callOptions:(GRPCCallOptions *)callOptions {
  // retain this interceptor until the method exit to prevent deallocation of the interceptor within
  // the interceptor's method
  GRPCInterceptor *thisInterceptor = _thisInterceptor;
  [thisInterceptor startWithRequestOptions:requestOptions callOptions:callOptions];
}

- (void)writeData:(id)data {
  // retain this interceptor until the method exit to prevent deallocation of the interceptor within
  // the interceptor's method
  GRPCInterceptor *thisInterceptor = _thisInterceptor;
  [thisInterceptor writeData:data];
}

- (void)finish {
  // retain this interceptor until the method exit to prevent deallocation of the interceptor within
  // the interceptor's method
  GRPCInterceptor *thisInterceptor = _thisInterceptor;
  [thisInterceptor finish];
}

- (void)cancel {
  // retain this interceptor until the method exit to prevent deallocation of the interceptor within
  // the interceptor's method
  GRPCInterceptor *thisInterceptor = _thisInterceptor;
  [thisInterceptor cancel];
}

- (void)receiveNextMessages:(NSUInteger)numberOfMessages {
  // retain this interceptor until the method exit to prevent deallocation of the interceptor within
  // the interceptor's method
  GRPCInterceptor *thisInterceptor = _thisInterceptor;
  [thisInterceptor receiveNextMessages:numberOfMessages];
}

- (void)didReceiveInitialMetadata:(nullable NSDictionary *)initialMetadata {
  if ([_thisInterceptor respondsToSelector:@selector(didReceiveInitialMetadata:)]) {
    // retain this interceptor until the method exit to prevent deallocation of the interceptor
    // within the interceptor's method
    GRPCInterceptor *thisInterceptor = _thisInterceptor;
    [thisInterceptor didReceiveInitialMetadata:initialMetadata];
  }
}

- (void)didReceiveData:(id)data {
  if ([_thisInterceptor respondsToSelector:@selector(didReceiveData:)]) {
    // retain this interceptor until the method exit to prevent deallocation of the interceptor
    // within the interceptor's method
    GRPCInterceptor *thisInterceptor = _thisInterceptor;
    [thisInterceptor didReceiveData:data];
  }
}

- (void)didCloseWithTrailingMetadata:(nullable NSDictionary *)trailingMetadata
                               error:(nullable NSError *)error {
  if ([_thisInterceptor respondsToSelector:@selector(didCloseWithTrailingMetadata:error:)]) {
    // retain this interceptor until the method exit to prevent deallocation of the interceptor
    // within the interceptor's method
    GRPCInterceptor *thisInterceptor = _thisInterceptor;
    [thisInterceptor didCloseWithTrailingMetadata:trailingMetadata error:error];
  }
}

- (void)didWriteData {
  if ([_thisInterceptor respondsToSelector:@selector(didWriteData)]) {
    // retain this interceptor until the method exit to prevent deallocation of the interceptor
    // within the interceptor's method
    GRPCInterceptor *thisInterceptor = _thisInterceptor;
    [thisInterceptor didWriteData];
  }
}

@end

@implementation GRPCInterceptor {
  GRPCInterceptorManager *_manager;
  dispatch_queue_t _dispatchQueue;
}

- (instancetype)initWithInterceptorManager:(GRPCInterceptorManager *)interceptorManager
                             dispatchQueue:(dispatch_queue_t)dispatchQueue {
  if ((self = [super init])) {
    _manager = interceptorManager;
    _dispatchQueue = dispatchQueue;
  }

  return self;
}

- (dispatch_queue_t)dispatchQueue {
  return _dispatchQueue;
}

- (void)startWithRequestOptions:(GRPCRequestOptions *)requestOptions
                    callOptions:(GRPCCallOptions *)callOptions {
  [_manager startNextInterceptorWithRequest:requestOptions callOptions:callOptions];
}

- (void)writeData:(id)data {
  [_manager writeNextInterceptorWithData:data];
}

- (void)finish {
  [_manager finishNextInterceptor];
}

- (void)cancel {
  [_manager cancelNextInterceptor];
  [_manager
      forwardPreviousInterceptorCloseWithTrailingMetadata:nil
                                                    error:[NSError
                                                              errorWithDomain:kGRPCErrorDomain
                                                                         code:GRPCErrorCodeCancelled
                                                                     userInfo:@{
                                                                       NSLocalizedDescriptionKey :
                                                                           @"Canceled"
                                                                     }]];
  [_manager shutDown];
}

- (void)receiveNextMessages:(NSUInteger)numberOfMessages {
  [_manager receiveNextInterceptorMessages:numberOfMessages];
}

- (void)didReceiveInitialMetadata:(NSDictionary *)initialMetadata {
  [_manager forwardPreviousInterceptorWithInitialMetadata:initialMetadata];
}

- (void)didReceiveRawMessage:(id)message {
  NSAssert(NO,
           @"The method didReceiveRawMessage is deprecated and cannot be used with interceptor");
  NSLog(@"The method didReceiveRawMessage is deprecated and cannot be used with interceptor");
  abort();
}

- (void)didReceiveData:(id)data {
  [_manager forwardPreviousInterceptorWithData:data];
}

- (void)didCloseWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error {
  [_manager forwardPreviousInterceptorCloseWithTrailingMetadata:trailingMetadata error:error];
  [_manager shutDown];
}

- (void)didWriteData {
  [_manager forwardPreviousInterceptorDidWriteData];
}

@end
