//
//  SMAAdMobSmaatoRewardedVideoAdapter.m
//  SmaatoSDKAdapters
//
//  Created by Smaato Inc on 06.03.19.
//  Copyright © 2019 Smaato Inc. All rights reserved.￼
//  Licensed under the Smaato SDK License Agreement￼
//  https://www.smaato.com/sdk-license-agreement/
//

#import <GoogleMobileAds/GoogleMobileAds.h>
#import <SmaatoSDKRewardedAds/SmaatoSDKRewardedAds.h>
#import "SMAAdMobSmaatoRewardedVideoAdapter.h"

static NSString *const kSMAAdMobCustomEventInfoAdSpaceIdKey = @"adspaceId";
static NSString *const kSMAAdMobVideoRewardedVideoAdapterVersion = @"1.0.3";

@interface SMAAdMobSmaatoRewardedVideoAdapter () <SMARewardedInterstitialDelegate, GADMRewardBasedVideoAdNetworkAdapter>
@property (nonatomic) SMARewardedInterstitial *rewardedAd;
@property (nonatomic, weak) id<GADMRewardBasedVideoAdNetworkConnector> adMobConnector;
@property (nonatomic, copy) NSString *adspaceId;
@end

@implementation SMAAdMobSmaatoRewardedVideoAdapter

+ (NSString *)version
{
    return [self adapterVersion];
}

- (instancetype)initWithRewardBasedVideoAdNetworkConnector:(id<GADMRewardBasedVideoAdNetworkConnector>)connector
{
    if (!connector) {
        return nil;
    }

    self = [super init];
    if (self) {
        self.adMobConnector = connector;
    }
    return self;
}

- (void)setUp
{
    NSString *parameter = [self.adMobConnector.credentials objectForKey:GADCustomEventParametersServer];

    // Extract key-value pairs from passed server parameter string
    NSDictionary *info = [self dictionaryFromServerParameter:parameter];

    // Extract ad space information
    self.adspaceId = [self fetchValueForKey:kSMAAdMobCustomEventInfoAdSpaceIdKey fromEventInfo:info];

    // Verify ad space information
    if (![self checkCredentialsWithAdSpaceId:self.adspaceId]) {
        NSString *description = @"AdSpaceId can not be extracted. Please check your configuration on AdMob dashboard.";
        NSLog(@"[SmaatoSDK] [Error] %@: %@", [self smaatoMediationNetworkName], description);
        NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : description, NSLocalizedFailureReasonErrorKey : description };
        NSError *error = [NSError errorWithDomain:@"com.smaaato.SMAAdMobSmaatoRewardedVideoAdapter" code:0 userInfo:userInfo];
        if ([self.adMobConnector respondsToSelector:@selector(adapter:didFailToSetUpRewardBasedVideoAdWithError:)]) {
            [self.adMobConnector adapter:self didFailToSetUpRewardBasedVideoAdWithError:error];
        }
        return;
    }

    // Pass user location
    if (self.adMobConnector.userHasLocation) {
        SMALocation *userLocation = [[SMALocation alloc] initWithLatitude:self.adMobConnector.userLatitude
                                                                longitude:self.adMobConnector.userLongitude
                                                       horizontalAccuracy:self.adMobConnector.userLocationAccuracyInMeters
                                                                timestamp:[NSDate date]];
        SmaatoSDK.userLocation = userLocation;
    }

    // OPTIONAL: Pass mediation information
    /**
     Optional: You can also set specific user profile targeting parameters here.
     Please check the Smaato wiki for all available properties and further details.

     Examples:
     SmaatoSDK.userAge = 30;
     SmaatoSDK.userGender = kSMAGenderMale;
     */

    SMARewardedInterstitial.mediationNetworkName = [self smaatoMediationNetworkName];
    SMARewardedInterstitial.mediationAdapterVersion = kSMAAdMobVideoRewardedVideoAdapterVersion;
    SMARewardedInterstitial.mediationNetworkSDKVersion = [NSString stringWithFormat:@"%s", GoogleMobileAdsVersionString];

    if ([self.adMobConnector respondsToSelector:@selector(adapterDidSetUpRewardBasedVideoAd:)]) {
        [self.adMobConnector adapterDidSetUpRewardBasedVideoAd:self];
    }
}

