//
//  XSNetwork.m
//  XenonSDK
//
//  Created by SAGESSE on 2019/5/28.
//  Copyright © 2019 SAGESSE. All rights reserved.
//

#import "XenonSDK.h"

#import <JSONModel/JSONModel.h>
#import "XSTracker.h"

#import "XSUtils.h"
#import <MBProgressHUD/MBProgressHUD.h>
#import <StoreKit/StoreKit.h>
#import "NSBundle+KODLocalizable.h"
#import "KODCommonConst.h"
#if SDK_HAS_IAP_PAYMENT
//#import "IAPAgnet.h"
#import "KDIAPManager.h"
#endif


@interface XSNetwork ()
@end

@implementation XSNetwork

dispatch_semaphore_t sdk_net_semaphore;
dispatch_queue_t sdk_net_waiting;

NSInteger sdk_net_count;
NSString* sdk_net_baseURL;
MBProgressHUD* sdk_net_hud;

+ (NSString*)baseURL {
    return sdk_net_baseURL;
}
+ (void)setBaseURL:(NSString *)baseURL {
    sdk_net_baseURL = baseURL;
}

+ (NSError*)errorWithCode:(NSInteger)code message:(NSString*)message {
    return [NSError errorWithDomain:@"XSNetwork"
                               code:code
                           userInfo:@{NSLocalizedDescriptionKey:message}];
}

+ (void)showHudLoading {
    [sdk_net_hud removeFromSuperview];
    sdk_net_hud = [MBProgressHUD showHUDAddedTo:UIApplication.sharedApplication.keyWindow animated:YES];
    sdk_net_hud.labelText = nil;
    sdk_net_hud.removeFromSuperViewOnHide = YES;
    [sdk_net_hud layoutIfNeeded];
    [sdk_net_hud show:YES];
}

+ (void)showHudSuccess:(id)error {
    [sdk_net_hud removeFromSuperview];
    sdk_net_hud = [MBProgressHUD showHUDAddedTo:UIApplication.sharedApplication.keyWindow animated:YES];
    sdk_net_hud.detailsLabelText = error;
    sdk_net_hud.userInteractionEnabled = NO;
    sdk_net_hud.mode = MBProgressHUDModeText;
    //hud?.customView = UIImageView(image: UIImage(named: "success", in: nil, compatibleWith: nil))
    sdk_net_hud.removeFromSuperViewOnHide = YES;
    [sdk_net_hud hide:YES afterDelay:1.8];

}
+ (void)showHudFailure:(id)error {
    
    NSString* message = error;
    if ([error isKindOfClass:NSError.class]) {
        message = [error localizedDescription];
    }
    
    [sdk_net_hud removeFromSuperview];
    sdk_net_hud = [MBProgressHUD showHUDAddedTo:UIApplication.sharedApplication.keyWindow animated:YES];
    sdk_net_hud.detailsLabelText = message;
    sdk_net_hud.userInteractionEnabled = NO;
    sdk_net_hud.mode = MBProgressHUDModeText;
    //hud?.customView = UIImageView(image: UIImage(named: "error", in: nil, compatibleWith: nil))
    sdk_net_hud.removeFromSuperViewOnHide = YES;
    [sdk_net_hud layoutIfNeeded];
    [sdk_net_hud hide:YES afterDelay:2];
}

+ (void)hideHud {
    [sdk_net_hud removeFromSuperview];
}

