//
//  PersonalyBridge.mm
//  Personaly
//
//  Created by Mobexs on 8/8/17.
//
//

#import "PersonalyBridge.h"
#import <Personaly/Personaly-Swift.h>
#import "PersonalyCallbackReceiver.h"

@implementation PersonalyBridge

extern "C" {

    void _configure(const char* objectName, const char* appID, const char* parameters) {

        NSString *objectNameString = [NSString stringWithUTF8String:objectName];
        NSString *appIDString = [NSString stringWithUTF8String:appID];
        NSMutableDictionary *parametersDictionary = nil;
        if (parameters != nil) {

            NSString *parametersString = [NSString stringWithUTF8String:parameters];
            NSData *parametersData = [parametersString dataUsingEncoding:NSUTF8StringEncoding];
            parametersDictionary = [NSJSONSerialization JSONObjectWithData:parametersData options:NSJSONReadingMutableContainers error:nil];

            NSString *dateOfBirthString = [parametersDictionary valueForKey:@"dateOfBirth"];
            if (dateOfBirthString != nil) {

                NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
                dateFormatter.dateFormat = @"YYYY/MM/dd";
                NSDate *dateOfBirth = [dateFormatter dateFromString:dateOfBirthString];
                [parametersDictionary setValue:dateOfBirth forKey:@"dateOfBirth"];
            }
        }

        static PersonalyCallbackReceiver *delegate = [[PersonalyCallbackReceiver alloc] init];
        delegate.callerName = objectNameString;
        Personaly.delegate = delegate;

        [Personaly configureWithAppID:appIDString
                           parameters:parametersDictionary
                                queue:dispatch_get_main_queue()
                           completion:^(BOOL success, NSError * _Nullable error) {

                               NSDictionary *dictionary = nil;
                               NSString *callbackName = nil;
                               if (success == YES) {

                                   callbackName = @"ConfigureSuccess";

                               }
                               else {

                                   dictionary = @{ @"errorMessage": [error localizedDescription],
                                                   @"errorCode": @(error.code) };
                                   callbackName = @"ConfigureFailure";
                               }

                               const char* json = [PersonalyBridge jsonFromDictionary:dictionary];
                               UnitySendMessage([objectNameString UTF8String],
                                                [callbackName UTF8String],
                                                json);
                           }];
    }

    void _precacheCampaigns(const char* objectName, const char* placementID) {

        NSString *objectNameString = [NSString stringWithUTF8String:objectName];
        NSString *placementIDString = [NSString stringWithUTF8String:placementID];

        [Personaly precacheCampaignsForPlacement:placementIDString
                                           queue:dispatch_get_main_queue()
                                      completion:^(BOOL success, NSError * _Nullable error) {

                                          NSDictionary *dictionary = nil;
                                          NSString *callbackName = nil;
                                          if (success == YES) {

                                              dictionary = @{ @"placementId": placementIDString };
                                              callbackName = @"PrecacheCampaignCallback";

                                          }
                                          else {

                                              dictionary = @{ @"placementId": placementIDString,
                                                              @"errorMessage": [error localizedDescription],
                                                              @"errorCode": @(error.code) };
                                              callbackName = @"FailureCampaignCallback";
                                          }

                                          const char* json = [PersonalyBridge jsonFromDictionary:dictionary];
                                          UnitySendMessage([objectNameString UTF8String],
                                                           [callbackName UTF8String],
                                                           json);
                                      }];
    }

    void _showCampaign(const char* objectName, const char* placementID, const char* serverParameter) {

        NSString *objectNameString = [NSString stringWithUTF8String:objectName];
        NSString *placementIDString = [NSString stringWithUTF8String:placementID];

        PersonalyServerParameter *serverParameterObj = nil;

        if (serverParameter != nil) {

            NSString *serverParameterString = [NSString stringWithUTF8String:serverParameter];
            serverParameterObj = [[PersonalyServerParameter alloc] init];
            serverParameterObj.parameters = [PersonalyBridge dictionaryFromJSON:serverParameterString];
        }

        [Personaly showCampaignForPlacement:placementIDString
                            serverParameter:serverParameterObj
                                 completion:^(BOOL success, NSError * _Nullable error) {

                                     NSDictionary *dictionary = nil;
                                     NSString *callbackName = nil;
                                     if (success == YES) {

                                         dictionary = @{ @"placementId": placementIDString };
                                         callbackName = @"CloseCampaignCallback";

                                     }
                                     else {

                                         dictionary = @{ @"placementId": placementIDString,
                                                         @"errorMessage": [error localizedDescription],
                                                         @"errorCode": @(error.code) };
                                         callbackName = @"FailureCampaignCallback";
                                     }

                                     const char* json = [PersonalyBridge jsonFromDictionary:dictionary];
                                     UnitySendMessage([objectNameString UTF8String],
                                                      [callbackName UTF8String],
                                                      json);
                                 }];
    }

    void _showOfferWall(const char* objectName, const char* placementID, const char* serverParameter) {

        NSString *objectNameString = [NSString stringWithUTF8String:objectName];
        NSString *placementIDString = [NSString stringWithUTF8String:placementID];

        PersonalyServerParameter *serverParameterObj = nil;

        if (serverParameter != nil) {

            NSString *serverParameterString = [NSString stringWithUTF8String:serverParameter];
            serverParameterObj = [[PersonalyServerParameter alloc] init];
            serverParameterObj.parameters = [PersonalyBridge dictionaryFromJSON:serverParameterString];
        }

        [Personaly showOfferWallForPlacement:placementIDString
                             serverParameter:serverParameterObj
                                  completion:^(BOOL success, NSError * _Nullable error) {

                                      NSDictionary *dictionary = nil;
                                      NSString *callbackName = nil;
                                      if (success == YES) {

                                          dictionary = @{ @"placementId": placementIDString };
                                          callbackName = @"CloseOfferWallCallback";

                                      }
                                      else {

                                          dictionary = @{ @"placementId": placementIDString,
                                                          @"errorMessage": [error localizedDescription],
                                                          @"errorCode": @(error.code) };
                                          callbackName = @"FailureOfferWallCallback";
                                      }

                                      const char* json = [PersonalyBridge jsonFromDictionary:dictionary];
                                      UnitySendMessage([objectNameString UTF8String],
                                                       [callbackName UTF8String],
                                                       json);
                                  }];
    }

    void _precacheRewardablePopupTemplate(const char* objectName) {

        NSString *objectNameString = [NSString stringWithUTF8String:objectName];

        [Personaly precacheRewardablePopupTemplateWithQueue:dispatch_get_main_queue()
                                                 completion:^(BOOL success, NSError * _Nullable error) {

                                                     NSDictionary *dictionary = nil;
                                                     NSString *callbackName = nil;
                                                     if (success == YES) {

                                                         callbackName = @"PrecachePopupOfferCallback";

                                                     }
                                                     else {

                                                         dictionary = @{ @"errorMessage": [error localizedDescription],
                                                                         @"errorCode": @(error.code) };
                                                         callbackName = @"FailurePopupOfferCallback";
                                                     }

                                                     const char* json = [PersonalyBridge jsonFromDictionary:dictionary];
                                                     UnitySendMessage([objectNameString UTF8String],
                                                                      [callbackName UTF8String],
                                                                      json);
                                                 }];
    }

    void _showRewardablePopup(const char* objectName, const char* placementID, const char* serverParameter) {

        NSString *objectNameString = [NSString stringWithUTF8String:objectName];
        NSString *placementIDString = [NSString stringWithUTF8String:placementID];

        PersonalyServerParameter *serverParameterObj = nil;

        if (serverParameter != nil) {

            NSString *serverParameterString = [NSString stringWithUTF8String:serverParameter];
            serverParameterObj = [[PersonalyServerParameter alloc] init];
            serverParameterObj.parameters = [PersonalyBridge dictionaryFromJSON:serverParameterString];
        }

        [Personaly showRewardablePopupForPlacement:placementIDString
                                   serverParameter:serverParameterObj
                                        completion:^(BOOL success, NSError * _Nullable error) {

                                            NSDictionary *dictionary = nil;
                                            NSString *callbackName = nil;
                                            if (success == YES) {

                                                dictionary = @{ @"placementId": placementIDString };
                                                callbackName = @"ClosePopupOfferCallback";

                                            }
                                            else {

                                                dictionary = @{ @"placementId": placementIDString,
                                                                @"errorMessage": [error localizedDescription],
                                                                @"errorCode": @(error.code) };
                                                callbackName = @"FailurePopupOfferCallback";
                                            }

                                            const char* json = [PersonalyBridge jsonFromDictionary:dictionary];
                                            UnitySendMessage([objectNameString UTF8String],
                                                             [callbackName UTF8String],
                                                             json);
                                        }];
    }
    
    void _canView(const char* objectName, const char* placementID) {
        
        NSString *objectNameString = [NSString stringWithUTF8String:objectName];
        NSString *placementIDString = [NSString stringWithUTF8String:placementID];

        [Personaly canViewForPlacement:placementIDString
                                 queue:dispatch_get_main_queue()
                            completion:^(BOOL success, NSError * _Nullable error) {

                                NSDictionary *dictionary = nil;
                                NSString *callbackName = nil;
                                if (success == YES) {

                                    dictionary = @{ @"placementId": placementIDString,
                                                    @"canView": @(YES) };
                                    callbackName = @"CanViewCampaignCallback";

                                }
                                else {

                                    dictionary = @{ @"placementId": placementIDString,
                                                    @"canView": @(NO),
                                                    @"errorMessage": [error localizedDescription],
                                                    @"errorCode": @(error.code) };
                                    callbackName = @"CanViewCampaignCallback";
                                }

                                const char* json = [PersonalyBridge jsonFromDictionary:dictionary];
                                UnitySendMessage([objectNameString UTF8String],
                                                 [callbackName UTF8String],
                                                 json);
                            }];
    }

    void _precacheNativeAds(const char* objectName, const char* placementID, bool shouldDownloadAssets, const char* creativeType, int numberOfAdsToPrecache) {

        NSString *objectNameString = [NSString stringWithUTF8String:objectName];
        NSString *placementIDString = [NSString stringWithUTF8String:placementID];
        NSString *creativeTypeString = [NSString stringWithUTF8String:creativeType];

        PersonalyNativeAdOptions *optionsObj = [[PersonalyNativeAdOptions alloc] init];
        optionsObj.shouldDownloadAssets = shouldDownloadAssets;
        optionsObj.numberOfAdsToPrecache = numberOfAdsToPrecache;
        optionsObj.creativeType = creativeTypeString;

        [Personaly precacheNativeAdsForPlacement:placementIDString
                                         options:optionsObj
                                           queue:dispatch_get_main_queue()
                                      completion:^(NSArray<PersonalyNativeAd *> * _Nonnull nativeAds, NSError * _Nullable error) {

                                          NSMutableArray *nativeAdsJSONArray = [NSMutableArray array];
                                          for (PersonalyNativeAd* nativeAd in nativeAds)
                                          {
                                              NSDictionary *infoJSONDict = @{ @"adId": nativeAd.adID,
                                                                                  @"appName": nativeAd.appName,
                                                                                  @"appId": nativeAd.storeAppID,
                                                                                  @"landingPage": nativeAd.storeAppURL,
                                                                                  @"rating": @(nativeAd.rating),
                                                                                  @"reviews": @(nativeAd.reviewsCount),
                                                                                  @"categories": nativeAd.categories,
                                                                                  @"appDeveloper": nativeAd.appDeveloper,
                                                                                  @"appDescription": nativeAd.appDescription,
                                                                                  @"appIcon": nativeAd.appIconURL
                                                                                  };

                                              NSDictionary *privacyJSONDict = @{ @"url": nativeAd.privacyPolicyURL,
                                                                                  @"image": nativeAd.privacyPolicyImageURL
                                                                                  };

                                              NSMutableArray *assets = [NSMutableArray array];
                                              for (PersonalyNativeAdAsset *asset in nativeAd.assets) {

                                                  NSDictionary *assetJSONDict = @{ @"url": asset.URL,
                                                                                   @"type": asset.type,
                                                                                   @"filePath": asset.filePath,
                                                                                   @"width": @(asset.size.width),
                                                                                   @"height": @(asset.size.height)
                                                                                   };
                                                  [assets addObject:assetJSONDict];
                                              }

                                              NSDictionary *nativeAdJSONDict = @{ @"impressionId": nativeAd.impressionID,
                                                                                  @"info": infoJSONDict,
                                                                                  @"assets": assets,
                                                                                  @"cta": nativeAd.callToActionText,
                                                                                  @"trackingUrl": nativeAd.trackingURL,
                                                                                  @"privacyPolicy": privacyJSONDict
                                                                                  };
                                              [nativeAdsJSONArray addObject:nativeAdJSONDict];
                                          }

                                          NSDictionary *dictionary = nil;
                                          NSString *callbackName = nil;
                                          if (error == nil) {

                                              dictionary = @{ @"placementId": placementIDString,
                                                              @"result": nativeAdsJSONArray
                                                              };
                                              callbackName = @"PrecacheNativeCallback";
                                          }
                                          else {

                                              dictionary = @{ @"placementId": placementIDString,
                                                              @"errorMessage": [error localizedDescription],
                                                              @"errorCode": @(error.code) };
                                              callbackName = @"FailureNativeCallback";
                                          }

                                          const char* json = [PersonalyBridge jsonFromDictionary:dictionary];
                                          UnitySendMessage([objectNameString UTF8String],
                                                           [callbackName UTF8String],
                                                           json);
                                      }];
    }

    void _reportNativeAdImpression(const char* impressionID) {

        NSString *impressionIDString = [NSString stringWithUTF8String:impressionID];
        [Personaly reportNativeAdImpressionWithImpressionID:impressionIDString];
    }

    void _reportNativeAdClick(const char* impressionID, const char* serverParameter) {

        NSString *impressionIDString = [NSString stringWithUTF8String:impressionID];

        PersonalyServerParameter *serverParameterObj = nil;

        if (serverParameter != nil) {

            NSString *serverParameterString = [NSString stringWithUTF8String:serverParameter];
            serverParameterObj = [[PersonalyServerParameter alloc] init];
            serverParameterObj.parameters = [PersonalyBridge dictionaryFromJSON:serverParameterString];
        }

        [Personaly reportNativeAdClickWithImpressionID:impressionIDString serverParameter:serverParameterObj];
    }

    void _reportNativeAdVideoStarted(const char* impressionID) {

        NSString *impressionIDString = [NSString stringWithUTF8String:impressionID];
        [Personaly reportNativeAdVideoStartedWithImpressionID:impressionIDString];
    }

    void _reportNativeAdVideoEnded(const char* impressionID) {

        NSString *impressionIDString = [NSString stringWithUTF8String:impressionID];
        [Personaly reportNativeAdVideoEndedWithImpressionID:impressionIDString];
    }

    void _setAutocaching(bool value) {

        [Personaly setAutoCaching:value];
    }

    bool _isCampaignReady(const char*  placementID) {

        NSString *placementIDString = [NSString stringWithUTF8String:placementID];
        return [Personaly isCampaignReadyWithPlacementID:placementIDString];
    }
}

+ (const char*)jsonFromDictionary:(NSDictionary *)dictionary {

    if (dictionary == nil) {

        return "";
    }

    NSError *error = nil;
    NSData *data = [NSJSONSerialization dataWithJSONObject:dictionary options:NSJSONWritingPrettyPrinted error:&error];

    if (error != nil) {

        return "";
    }
    else {

        NSString * string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        return [string UTF8String];
    }
}

+ (NSDictionary *)dictionaryFromJSON:(NSString *)json {

    if (json != nil) {

        NSData *jsonData = [json dataUsingEncoding:NSUTF8StringEncoding];
        NSError *error = nil;
        NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONWritingPrettyPrinted error:&error];
        if (error == nil) {

            return dictionary;
        }
    }
    return nil;
}

@end
