#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <UnityAppController.h>
#import <objc/runtime.h>

#import <P101XP/P101XP-Swift.h>


@implementation UnityAppController(P101XPSDK)

static NSMutableDictionary *isOverridedMethod;

#define P101XP_IS_OVERRIDED_METHOD(_sel) \
([isOverridedMethod[[NSValue valueWithPointer:_sel]] boolValue])

#define P101XP_OVERRIDE_METHOD(_src, _dst) \
(@[ [NSValue valueWithPointer:_src], [NSValue valueWithPointer:_dst] ])

+ (void)load {
    isOverridedMethod = [[NSMutableDictionary alloc] init];
    NSArray *overrideMethods = @[ /* source_method, destination_method */
    // didFinishLaunchingWithOptions
    P101XP_OVERRIDE_METHOD(@selector(application:didFinishLaunchingWithOptions:),
                           @selector(p101xpApplication:didFinishLaunchingWithOptions:)),
    // didReceiveRemoteNotification:fetchCompletionHandler
    P101XP_OVERRIDE_METHOD(@selector(application:didReceiveRemoteNotification:fetchCompletionHandler:),
                           @selector(p101xpApplication:didReceiveRemoteNotification:fetchCompletionHandler:)),
    // applicationWillTerminate
    P101XP_OVERRIDE_METHOD(@selector(applicationWillTerminate:),
                           @selector(p101xpApplicationWillTerminate:))
    ];
    
    for (NSArray *method in overrideMethods) {
        BOOL overrided = [UnityAppController exchangeSelectors:SEL([method[0] pointerValue])
                                     selector:SEL([method[1] pointerValue])];
        isOverridedMethod[method[0]] = [NSNumber numberWithBool:overrided];
    }
}

+ (BOOL)exchangeSelectors:(SEL)sourceSelector selector:(SEL)destinationSelector {
    bool overrided = NO;
    Method original = class_getInstanceMethod(self, sourceSelector);
    Method swizzled = class_getInstanceMethod(self, destinationSelector);
    
    if (original != nil) {
        method_exchangeImplementations(original, swizzled);
        overrided = YES;
    } else {
        class_addMethod([self class],
                        sourceSelector,
                        method_getImplementation(swizzled),
                        method_getTypeEncoding(swizzled));
    }
    
    return overrided;
}

- (BOOL)p101xpApplication:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
    BOOL res = [P101XPSDK didFinishLaunchingWithOptions:application options:launchOptions];
    if (P101XP_IS_OVERRIDED_METHOD(@selector(application:didFinishLaunchingWithOptions:))) {
        return [self p101xpApplication:application didFinishLaunchingWithOptions:launchOptions] || res;
    }
    return res;
}

- (void)p101xpApplication:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo
   fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler {
    [P101XPSDK didReceiveRemoteNotification:userInfo completionHandler:completionHandler];
    if (P101XP_IS_OVERRIDED_METHOD(@selector(application:didReceiveRemoteNotification:fetchCompletionHandler:))) {
        [self p101xpApplication:application didReceiveRemoteNotification:userInfo
         fetchCompletionHandler:completionHandler];
    }
}

- (void)p101xpApplicationWillTerminate:(UIApplication *)application {
    [P101XPSDK sceneWillTerminate];
    if (P101XP_IS_OVERRIDED_METHOD(@selector(applicationWillTerminate:))) {
        [self p101xpApplicationWillTerminate:application];
    }
}
@end