+ (void)showPrompt:(NSString*)user {
    
    // If no user information is provided, it is turned off by default.
    if (user.length == 0) {
        //登录成功
        NSString *str = [NSBundle KOD_localizedStringForKey:LoginSuccess];
        [self showHudSuccess:str];
        return;
    }
    
    // Hide the hud first to prevent errors.
    [self hideHud];

    UIWindow* window = UIApplication.sharedApplication.keyWindow;
    UIView* view = [[UIView alloc] initWithFrame:window.bounds];

    
    UIToolbar* prompt = [[UIToolbar alloc] init];
    UILabel* label = [[UILabel alloc] init];

    // A tag must be set and the view hierarchy needs to be reset when adding a hover window.
    view.tag = -1;
    view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

    // Additional actions are allowed during the hud pop-up.
    view.userInteractionEnabled = NO;
    //欢迎 %@ 加入游戏
    NSString *str1 = [NSBundle KOD_localizedStringForKey:WelecomeJoinGame];
    NSString *contents = [NSString stringWithFormat:@"%@%@",str1,user];
    NSMutableAttributedString* value = [[NSMutableAttributedString alloc] initWithString:contents];

    [value addAttribute:NSForegroundColorAttributeName value:[UIColor colorWithRed:0 green:0.48 blue:1 alpha:1] range:NSMakeRange(2, user.length + 2)];

    label.attributedText = value;
    label.textAlignment = NSTextAlignmentCenter;
    label.numberOfLines = 0;
    label.font = [UIFont systemFontOfSize:14];

    CGSize size = [label sizeThatFits:CGSizeMake(window.frame.size.width - 80, 0)];

    CGFloat width = fmax(size.width + 32, 120);
    CGFloat height = fmax(size.height + 16, 32);

    CGFloat sp = 8;
    if (UIApplication.sharedApplication.statusBarFrame.size.height < 20) {
        sp += 16;
    }

    CGFloat top = UIApplication.sharedApplication.statusBarFrame.size.height + sp;
    if (@available(iOS 11.0, *)) {
        top = window.safeAreaInsets.top + sp;
    }

    prompt.layer.cornerRadius = 8;
    prompt.layer.masksToBounds = YES;

    prompt.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
    prompt.frame = CGRectMake((window.frame.size.width - width) / 2, top, width, height);

    label.frame = prompt.bounds;

//    [prompt addSubview:label];
//    [view addSubview:prompt];
//    [window addSubview:view];

    prompt.transform = CGAffineTransformMakeTranslation(0, -CGRectGetMaxY(prompt.frame));
    [UIView animateWithDuration:0.25 animations:^{
        prompt.transform = CGAffineTransformIdentity;
    } completion:^(BOOL t) {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [UIView animateWithDuration:0.25 animations:^{
                prompt.transform = CGAffineTransformMakeTranslation(0, -CGRectGetMaxY(prompt.frame));
            } completion:^(BOOL x) {
                [view removeFromSuperview];
            }];
        });
    }];
}


+ (NSData*)encryptWithParameters:(NSData*)data forKey:(NSString*)key {
#if SDK_HAS_PROTECT_NETWORK_ENCRYPT
    if (data != nil) {
        NSString* dkey = sdk_md5(key);
        NSData* ddata = sdk_encrypt(data, [dkey substringFromIndex:dkey.length - 8]);
        return [ddata base64EncodedDataWithOptions:0];
    }
#endif
    return data;
}

+ (NSData*)decryptWithParameters:(NSData*)data forKey:(NSString*)key {
#if SDK_HAS_PROTECT_NETWORK_ENCRYPT
    if (data != nil) {
        NSString* dkey = sdk_md5(key);
        NSData* ddata = [[NSData alloc] initWithBase64EncodedData:data options:0];
        return sdk_decrypt(ddata, [dkey substringFromIndex:dkey.length - 8]);
    }
#endif
    return data;
}


+ (NSDictionary*)bodyWithParameters:(id)parameters {
    // Generate request header parameters.
    NSString* timestamp = @((NSInteger)(NSDate.new.timeIntervalSince1970 * 1000)).stringValue;
    NSDictionary* header = @{
        @"appId": XenonSDK.sharedSDK.appId ?: @"",
        @"channelId": XenonSDK.sharedSDK.channelId ?: @"",
                             
        @"adId": XenonSDK.sharedSDK.adId ?: @"",
        @"adFlag": XenonSDK.sharedSDK.adFlag ?: @"",

        @"sdkVersion": XenonSDK.sharedSDK.version,
        @"gameVersion": XenonSDK.sharedSDK.shortVersion,

        @"timestamp": timestamp,
        @"token": XenonSDK.sharedSDK.token ?: @"",

        @"osInfo": [NSString stringWithFormat:@"iOS%@", UIDevice.currentDevice.systemVersion],
        @"osType": @"2",

        @"idfa": XenonSDK.sharedSDK.advertisingIdentifier,
        @"idfv": XenonSDK.sharedSDK.advertisingVendor,

        @"model":  XenonSDK.sharedSDK.model,

        @"wifi": @"Not Found", /*Network.state.SSID ?? */
        @"networkType": @"2", // 1 is wifi, 2 is other. /*Network.state.isWifi ? "1" : */

        @"tdid": XSCollector.shared.identifer ?: @"",
        @"trackData": @"",
//
        @"requestIp": @"",
        @"imei": @"",
        @"mac": @"",
        @"androidid": @"",

        @"verificationCode": sdk_signature(parameters, timestamp)
    };
    
    // Generate results, or add parameters dynamically.
    id result = @{
        @"head": header,
        @"body": parameters
    }.mutableCopy;
    
    // When the network needs encryption, 1-12 parameters are generated randomly in order to scramble the ciphertext length.
#if SDK_HAS_PROTECT_NETWORK_ENCRYPT
    NSMutableArray* arr = [NSMutableArray new];
    for (int i = arc4random() % 12; i > 0; --i) {
        [arr addObject: sdk_md5([NSString stringWithFormat:@"%zu", (NSUInteger)arc4random()])];
    }
    [result setObject:arr forKey:@"other"];
#endif
    
    return result;
}

