#import <Foundation/Foundation.h>

#import <SGSBase/SGSBase.h>
#import <SGSIAP/SGSIAP.h>
#import <SGSAuth/SGSAuth.h>

#import "IAPNativeInterface.h"

@interface SGSIAPPurchasedNotification : NSObject

@property (copy) NSString *identifier;

+ (SGSIAPPurchasedNotification *)sharedInstance;

@end

@implementation SGSIAPPurchasedNotification

+ (SGSIAPPurchasedNotification *)sharedInstance
{
    static SGSIAPPurchasedNotification *notification;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        notification = [[SGSIAPPurchasedNotification alloc] init];
    });
    
    return notification;
}

- (void)updatedPurchasesNotification:(NSNotification *)notification
{
    SGSResult *result = [notification.userInfo objectForKey:@"result"];
    SGSIAPProduct *product = [notification.userInfo objectForKey:@"product"];
    SGSIAPPurchaseDetail *purchaseDetail = [notification.userInfo objectForKey:@"purchaseDetail"];
    
    NSDictionary *resultDic = [NSDictionary dictionaryWithObjectsAndKeys:
                               [result dictionary], @"result",
                               [product dictionary], @"product",
                               [purchaseDetail dictionary], @"purchaseDetail",
                               nil];
    
    StoveSDKNativeNotifyPayload *payload =
    [StoveSDKNativeNotifyPayload notifyWithIdentifier:self.identifier value:resultDic];
    [payload notifyMessage];
}

@end

// MARK: - Extern APIs

void stove_iap_setCustomBillingGUID(const char *guid)
{
    NSString *nsGuid = StoveSDKMakeNSString(guid);
    
    [SGSIAP setCustomBillingGUID:nsGuid];
}

void stove_iap_initialize(const char *identifier) {
    NSString *nsIdentifier = StoveSDKMakeNSString(identifier);
    
    [SGSIAP initializeWithCompletionHandler:^(SGSResult * _Nonnull result) {
        NSDictionary *resultDic = [NSDictionary dictionaryWithObjectsAndKeys:
                                   [result dictionary], @"result",
                                   nil];
        
        StoveSDKNativeCallbackPayload *payload =
        [StoveSDKNativeCallbackPayload payloadWithIdentifier:nsIdentifier value:resultDic];
        [payload sendMessage];
    }];
}

void stove_iap_fetchProducts(const char *identifier) {
    NSString *nsIdentifier = StoveSDKMakeNSString(identifier);
    
    [SGSIAP fetchProductsWithCompletionHandler:^(SGSResult * _Nonnull result, NSArray<SGSIAPProduct *> * _Nullable productList)
    {
        NSMutableArray *mutableProducts = [NSMutableArray array];
        for (SGSIAPProduct *product in productList) {
            [mutableProducts addObject:[product dictionary]];
        }
        
        NSDictionary *resultDic = [NSDictionary dictionaryWithObjectsAndKeys:
                                   [result dictionary], @"result",
                                   mutableProducts, @"productList",
                                   nil];
        
        StoveSDKNativeCallbackPayload *payload =
        [StoveSDKNativeCallbackPayload payloadWithIdentifier:nsIdentifier value:resultDic];
        [payload sendMessage];
    }];
}

void stove_iap_startPurchaseWithProduct(const char *product, const char *identifier) {
    NSString *nsProduct = StoveSDKMakeNSString(product);
    NSString *nsIdentifier = StoveSDKMakeNSString(identifier);
    
    [SGSIAP startPurchaseWithProduct:[SGSIAPProduct productWithDictionary:[nsProduct JSONObject]]
                   completionHandler:^(SGSResult * _Nonnull result) {
        NSDictionary *resultDic = [NSDictionary dictionaryWithObjectsAndKeys:
                                   [result dictionary], @"result",
                                   nil];
        
        StoveSDKNativeCallbackPayload *payload =
        [StoveSDKNativeCallbackPayload payloadWithIdentifier:nsIdentifier value:resultDic];
        [payload sendMessage];
    }];
}

