//
//  JailMonkey.m
//  Trackops
//
//  Created by Gant Laborde on 7/19/16.
//  Copyright © 2016 Facebook. All rights reserved.
//

#import "JailMonkey.h"
#include <TargetConditionals.h>
#import <React/RCTConvert.h>
#import <React/RCTUtils.h>
#import "ScreenRecordingDetector.h"


@import UIKit;
@import Darwin.sys.sysctl;

static NSString * const JMJailbreakTextFile = @"/private/jailbreak.txt";
static NSString * const JMisJailBronkenKey = @"isJailBroken";
static NSString * const JMCanMockLocationKey = @"canMockLocation";

static BOOL secureScreenOn = NO;
static BOOL screenisShown = NO;
static UIViewController *blankViewControllerMinize;
static UIViewController *blankViewControllerRecord;
@implementation JailMonkey

RCT_EXPORT_MODULE();

+ (BOOL)requiresMainQueueSetup
{
    return YES;
}

- (NSArray *)pathsToCheck
{
    return @[
             @"/Applications/Cydia.app",
             @"/Library/MobileSubstrate/MobileSubstrate.dylib",
             @"/bin/bash",
             @"/usr/sbin/sshd",
             @"/etc/apt",
             @"/private/var/lib/apt",
             @"/usr/sbin/frida-server",
             @"/usr/bin/cycript",
             @"/usr/local/bin/cycript",
             @"/usr/lib/libcycript.dylib",
             @"/Applications/FakeCarrier.app",
             @"/Applications/Icy.app",
             @"/Applications/IntelliScreen.app",
             @"/Applications/MxTube.app",
             @"/Applications/RockApp.app",
             @"/Applications/SBSettings.app",
             @"/Applications/WinterBoard.app",
             @"/Applications/blackra1n.app",
             @"/Library/MobileSubstrate/DynamicLibraries/LiveClock.plist",
             @"/Library/MobileSubstrate/DynamicLibraries/Veency.plist",
             @"/System/Library/LaunchDaemons/com.ikey.bbot.plist",
             @"/System/Library/LaunchDaemons/com.saurik.Cydia.Startup.plist",
             @"/bin/sh",
             @"/etc/ssh/sshd_config",
             @"/private/var/lib/cydia",
             @"/private/var/mobile/Library/SBSettings/Themes",
             @"/private/var/stash",
             @"/private/var/tmp/cydia.log",
             @"/usr/bin/sshd",
             @"/usr/libexec/sftp-server",
             @"/usr/libexec/ssh-keysign",
             @"/var/cache/apt",
             @"/var/lib/apt",
             @"/var/lib/cydia",
             ];
}




+(void)showSecureScreen:(UIWindow*) window{
    if(![[ScreenRecordingDetector sharedInstance] isRecording]){
        [ScreenRecordingDetector stopDetectorTimer];
    }
    if(secureScreenOn){
        if(!screenisShown){
            [window.rootViewController presentViewController:blankViewControllerMinize  animated:NO completion:NULL];
            screenisShown = YES;
        }
        
    }
}


+(void)hideSecureScreen:(UIWindow*) window{
    
    if(secureScreenOn){
        if(screenisShown && ![[ScreenRecordingDetector sharedInstance] isRecording]){
            [window.rootViewController dismissViewControllerAnimated:NO completion:nil];
            screenisShown = NO;
            [ScreenRecordingDetector triggerDetectorTimer];
        }
        
    }
    
    
}

- (NSArray *)schemesToCheck
{
    return @[
             @"cydia://package/com.example.package",
             ];
}

- (BOOL)checkPaths
{
    BOOL existsPath = NO;

    for (NSString *path in [self pathsToCheck]) {
        if ([[NSFileManager defaultManager] fileExistsAtPath:path]){
            existsPath = YES;
            break;
        }
    }

    return existsPath;
}

- (BOOL)checkSchemes
{
    BOOL canOpenScheme = NO;

    for (NSString *scheme in [self schemesToCheck]) {
        if([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:scheme]]){
            canOpenScheme = YES;
            break;
        }
    }

    return canOpenScheme;
}

- (BOOL)canViolateSandbox{

	NSError *error;
    BOOL grantsToWrite = NO;
	NSString *stringToBeWritten = @"This is an anti-spoofing test.";
	[stringToBeWritten writeToFile:JMJailbreakTextFile atomically:YES
						  encoding:NSUTF8StringEncoding error:&error];
	if(!error){
		//Device is jailbroken
		grantsToWrite = YES;
	}

    [[NSFileManager defaultManager] removeItemAtPath:JMJailbreakTextFile error:nil];

    return grantsToWrite;
}

