//
// Copyright 2018 Google Inc.
//
// 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 "Service/Sources/EDOObject.h"

#include <objc/runtime.h>

#import "Service/Sources/EDOBlockObject.h"
#import "Service/Sources/EDOClientService+Private.h"
#import "Service/Sources/EDOClientService.h"
#import "Service/Sources/EDOHostService+Private.h"
#import "Service/Sources/EDOHostService.h"
#import "Service/Sources/EDOInvocationMessage.h"
#import "Service/Sources/EDOMethodSignatureMessage.h"
#import "Service/Sources/EDOObject+Private.h"
#import "Service/Sources/EDOParameter.h"
#import "Service/Sources/EDORemoteException.h"
#import "Service/Sources/EDOServicePort.h"
#import "Service/Sources/EDOServiceRequest.h"

static EDORemoteException *RemoteExceptionWithLocalInformation(EDORemoteException *remoteException,
                                                               EDOObject *target,
                                                               NSInvocation *invocation) {
  NSArray<NSString *> *currentStackTraces = [NSThread callStackSymbols];
  NSUInteger eDOStackIndex = [currentStackTraces
      indexOfObjectPassingTest:^BOOL(NSString *item, NSUInteger idx, BOOL *stop) {
        return [item containsString:@"_CF_forwarding_prep_0"];
      }];
  // If the pattern symbol of eDO entrance is not found, we keep the whole eDO stacks, but we still
  // remove the symbol of this helper C function.
  if (eDOStackIndex == NSNotFound) {
    eDOStackIndex = 0;
  }
  NSArray<NSString *> *localOutputStackTraces = [currentStackTraces
      subarrayWithRange:NSMakeRange(eDOStackIndex + 1,
                                    currentStackTraces.count - eDOStackIndex - 1)];
  NSString *classInfo;
  NSString *methodInfo;
  if (object_getClass(target) == [EDOBlockObject class]) {
    classInfo = @"__block_invoke";
    methodInfo = ((EDOBlockObject *)target).signature;
  } else {
    classInfo = target.className;
    methodInfo = NSStringFromSelector(invocation.selector);
  }
  NSString *separationSymbol =
      [NSString stringWithFormat:@"|---- eDO invocation [%@ %@] ----|", classInfo, methodInfo];

  NSMutableArray<NSString *> *fullStackTraces = [remoteException.callStackSymbols mutableCopy];
  [fullStackTraces addObject:separationSymbol];
  [fullStackTraces addObjectsFromArray:localOutputStackTraces];
  return [[EDORemoteException alloc] initWithName:remoteException.name
                                           reason:remoteException.reason
                                 callStackSymbols:fullStackTraces];
}

// The cache of the instance method signatures.
static NSCache<NSString *, NSMethodSignature *> *gEDOInstanceMethodSignatureCache;

/**
 * Builds the key for the instance method signature cache.
 *
 * @param selector The selector.
 * @param className The class name.
 * @return The key.
 */
static NSString *EDOCreateMethodSignatureCacheKey(SEL selector, NSString *className) {
  return [NSString stringWithFormat:@"%@-%@", className, NSStringFromSelector(selector)];
}

/**
 * Gets the instance method signature for the given selector and class name from the cache.
 *
 * @param selector The selector.
 * @param className The class name.
 * @return The instance method signature.
 */
static NSMethodSignature *EDOInstanceMethodSignatureForSelector(SEL selector, NSString *className) {
  NSString *key = EDOCreateMethodSignatureCacheKey(selector, className);
  NSMethodSignature *methodSignature = [gEDOInstanceMethodSignatureCache objectForKey:key];
  return methodSignature;
}

/**
 * Adds the instance method signature for the given selector and class name to the cache.
 *
 * @param methodSignature The method signature.
 * @param selector The selector.
 * @param className The class name.
 */
static void EDOAddInstanceMethodSignature(NSMethodSignature *methodSignature, SEL selector,
                                          NSString *className) {
  NSString *key = EDOCreateMethodSignatureCacheKey(selector, className);
  [gEDOInstanceMethodSignatureCache setObject:methodSignature forKey:key];
}

/**
 * The extension of EDOObject to handle the message forwarding.
 *
 * When a method is not implemented, the objc runtime executes a sequence of events to recover
 * before it sends doesNotRecognizeSelector: or raises an exception. It requests an
 * NSMethodSignature using -/+methodSignatureForSelector:, which bundles with arguments types and
 * return type information. And from there, it creates an NSInvocation object which captures the
 * full message being sent, including the target, the selector and all the arguments. After this,
 * the runtime invokes -/+forwardInvocation: method and here it serializes all the arguments and
 * sends it across the wire; once it returns, it sets its return value back to the NSInvocation
 * object. This allows us dynamically to turn a local invocation into a remote invocation.
 *
 */
@implementation EDOObject (Invocation)

+ (void)initialize {
  if (self == [EDOObject class]) {
    gEDOInstanceMethodSignatureCache = [[NSCache alloc] init];
  }
}