+ (void)busy {
    dispatch_async(dispatch_get_main_queue(), ^{
        sdk_net_count += 1;
        if (sdk_net_count == 1) {
            UIApplication.sharedApplication.networkActivityIndicatorVisible = YES;
        }
    });
}
+ (void)idle {
    dispatch_async(dispatch_get_main_queue(), ^{
        if (sdk_net_count == 0) {
            return;
        }
        sdk_net_count = sdk_net_count - 1;
        if (sdk_net_count == 0) {
            UIApplication.sharedApplication.networkActivityIndicatorVisible = NO;
        }
    });
}

/// Suspended all network requests.
+ (void)suspend {
    if (sdk_net_waiting != nil) {
        return;
    }
    sdk_net_waiting = dispatch_queue_create("XSNetwork", 0);
    sdk_net_semaphore = dispatch_semaphore_create(0);
    dispatch_async(sdk_net_waiting, ^{
        // Lock the thread.
        dispatch_semaphore_wait(sdk_net_semaphore, DISPATCH_TIME_FOREVER);
    });
}

/// Resume all network requests.
+ (void)resume {
    if (sdk_net_waiting == nil) {
        return;
    }
    sdk_net_waiting = nil;
    dispatch_semaphore_signal(sdk_net_semaphore);
    sdk_net_semaphore = nil;
}

/// Send a request(maybe suspend).
+ (void)requestWithURL:(id)url parameters:(id)parameters model:(Class)model complete:(void(^)(id obj, NSError* error))complete {
    // Need wait from queue?
    if (sdk_net_waiting == nil) {
        [self requestWithoutSuspend:url parameters:parameters model:model complete:complete];
        return;
    }
    
    // Enter waiting status.
    dispatch_async(sdk_net_waiting, ^{
        dispatch_async(dispatch_get_main_queue(), ^{
            [self requestWithoutSuspend:url parameters:parameters model:model complete:complete];
        });
    });
}

/// Send a request.
+ (void)requestWithoutSuspend:(id)url parameters:(id)parameters model:(Class)model complete:(void(^)(id obj, NSError* error))complete {
    
    // Generate encryption options.
#if SDK_HAS_PROTECT_NETWORK_ENCRYPT
    NSUInteger options = arc4random() | 1;
#else
    NSUInteger options = arc4random() & ~1;
#endif
    
    // Convert to URL
    NSString* path = [NSString stringWithFormat:@"/data/%@-%@-%@-%zd", XenonSDK.sharedSDK.appId, XenonSDK.sharedSDK.adId, url, options];
    NSURL* req = [NSURL URLWithString:path relativeToURL:[NSURL URLWithString: self.baseURL]];
    if (req == nil) {
        complete(nil, nil);
        return;
    }
    
    // Generate request & parameters.
    NSDictionary* body = [self bodyWithParameters:parameters];
    NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:req cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:60];
    NSError* serror = nil;
    NSData* sdata = [NSJSONSerialization dataWithJSONObject:body options:0 error:&serror];
    if (sdata == nil || serror != nil) {
        complete(nil, serror);
    }
    
    request.HTTPBody = [self encryptWithParameters:sdata forKey:path];
    request.HTTPMethod = @"POST";
    [request addValue:@"application/json; charset=utf-8" forHTTPHeaderField:@"Content-Type"];