- (BOOL)isDebugged{
    struct kinfo_proc info;
    size_t info_size = sizeof(info);
    int name[4];

    name[0] = CTL_KERN;
    name[1] = KERN_PROC;
    name[2] = KERN_PROC_PID;
    name[3] = getpid();

    if (sysctl(name, 4, &info, &info_size, NULL, 0) == -1) {
        NSLog(@"sysctl() failed: %s", strerror(errno));
        return false;
    }

    if ((info.kp_proc.p_flag & P_TRACED) != 0) {
        return true;
	}

    return false;
}

RCT_EXPORT_METHOD(isDebuggedMode:(RCTPromiseResolveBlock) resolve
    rejecter:(RCTPromiseRejectBlock) __unused reject) {
    BOOL *isDebuggedModeActived = [self isDebugged]; 
    resolve(isDebuggedModeActived ? @YES : @NO);
}

RCT_EXPORT_METHOD(isSafe: (NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    //    NSString *is = [RCTConvert NSString:params[@"promptMessage"]];
    //    NSString *payload = [RCTConvert NSString:params[@"payload"]];
    dispatch_async(dispatch_get_main_queue(), ^(void){
    
    if([params objectForKey:@"debug"] != nil){
        bool debugMode = false;
        debugMode = [RCTConvert BOOL:params[@"debug"]];
        if(debugMode){
            NSDictionary *result = @{
                @"success": @(YES)
            };
            resolve(result);
            return;
        }
    }
    
    // if([self checkPaths]){
    //     reject(@"rooted",@"jailBreakPath",nil);
    //     return;
    // }
    
    // if([self checkSchemes]){
    //     reject(@"rooted",@"jailBreakSchemes",nil);
    //     return;
    // }
    
    // if([self canViolateSandbox]){
    //     reject(@"rooted",@"canViolateSandbox",nil);
    //     return;
    // }
    if([params objectForKey:@"checkEmulator"] != nil){
        bool checkSimulator = false;
        checkSimulator = [RCTConvert BOOL:params[@"checkEmulator"]];
        if(checkSimulator){
            if([self isSimulator]){
                reject(@"rooted",@"isSimulator",nil);
                return;
            }
        }
    }
    
    
    NSDictionary *result = @{
        @"success": @(YES)
    };
    resolve(result);
    });
}



RCT_EXPORT_METHOD(externalCheck: (NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    //    NSString *is = [RCTConvert NSString:params[@"promptMessage"]];
    //    NSString *payload = [RCTConvert NSString:params[@"payload"]];
//    dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // isRunningOnMac();
        // isJb();
        // isInjectedWithDynamicLibrary();
        // isSecurityCheckPassed();
        // isDebugged();
        // isFromAppStore();
    
        //Background Thread
        dispatch_async(dispatch_get_main_queue(), ^(void){
            //Run UI Updates
     

        if([params objectForKey:@"isRunningOnMac"] != nil){
            if([params objectForKey:@"isRunningOnMac"]){
                if(isRunningOnMac()){
                    reject(@"error",@"isRunningOnMac",nil);
                    return;
                }
            }
        }
        
        if([params objectForKey:@"isJb"] != nil){
            if([params objectForKey:@"isJb"]){
                if(isJb()){
                    reject(@"error",@"isJb",nil);
                    return;
                }
            }
        }
        
        
        if([params objectForKey:@"isInjectedWithDynamicLibrary"] != nil){
            if([params objectForKey:@"isInjectedWithDynamicLibrary"]){
                if(isInjectedWithDynamicLibrary()){
                    reject(@"error",@"isInjectedWithDynamicLibrary",nil);
                    return;
                }
            }
        }
        
        
        if([params objectForKey:@"isSecurityCheckPassed"] != nil){
            if([params objectForKey:@"isSecurityCheckPassed"]){
                if(isSecurityCheckPassed()){
                    reject(@"error",@"isSecurityCheckPassed",nil);
                    return;
                }
            }
        }
        
        if([params objectForKey:@"isDebugged"] != nil){
            if([params objectForKey:@"isDebugged"]){
                if(isDebugged()){
                    reject(@"error",@"isDebugged",nil);
                    return;
                }
            }
        }
        
        
        if([params objectForKey:@"isFromAppStore"] != nil){
            if([params objectForKey:@"isFromAppStore"]){
                if(isFromAppStore()){
                    reject(@"error",@"isFromAppStore",nil);
                    return;
                }
            }
        }
        
        NSDictionary *result = @{
            @"success": @(YES)
        };
        resolve(result);
        return;
        });
//    });
}

RCT_EXPORT_METHOD(secureScreen:(NSString *)args resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
  dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
      secureScreenOn = YES;
      [ScreenRecordingDetector triggerDetectorTimer];
      [[NSNotificationCenter defaultCenter] addObserverForName:kScreenRecordingDetectorRecordingStatusChangedNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note){
          [self screenCaptureStatusChanged:args];
      }];
  });
}