void stove_iap_startPurchase(const char *product, const char *serviceOrderId, const char *optional, const char *identifier)
{
    NSString *nsProduct = StoveSDKMakeNSString(product);
    NSString *nsServiceOrderId = StoveSDKMakeNSString(serviceOrderId);
    NSString *nsOptional = StoveSDKMakeNSString(optional);
    NSString *nsIdentifier = StoveSDKMakeNSString(identifier);
    
    [SGSIAP startPurchaseWithProduct:[SGSIAPProduct productWithDictionary:[nsProduct JSONObject]]
                      serviceOrderId:nsServiceOrderId
                            optional:[SGSIAPOptional optionalWithDictionary:[nsOptional JSONObject]]
                   completionHandler:^(SGSResult * _Nonnull result) {
        NSDictionary *resultDic = [NSDictionary dictionaryWithObjectsAndKeys:
                                   [result dictionary], @"result",
                                   nil];
        
        StoveSDKNativeCallbackPayload *payload =
        [StoveSDKNativeCallbackPayload payloadWithIdentifier:nsIdentifier value:resultDic];
        [payload sendMessage];
    }];
}

void stove_iap_setListener(const char *identifier) {
    NSString *nsIdentifier = StoveSDKMakeNSString(identifier);

    [[SGSIAPPurchasedNotification sharedInstance] setIdentifier:nsIdentifier];

    [[NSNotificationCenter defaultCenter] removeObserver:[SGSIAPPurchasedNotification sharedInstance] name:NSNotification.SGSPurchasesUpdatedNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:[SGSIAPPurchasedNotification sharedInstance]
                                             selector:@selector(updatedPurchasesNotification:)
                                                 name:NSNotification.SGSPurchasesUpdatedNotification
                                               object:nil];

    [SGSIAP prepareTransactionListener];
}

bool stove_iap_flush() {
    
    return [SGSIAP flush];
}

void stove_iap_consume(const char *product, const char *identifier)
{
    NSString *nsProduct = StoveSDKMakeNSString(product);
    NSString *nsIdentifier = StoveSDKMakeNSString(identifier);
    
    [SGSIAP consume:[SGSIAPProduct productWithDictionary:[nsProduct JSONObject]] completionHandler:^(SGSResult * _Nonnull result) {
        NSDictionary *resultDic = [NSDictionary dictionaryWithObjectsAndKeys:
                                   [result dictionary], @"result",
                                   nil];
        
        StoveSDKNativeCallbackPayload *payload =
        [StoveSDKNativeCallbackPayload payloadWithIdentifier:nsIdentifier value:resultDic];
        [payload sendMessage];
    }];
}

void stove_iap_fetchVoidedPurchases(const char *identifier) {
    NSString *nsIdentifier = StoveSDKMakeNSString(identifier);
    [SGSIAP fetchVoidedPurchasesWithCompletionHandler:^(SGSResult * _Nonnull result, NSArray * _Nullable voidedPurchases) {
        NSDictionary *resultDic = [NSDictionary dictionaryWithObjectsAndKeys:
                                   [result dictionary], @"result",
                                   voidedPurchases, @"voidedPurchases",
                                   nil];
        
        StoveSDKNativeCallbackPayload *payload =
        [StoveSDKNativeCallbackPayload payloadWithIdentifier:nsIdentifier value:resultDic];
        [payload sendMessage];
    }];
}

void stove_iap_handleVoidedPurchases(const char *identifier) {
    NSString *nsIdentifier = StoveSDKMakeNSString(identifier);
    [SGSIAP handleVoidedPurchasesFromViewController:nil completionHandler: ^(SGSResult * _Nonnull result) {
        NSDictionary *resultDic = [NSDictionary dictionaryWithObjectsAndKeys:
                                   [result dictionary], @"result",
                                   nil];
        
        StoveSDKNativeCallbackPayload *payload =
        [StoveSDKNativeCallbackPayload payloadWithIdentifier:nsIdentifier value:resultDic];
        [payload sendMessage];
    }];
}

const char *stove_iap_version() {
    NSString * version = [SGSIAP moduleVersion];
    return StoveSDKMakeCString(version);
}