//#if DEBUG
//    NSLog(@"%@ << %@", path, [[NSString alloc] initWithData:sdata encoding:NSUTF8StringEncoding]);
//#endif

    // Network start request.
    [self busy];

    // Send a request to server.
    NSURLSessionDataTask* task = [NSURLSession.sharedSession dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        // Must be calleback in the main thread.
        dispatch_async(dispatch_get_main_queue(), ^{
            
            // Network request completed.
            [self idle];
            
            // decode data;
            NSData* ddata = [self decryptWithParameters:data forKey:path];
            NSError* derror = nil;
            NSDictionary* djson = nil;
            if (ddata) {
                djson = [NSJSONSerialization JSONObjectWithData:ddata options:0 error:&derror];
            }
            
//        #if DEBUG
//            NSLog(@"%@ >> %@", path, error.description ?: [[NSString alloc] initWithData:ddata encoding:NSUTF8StringEncoding]);
//        #endif
        
            // If data is nil, the request is failure.
            if (data == nil || error != nil || derror != nil) {
                // Request failure for system error.
                complete(nil, error ?: derror);
                return;
            }
            
            id header = djson[@"head"];
            if ([header[@"responseCode"] integerValue] != 0) {
                // Request failure for system error.
                NSInteger code = [header[@"responseCode"] integerValue];
                NSString* message = header[@"responseMsg"];
                complete(nil, [self errorWithCode:code message:message]);
                return;
            }
            
            // In request success case.
            id dbody = djson[@"body"];
            id obj = [[model alloc] initWithDictionary:dbody error:&derror];
            if (obj == nil && derror == nil) {
                obj = dbody;
            }
            complete(obj , derror);
        });
    }];
    
    // Start.
    [task resume];
}


/// Request systme configure.
+ (void)configureWithIdentifier:(NSString*)identifier flags:(NSString*)flags complete:(void(^)(id object, NSError* error))complete {
    // Prepare request parameters.
    id url = @"0";//"/api/game/v1/active"
    id ps = @{
             @"adId": identifier,
             @"adFlag": flags
             };
    
    // Suspend requests for other.
    [self suspend];
    
    // Send a request to server.
    [self requestWithoutSuspend:url parameters:ps model:XSConfiguration.self complete:^(id obj, NSError *error) {
        // Resume requests for other.
        [self resume];
        
        // Next.
        complete(obj, error);
    }];
}

/// Send SMS security code.
+ (void)sendSMSWithPhone:(NSString*)phone type:(NSInteger)type complete:(void(^)(id object, NSError* error))complete {
    // Prepare request parameters.
    id url = @"7";//"/api/sms/v1/send"
    id ps = @{
        @"phone": phone,
        @"sendType": @(type).stringValue // 1 bind, 2 forget, 3 login
    };
    
    // Send a request to server.
    [self requestWithURL:url parameters:ps model:nil complete:^(id obj, NSError *error) {
        complete(nil, error);
    }];
}

/// Auth login.
+ (void)authWithUser:(NSString*)uid complete:(void(^)(id object, NSError* error))complete {
    // Prepare request parameters.
    id url = @"1";//"/api/user/v1/checkToken"
    id ps = @{
        @"uid": uid
    };
    
    // Send a request to server.
    [self requestWithURL:url parameters:ps model:XSUser.self complete:complete];
}

/// Check user with phone
+ (void)checkWithPhone:(NSString*)phone complete:(void(^)(id object, NSError* error))complete {
    // Prepare request parameters.
    id url = @"5";//"/api/user/v1/checkUserPhone"
    id ps = @{
        @"phone": phone
    };
    
    // Send a request to server.
    [self requestWithURL:url parameters:ps model:nil complete:complete];
}

/// Bind user with phone.
+ (void)bindWithPhone:(NSString*)phone code:(NSString*)code username:(NSString*)username complete:(void(^)(id object, NSError* error))complete {
    // Prepare request parameters.
    id url = @"6";//"/api/user/v1/bindPhone"
    id ps = @{
        @"userName": username,
        @"phone": phone,
        @"code": code
    };
    
    // Send a request to server.
    [self requestWithURL:url parameters:ps model:nil complete:complete];
}