-(void)screenCaptureStatusChanged:(NSString *)args {
    if ([[ScreenRecordingDetector sharedInstance] isRecording]) {
        NSLog(@"recording");
//        UIApplication.sharedApplication().window.rootViewController
        if(!screenisShown){
            [self blurScreen: args];
        UIViewController* vc = RCTPresentedViewController();
        [vc presentViewController:blankViewControllerMinize animated:NO completion:NULL];
            screenisShown = YES;
        }
    }else{
        
        if(screenisShown){
            [self removeBlurScreen];
            UIViewController* vc = RCTPresentedViewController();
            [vc dismissViewControllerAnimated:NO completion:nil];
            screenisShown = NO;
            NSLog(@"not recording");
        }
        
    }
    
}


RCT_EXPORT_METHOD(unSecureScreen: (RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
  dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
      secureScreenOn = NO;
  });
}


- (BOOL)isJailBroken{
    #if TARGET_OS_SIMULATOR
      return NO;
    #endif
    BOOL isiOSAppOnMac = false;
    if (@available(iOS 14.0, *)) {
        isiOSAppOnMac = [NSProcessInfo processInfo].isiOSAppOnMac;
    }
    if (isiOSAppOnMac) {
        return false;
    }
    return [self checkPaths] || [self checkSchemes] || [self canViolateSandbox];
}

-(void)initBlankScreen{
    if(blankViewControllerMinize == nil){
        blankViewControllerMinize = [UIViewController new];
    }
    
    blankViewControllerMinize.view.backgroundColor = [UIColor whiteColor];
    [blankViewControllerMinize setRestorationIdentifier:@"privacyScreen"];
    [blankViewControllerMinize setModalPresentationStyle:UIModalPresentationFullScreen];
    blankViewControllerMinize.view.userInteractionEnabled = NO;
   
}

-(void) blurScreen:(NSString *)args{
    if(blankViewControllerMinize == nil){
        blankViewControllerMinize = [UIViewController new];
    }
    blankViewControllerMinize.view.backgroundColor = [UIColor clearColor];
    UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
    UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
    blurEffectView.frame = blankViewControllerMinize.view.bounds;
    [blankViewControllerMinize.view addSubview:blurEffectView];
    [blankViewControllerMinize setModalPresentationStyle:UIModalPresentationOverCurrentContext];
    blankViewControllerMinize.view.userInteractionEnabled = NO;
    UILabel *fromLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, blankViewControllerMinize.view.bounds.size.width-100, blankViewControllerMinize.view.bounds.size.height)];
    fromLabel.text = args;
    fromLabel.numberOfLines = 0;
    fromLabel.minimumScaleFactor = 10.0f/12.0f;
    fromLabel.baselineAdjustment =UIBaselineAdjustmentAlignCenters;
    fromLabel.adjustsFontSizeToFitWidth = YES;
    fromLabel.textColor = [UIColor whiteColor];
    fromLabel.textAlignment = NSTextAlignmentCenter;
    [fromLabel setCenter:blankViewControllerMinize.view.center];
    //    [fromLabel setCenter: CGPointMake(blankViewControllerMinize.view.center.x, blankViewControllerMinize.view.center.y)];
    [blankViewControllerMinize.view addSubview:fromLabel];
}

-(void) removeBlurScreen{
    blankViewControllerMinize = nil;
    [blankViewControllerMinize.view removeFromSuperview];
}

- (BOOL)isSimulator{
    #if TARGET_OS_SIMULATOR
      return YES;
    #endif
    
    
    return NO;
}

- (NSDictionary *)constantsToExport
{
	return @{
		JMisJailBronkenKey: @(self.isJailBroken),
		JMCanMockLocationKey: @(self.isJailBroken)
	};
}

@end