- (NSString *)fetchValueForKey:(NSString *)definedKey fromEventInfo:(NSDictionary *)info
{
    __block NSString *value;
    [info enumerateKeysAndObjectsUsingBlock:^(NSString *_Nonnull key, id _Nonnull obj, BOOL *_Nonnull stop) {
        if ([definedKey caseInsensitiveCompare:key] == NSOrderedSame) {
            value = obj;
            *stop = YES;
        }
    }];
    return value;
}

- (void)requestRewardBasedVideoAd
{
    if (self.rewardedAd.availableForPresentation) {
        if ([self.adMobConnector respondsToSelector:@selector(adapterDidReceiveRewardBasedVideoAd:)]) {
            [self.adMobConnector adapterDidReceiveRewardBasedVideoAd:self];
        }
    } else {
        NSString *description = @"Failed to load ad.";
        NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : description, NSLocalizedFailureReasonErrorKey : description };
        NSError *error = [NSError errorWithDomain:@"com.smaaato.SMAAdMobSmaatoRewardedVideoAdapter" code:0 userInfo:userInfo];
        if ([self.adMobConnector respondsToSelector:@selector(adapter:didFailToLoadRewardBasedVideoAdwithError:)]) {
            [self.adMobConnector adapter:self didFailToLoadRewardBasedVideoAdwithError:error];
        }

        // Preload new one
        [SmaatoSDK loadRewardedInterstitialForAdSpaceId:self.adspaceId delegate:self];
    }
}

- (void)presentRewardBasedVideoAdWithRootViewController:(UIViewController *)viewController
{
    if (self.rewardedAd.availableForPresentation) {
        // The reward based video ad is available, present the ad.
        [self.rewardedAd showFromViewController:viewController];
    } else {
        // Because publishers are expected to check that an ad is available before
        // trying to show one, the above conditional should always hold true. If for
        // any reason the adapter is not ready to present an ad, however, it should
        // log an error with reason for failure.
        NSLog(@"No ads to show.");
    }
}

+ (NSString *)adapterVersion
{
    return kSMAAdMobVideoRewardedVideoAdapterVersion;
}

+ (Class<GADAdNetworkExtras>)networkExtrasClass
{
    return nil;
}

- (void)stopBeingDelegate
{
    // TODO nothing
}

- (NSDictionary *)dictionaryFromServerParameter:(NSString *)serverParameter
{
    NSMutableDictionary *parsedServerParameters = [NSMutableDictionary new];
    [[serverParameter componentsSeparatedByString:@"&"]
        enumerateObjectsUsingBlock:^(NSString *_Nonnull obj, NSUInteger idx, BOOL *_Nonnull stop) {
            NSArray *pair = [obj componentsSeparatedByString:@"="];
            if (pair.count > 1) {
                id key = pair[0];
                id value = pair[1];
                parsedServerParameters[key] = value;
            }
        }];

    return [parsedServerParameters copy];
}

- (NSString *)smaatoMediationNetworkName
{
    return NSStringFromClass([self class]);
}

- (BOOL)checkCredentialsWithAdSpaceId:(NSString *)adSpaceId
{
    if (adSpaceId) {
        return YES;
    }
    return NO;
}

#pragma mark - SMARewardedInterstitialDelegate

- (void)rewardedInterstitialDidFail:(SMARewardedInterstitial *)rewardedInterstitial withError:(NSError *)error
{
    if ([self.adMobConnector respondsToSelector:@selector(adapter:didFailToLoadRewardBasedVideoAdwithError:)]) {
        [self.adMobConnector adapter:self didFailToLoadRewardBasedVideoAdwithError:error];
    }
}