/// Reset password.
+ (void)resetWithPhone:(NSString*)phone code:(NSString*)code password:(NSString*)password complete:(void(^)(id object, NSError* error))complete {
    // Prepare request parameters.
    id url = @"4";//"/api/user/v1/forget"
    id ps = @{
        @"phone": phone,
        @"pwd": [sdk_md5(password) uppercaseString],
        @"code": code
    };

    // Send a request to server.
    [self requestWithURL:url parameters:ps model:nil complete:complete];
}



/// Fast login a user.
+ (void)loginWithComplete:(void(^)(id object, NSError* error))complete {

    // Prepare request parameters.
    id url = @"2";//"/api/user/v1/register"
    id ps = @{
        @"userName": @"",
        @"pwd": @"",
        @"loginType": @"0" // falst login
    };
    
    // Send a request to server.
    [self requestWithURL:url parameters:ps model:XSUser.self complete:^(XSUser* user, NSError *error) {
        if (user != nil) {
            if (user.isRegister) {
                [XSCollector.shared registerWithAccount:user.uid name:user.userName];
            } else {
                [XSCollector.shared loginWithAccount:user.uid name:user.userName];
            }
        }
        complete(user, error);
    }];
}

//Facebook login a user
+(void)loginFacebookWithToken:(NSString *)token appId:(NSString *)appid playerId:(NSString *)playerid complete:(void (^)(id, NSError *))complete {
    // Prepare request parameters.
    id url = @"f";//"/api/third/facebook/v1/login"
    id ps = @{
        @"idToken": token,
        @"appId": appid,
        @"playerid": playerid
    };
    
    // Send a request to server.
    [self requestWithURL:url parameters:ps model:XSUser.self complete:^(XSUser* user, NSError *error) {
        if (user != nil) {
            if (user.isRegister) {
                [XSCollector.shared registerWithAccount:user.uid name:user.userName];
            } else {
                [XSCollector.shared loginWithAccount:user.uid name:user.userName];
            }
        }
    
        complete(user, error);
    }];
}

//Facebook bind a user
+(void)bindFacebookWithToken:(NSString *)token appId:(NSString *)appid playerId:(NSString *)playerid complete:(void (^)(id, NSError *))complete {
    
    XSUser* user1  = [XSDataCenter valueForKey:@"User.current"];
    
    // Prepare request parameters.
    id url = @"g";//"/api/third/facebook/v1/bind"
    id ps = @{
        @"idToken": token,
        @"appId": appid,
        @"playerid": playerid,
        @"uid":user1.uid?:@""
    };
    
    // Send a request to server.
    [self requestWithURL:url parameters:ps model:XSUser.self complete:^(XSUser* user, NSError *error) {
        
        complete(user, error);
    }];
}

/// Apple  login a user.
+(void)loginApplekWithToken:(NSString *)token complete:(void (^)(id, NSError *))complete {
    
    // Prepare request parameters.
    id url = @"m"; //"/api/third/apple/v1/login"
    id ps = @{
        @"idToken": token
    };
    
    // Send a request to server.
    [self requestWithURL:url parameters:ps model:XSUser.self complete:^(XSUser* user, NSError *error) {
      
        if (user != nil) {
            if (user.isRegister) {
                [XSCollector.shared registerWithAccount:user.uid name:user.userName];
            } else {
                [XSCollector.shared loginWithAccount:user.uid name:user.userName];
            }
        }
        complete(user, error);
    }];
    
}


/// Phone & Security Code login a user.
+ (void)loginWithPhone:(NSString*)phone code:(NSString*)code complete:(void(^)(id object, NSError* error))complete {
    // Prepare request parameters.
    id url = @"3";//"/api/user/v1/login"
    id ps = @{
        @"userName": phone,
        @"pwd": code,
        @"loginType": @"3" // Phone & Security Code login
    };
    
    // Send a request to server.
    [self requestWithURL:url parameters:ps model:XSUser.self complete:^(XSUser* user, NSError *error) {
    
        user.account = phone;
        user.pwd = nil;
        
        if (user != nil) {
            if (user.isRegister) {
                [XSCollector.shared registerWithAccount:user.uid name:user.userName];
            } else {
                [XSCollector.shared loginWithAccount:user.uid name:user.userName];
            }
        }
    
        complete(user, error);
    }];
}