/**
 * Get an instance method signature for the @c EDOObject
 *
 * This is called from the callee's thread and it is synchronous.
 *
 * @param selector The selector.
 *
 * @return         The instance method signature.
 */
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {
  NSString *className = self.className;
  NSMethodSignature *signature = EDOInstanceMethodSignatureForSelector(selector, className);
  if (signature) {
    return signature;
  }
  EDOServiceRequest *request = [EDOMethodSignatureRequest requestWithObject:self.remoteAddress
                                                                       port:self.servicePort
                                                                   selector:selector];
  EDOMethodSignatureResponse *response = (EDOMethodSignatureResponse *)[EDOClientService
      sendSynchronousRequest:request
                      onPort:self.servicePort.hostPort];
  NSString *signatureString = response.signature;
  if (signatureString) {
    signature = [NSMethodSignature signatureWithObjCTypes:signatureString.UTF8String];
    EDOAddInstanceMethodSignature(signature, selector, className);
  }
  return signature;
}

/** Forwards the invocation to the remote. */
- (void)forwardInvocation:(NSInvocation *)invocation {
  [self edo_forwardInvocation:invocation selector:invocation.selector returnByValue:NO];
}

- (void)edo_forwardInvocation:(NSInvocation *)invocation
                     selector:(SEL)selector
                returnByValue:(BOOL)returnByValue {
  // Keep the service until the end of the invocation scope so the nested remote call can be made
  // using this service.
  NS_VALID_UNTIL_END_OF_SCOPE EDOHostService *service =
      [EDOHostService serviceForCurrentOriginatingQueue];
  BOOL useTemporaryService = NO;

  // If there is no host service created for the current queue, a temporary queue is created only
  // within this invocation scope.
  if (!service) {
    service = [EDOHostService temporaryServiceForCurrentThread];
    useTemporaryService = YES;
  }

  EDOInvocationRequest *request = [EDOInvocationRequest requestWithInvocation:invocation
                                                                       target:self
                                                                     selector:selector
                                                                returnByValue:returnByValue
                                                                      service:service];

  EDOExecutor *executor = [EDOHostService serviceForCurrentExecutingQueue].executor;

  // If we create a temp service, use it as the executor.
  if (useTemporaryService && service.valid) {
    NSAssert(!executor, @"The executor from the temporary service is conflicting with the executor "
                        @"from the executing queue.");
    executor = service.executor;
  }

  EDOInvocationResponse *response =
      (EDOInvocationResponse *)[EDOClientService sendSynchronousRequest:request
                                                                 onPort:self.servicePort.hostPort
                                                           withExecutor:executor];

  if (response.exception) {
    // Populate the exception.
    // Note: we throw here rather than -[raise] because we can't make an assumption of what user's
    //       code will throw.
    @throw RemoteExceptionWithLocalInformation(response.exception, self, invocation);  // NOLINT
  }

  NSUInteger returnBufSize = invocation.methodSignature.methodReturnLength;
  char const *ctype = invocation.methodSignature.methodReturnType;
  if (EDO_IS_OBJECT_OR_CLASS(ctype)) {
    id __unsafe_unretained obj;
    [response.returnValue getValue:&obj];
    obj = [EDOClientService unwrappedObjectFromObject:obj];
    obj = [EDOClientService cachedEDOFromObjectUpdateIfNeeded:obj];
    [invocation setReturnValue:&obj];

    // ARC will insert a -release on the return if the method returns a retained object, but because
    // we build the invocation dynamically, the return is not retained, we insert an extra retain
    // here to compensate ARC.
    if (response.returnRetained) {
      CFBridgingRetain(obj);
    }
  } else if (returnBufSize > 0) {
    char *const returnBuf = calloc(returnBufSize, sizeof(char));
    [response.returnValue getValue:returnBuf];
    [invocation setReturnValue:returnBuf];
    free(returnBuf);
  }

  NSArray<EDOBoxedValueType *> *outValues = response.outValues;
  if (outValues.count > 0) {
    NSMethodSignature *method = invocation.methodSignature;
    NSUInteger numOfArgs = method.numberOfArguments;
    for (NSUInteger curArgIdx = selector ? 2 : 1, curOutIdx = 0; curArgIdx < numOfArgs;
         ++curArgIdx) {
      char const *ctype = [method getArgumentTypeAtIndex:curArgIdx];
      if (!EDO_IS_OBJPOINTER(ctype)) {
        continue;
      }

      id __unsafe_unretained *obj;
      [invocation getArgument:&obj atIndex:curArgIdx];

      // Fill the out value back to its original buffer if provided.
      if (obj) {
        [outValues[curOutIdx] getValue:obj];
        *obj = [EDOClientService unwrappedObjectFromObject:*obj];
        // When there is no running service or the object is a true remote object, we will check
        // the local distant objects cache.
        *obj = [EDOClientService cachedEDOFromObjectUpdateIfNeeded:*obj];
      }

      ++curOutIdx;
    }
  }
}

@end