- (void)rewardedInterstitialDidLoad:(SMARewardedInterstitial *)rewardedInterstitial
{
    self.rewardedAd = rewardedInterstitial;
    if ([self.adMobConnector respondsToSelector:@selector(adapterDidReceiveRewardBasedVideoAd:)]) {
        [self.adMobConnector adapterDidReceiveRewardBasedVideoAd:self];
    }
}

- (void)rewardedInterstitialDidReward:(SMARewardedInterstitial *)rewardedInterstitial
{
    // Smaato doesn't retrieve exact reward (currency and amount) after video ad completion, due to this reason
    // publisher receives AdMobRewardedVideoAdapterViewController() callback with default GADAdReward value ( amount = 1 )
    if ([self.adMobConnector respondsToSelector:@selector(adapter:didRewardUserWithReward:)]) {
        [self.adMobConnector adapter:self didRewardUserWithReward:nil];
    }
}

- (void)rewardedInterstitialDidTTLExpire:(SMARewardedInterstitial *)rewardedInterstitial
{
    NSString *description = @"Failed to show a rewarded video ad as the ad has expired. Please make a new ad request. ";
    NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : description, NSLocalizedFailureReasonErrorKey : description };
    NSError *error = [NSError errorWithDomain:@"com.smaaato.SMAAdMobSmaatoRewardedVideoAdapter" code:0 userInfo:userInfo];
    if ([self.adMobConnector respondsToSelector:@selector(adapter:didFailToLoadRewardBasedVideoAdwithError:)]) {
        [self.adMobConnector adapter:self didFailToLoadRewardBasedVideoAdwithError:error];
    }
}

- (void)rewardedInterstitialWillAppear:(SMARewardedInterstitial *)rewardedInterstitial
{
    // No corresponding method from AdMob SDK available.
}

- (void)rewardedInterstitialDidAppear:(SMARewardedInterstitial *)rewardedInterstitial
{
    if ([self.adMobConnector respondsToSelector:@selector(adapterDidOpenRewardBasedVideoAd:)]) {
        [self.adMobConnector adapterDidOpenRewardBasedVideoAd:self];
    }
}

- (void)rewardedInterstitialWillDisappear:(SMARewardedInterstitial *)rewardedInterstitial
{
    // No corresponding method from AdMob SDK available.
}

- (void)rewardedInterstitialDidDisappear:(SMARewardedInterstitial *)rewardedInterstitial
{
    if ([self.adMobConnector respondsToSelector:@selector(adapterDidCloseRewardBasedVideoAd:)]) {
        [self.adMobConnector adapterDidCloseRewardBasedVideoAd:self];
    }

    // Preload new one
    [SmaatoSDK loadRewardedInterstitialForAdSpaceId:self.adspaceId delegate:self];
}

- (void)rewardedInterstitialDidStart:(SMARewardedInterstitial *)rewardedInterstitial
{
    if ([self.adMobConnector respondsToSelector:@selector(adapterDidStartPlayingRewardBasedVideoAd:)]) {
        [self.adMobConnector adapterDidStartPlayingRewardBasedVideoAd:self];
    }
}

- (void)rewardedInterstitialDidClick:(SMARewardedInterstitial *)rewardedInterstitial
{
    if ([self.adMobConnector respondsToSelector:@selector(adapterDidGetAdClick:)]) {
        [self.adMobConnector adapterDidGetAdClick:self];
    }
}

- (void)rewardedInterstitialWillLeaveApplication:(SMARewardedInterstitial *)rewardedInterstitial
{
    if ([self.adMobConnector respondsToSelector:@selector(adapterWillLeaveApplication:)]) {
        [self.adMobConnector adapterWillLeaveApplication:self];
    }
}

@end