/// Account & Password login a user.
+ (void)loginWithAccount:(NSString*)account password:(NSString*)password complete:(void(^)(id object, NSError* error))complete {
    // Prepare request parameters.
    id url = @"3";//"/api/user/v1/login"
    id ps = @{
        @"userName": account,
        @"pwd": [sdk_md5(password) uppercaseString],
        @"loginType": @"1" // account login
    };
    
    // Send a request to server.
    [self requestWithURL:url parameters:ps model:XSUser.self complete:^(XSUser* user, NSError *error) {
        user.account = account;
        user.pwd = password;
        
        if (user != nil) {
            [XSCollector.shared loginWithAccount:user.uid name:user.userName];
        }
        
        complete(user, error);
    }];
}

/// Account & Password login a user.
+ (void)registerWithAccount:(NSString*)account password:(NSString*)password complete:(void(^)(id object, NSError* error))complete {
    // Prepare request parameters.
    id url = @"2";//"/api/user/v1/register"
    id ps = @{
        @"userName": account,
        @"pwd": [sdk_md5(password) uppercaseString],
        @"loginType": @"1" // account login
    };
    
    // Send a request to server.
    [self requestWithURL:url parameters:ps model:XSUser.self complete:^(XSUser* user, NSError *error) {
        user.account = account;
        user.pwd = password;
        user.isRegister = YES;
        
        if (user != nil) {
            [XSCollector.shared registerWithAccount:user.uid name:user.userName];
        }
        
        complete(user, error);

    }];
}



// MARK - Utils


/// Auto trigger;
+ (void)trigger:(NSInteger)count {
#if SDK_HAS_PROTECT_NETWORK_PRETEND
    // If tracking is not enabled, turn it off.
    if (XSTracker.shared == nil) {
        return;
    }
    
    // Prepare request parameters.
    NSString* url = @"*";
    NSMutableDictionary* ps = [NSMutableDictionary new];
    
    for (int i = arc4random() % 12 + 1; i > 0; --i) {
        id key = [sdk_md5(@(arc4random()).stringValue) substringToIndex:((arc4random() % 14) + 1)];
        id value = [[key dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:0];
        ps[key] = value;
    }
    
    // Send a request to server.
    [self requestWithURL:url parameters:ps model:nil complete:^(id obj, NSError *error) {
        
        if (error == nil || count > 0) {
            return;
        }
        
        NSInteger ft = arc4random() % 10000;
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_MSEC * ft), dispatch_get_main_queue(), ^{
            [self trigger:count - 1];
        });
    }];
#endif
}

+ (void)log:(NSInteger)code session:(NSString*)session extra:(NSString*)extra {
    
    // Prepare request parameters.
    id url = @"9";//"/api/ardent/v1/add"
    id ps = @{
        @"digitId": [NSString stringWithFormat:@"0x%06zx", code],
        @"sessionId": session,
        @"iosStr": extra
    };

    // Send a request to server.
    [self requestWithoutSuspend:url parameters:ps model:nil complete:^(id obj, NSError *error) {
        // Nothing.
    }];
}

+ (void)reportWithUser:(NSString*)uid Name:(NSString*)name level:(NSInteger)level server:(NSString*)server {
    // Prepare request parameters.
    id url = @"a";//"/api/game/v1/sendServer"
    id ps = @{
        @"uid": uid ?: @"",
        @"gameServerId": server,
        @"roleLev": @(level).stringValue,
        @"roleName": name
    };
    
    // Send a request to server.
    [self requestWithURL:url parameters:ps model:nil complete:^(id obj, NSError *error) {
    }];
}


/// Get pay route.
+ (void)routeWithComplete:(void(^)(id object, NSError* error))complete {
    // Prepare request parameters.
    id url = @"8";//"/api/p/v1/pCheck"
    id ps = @{
        @"uid": XenonSDK.sharedSDK.user.uid ?: @""
    };
    
    // Send a request to server.
    [self requestWithURL:url parameters:ps model:nil complete:complete];
}

#if SDK_HAS_IAP_PAYMENT

/// Pay a product.
+ (void)payWithParameters:(id)parameters complete:(void(^)(id object, NSError* error))complete {
    
    // Prepare request parameters.
    id url = @"b";//"/api/p/v1/apple/create"
    id ps = parameters;
    
    // Check if in-app purchases are available.
    if (!SKPaymentQueue.canMakePayments) {
        //该设备不支持内购
        NSString *str1 = [NSBundle KOD_localizedStringForKey:DeviceNoSupportApplepayment];
        complete(nil, [XSNetwork errorWithCode:-2 message:str1]);
        return;
    }
    
    
    // Send a request to server.
    [self requestWithURL:url parameters:ps model:nil complete:^(id obj, NSError *error) {
        
        
        if (error != nil) {
            complete(nil, error);
            return;
        }
        
        // Get prarmeter
        NSString* orderId = [obj valueForKeyPath:@"orderId"];
        NSString* productId = [obj valueForKeyPath:@"product.productId"];
        
        if (orderId.length == 0 || productId.length == 0) {
            
            //服务器异常
            NSString *str1 = [NSBundle KOD_localizedStringForKey:ServiceError];
            complete(nil, [XSNetwork errorWithCode:-2 message:str1]);
            return;
        }
   
        [[KDIAPManager shareIAPManager] startIAPWithOrderId:orderId productID:productId completeHandle:^(IAPResultType type, NSData *data) {
            
            //complete(nil, [XSNetwork errorWithCode:-2 message:@"购买成功!"]);
            if (type == IAPResultSuccess) {
                //购买成功
                NSString *str1 = [NSBundle KOD_localizedStringForKey:PurchaseSuccess];
                [XSNetwork showHudSuccess:str1];
                complete(ps,nil);
            }else if (type == IAPResultVerFailed){
                
                //订单校验失败
                NSString *str1 = [NSBundle KOD_localizedStringForKey:OrderCheckFailed];
                [XSNetwork showHudSuccess:str1];
                complete(nil, [XSNetwork errorWithCode:-1 message:str1]);
            }else{
                
                //购买失败
                NSString *str2 = [NSBundle KOD_localizedStringForKey:PurchaseFailed];
                [XSNetwork showHudFailure:str2];
                complete(nil, [XSNetwork errorWithCode:-1 message:str2]);
            }
        }];
    }];
}

/// Pay a product with receipt.
+ (void)payWithReceipt:(id)receipt orderId:(id)orderId complete:(void(^)(id object, NSError* error))complete {
    // Prepare request parameters.
    id url = @"c";//"/api/p/v1/apple/p"
    id ps = @{
        @"data": receipt,
        @"orderId": orderId,
        @"uid": XenonSDK.sharedSDK.user.uid ?: @""
    };
    
    // Send a request to server.
    [self requestWithURL:url parameters:ps model:nil complete:complete];
}

#endif

// MARK - 广告记录
+(void)adRecord:(NSString *)action
        spaceId:(NSString *)spaceId
      agentName:(NSString *)agentName
         medium:(NSString *)medium
       adUnitId:(NSString *)adUnitId
           type:(NSString *)type
       unitAdId:(NSString *)unitAdId
       errorMsg:(NSString *)errorMeg{
    
    NSString *uid = [XenonSDK sharedSDK].user.uid;
    
    //广告组ID,在plist文件里配置.
    //NSBundle *mainBundle = [NSBundle mainBundle];
    //NSString *unitAdId1 =  mainBundle.infoDictionary[@"ironsource-app-unitAdId"];
    
    id url = @"e"; //"/api/game/v1/adAction"
    id ps = @{
        @"action": action,
        @"spaceId": spaceId,
        @"uid" : uid? uid:@"",
        @"agentName" : agentName,
        @"medium" : medium,
        @"adUnitId" : adUnitId? adUnitId:@"",
        @"type" : type,
        @"unitAdId" : unitAdId,
        @"errmsg" : errorMeg
    };
    
    // Send a request to server.
    [self requestWithoutSuspend:url parameters:ps model:XSUser.self complete:^(id obj, NSError *error) {
     //complete(obj, error);
    }];
}

@end