//
//  AdPlugin.m
//  TestDemo
//
//  Created by 兵伍 on 2020/8/3.
//

#import "AdPlugin.h"
#import <MobADSDK/MobADSDK.h>
#import "ADH5Tool.h"
#import "LaunchPlaceHolder.h"
#import "SplashLogoView.h"
#import "AppDelegate.h"

@interface AdPlugin()<MADRewardVideoAdCallbackDelegate, MADInterstitialAdCallbackDelegate, MADBannerAdCallbackDelegate, MADSplashAdCallbackDelegate>

@property (nonatomic, strong) NSString *rvCallback;
@property (nonatomic, strong) NSString *interCallback;

@property (nonatomic, strong) id<MADBannerAdManagerProtocol> bannerAd;
@property (nonatomic, strong) id<MADRewardVideoAdManagerProtocol> rewardVideo;

@property (nonatomic, strong) NSMutableDictionary *bannerCallbackDict;
@property (nonatomic, strong) NSMutableDictionary *bannerViewDict;
@property (nonatomic, strong) UIView *splashView;

@property (nonatomic, strong) NSXMLParser *configParser;
@property (nonatomic, strong) NSString *appId;
@property (nonatomic, strong) NSString *splashLogo;
@end

@implementation AdPlugin

- (void)setupADSDK {
    
    // 创建初始化配置实例
    MobADConfigModel *config = [[MobADConfigModel alloc] init];
    
    config.appId = self.appId;
    
    // 初始化SDK
    BOOL result = [MobADSDKApi setupWithConfig:config];
    
    MobADConfigModel *config2 = [MobADSDKApi getConfig];
    NSLog(@"userId:%@", config2.userId);
    NSLog(@"ADSDK setup success:%d", result);
    NSLog(@"ADSDK version:%@", [MobADSDKApi sdkVersion]);
}

- (void)showSplashAdFromLaunch:(BOOL)launch {
    NSString *splashLogoPath = self.splashLogo;
    if ([splashLogoPath hasPrefix:@"www/"]) {
        splashLogoPath = [[splashLogoPath componentsSeparatedByString:@"www/"] lastObject];
    }
    NSString *pa = [self.commandDelegate pathForResource:splashLogoPath];
    UIImage *logo = [UIImage imageWithContentsOfFile:pa];
    
    UIWindow *window = ((AppDelegate *)[self appDelegate]).window;
    
    // 开屏占位视图(加载开屏广告时的占位视图)
    LaunchPlaceHolder *placeHolder = [LaunchPlaceHolder loadViewFromXib];
    placeHolder.frame = window.bounds;
    
    // 开屏自定义logo视图(显示在开屏广告底部)
    SplashLogoView *logoView = [SplashLogoView loadViewFromXib];
    logoView.frame = CGRectMake(0, 0, window.bounds.size.width, floor(window.bounds.size.height/4.0));
    logoView.logoImgView.image = logo;
    
    // 加载开屏
    self.splashView = [MobADSDKApi splashAdViewFromWindow:window delegate:self placeHolder:placeHolder customView:logoView timeout:3 isLaunch:launch group:@"s1"];
}

#pragma mark - 开屏广告回调

- (void)ad_splashAdCallbackWithEvent:(MADSplashAdCallbackEvent)event error:(NSError *)error andInfo:(NSDictionary *)info {
    NSLog(@"splash event:%zd, error:%@, info:%@", event, error, info);
    
    if (event == MADSplashAdCallbackEventAdLoadSuccess) {
        // 保存上次开屏时间
        double ts = [[NSDate date] timeIntervalSince1970];
        NSLog(@"splash -> save ts:%lf", ts);
        [[NSUserDefaults standardUserDefaults] setDouble:ts forKey:@"AppLastSplashShownTimestamp"];
        [[NSUserDefaults standardUserDefaults] synchronize];
    }
    
    // 移除开屏
    if (event == MADSplashAdCallbackEventAdDidClose) {
        [self.splashView removeFromSuperview];
        self.splashView = nil;
    }
}

- (void)handleApplicationWillEnterForeground:(NSNotification *)notification {
    double last = [[NSUserDefaults standardUserDefaults] doubleForKey:@"AppLastSplashShownTimestamp"];
    double ts = [[NSDate date] timeIntervalSince1970];
    double delt = ts - last;
    
    NSLog(@"splash -> interval:%lf", delt);

    NSInteger interval = 3 * 60;// 3分钟间隔展示开屏
    if (interval <= 0) {
        return;
    }
    
    if (delt >= interval) {
        NSLog(@"splash -> should show");
        [self showSplashAdFromLaunch:NO];
    }
}

- (void)pluginInitialize {
    NSLog(@"AdPlugin -> pluginInitialize");
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [self parseConfig];
        
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleApplicationWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil];
    });
}

- (void)dealloc {
    NSLog(@"AdPlugin -> dealloc");
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)parseConfig {
        
    UIWindow *window = ((AppDelegate *)[self appDelegate]).window;
    CDVViewController *vc = (id)window.rootViewController;
    if ([vc isKindOfClass:[CDVViewController class]]) {
        NSString *path = [vc performSelector:@selector(configFilePath)];
        NSURL* url = [NSURL fileURLWithPath:path];

        self.configParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
        if (self.configParser == nil) {
            NSLog(@"Failed to initialize XML parser.");
            return;
        }
        
        CDVConfigParser* delegate = [[CDVConfigParser alloc] init];
        [self.configParser setDelegate:delegate];
        [self.configParser parse];
        
        self.appId = delegate.settings[@"adappid"];
        self.splashLogo = delegate.settings[@"adsplashlogo"];
        [ADH5Tool setDebug:[delegate.settings[@"adaddebug"] boolValue]];

        // 初始化广告SDK
        [self setupADSDK];
        // 显示开屏
        [self showSplashAdFromLaunch:YES];
    }
}

#pragma mark - Getter and Setter

- (NSMutableDictionary *)bannerCallbackDict {
    if (!_bannerCallbackDict) {
        _bannerCallbackDict = [NSMutableDictionary dictionary];
    }
    return _bannerCallbackDict;
}

- (NSMutableDictionary *)bannerViewDict {
    if (!_bannerViewDict) {
        _bannerViewDict = [NSMutableDictionary dictionary];
    }
    return _bannerViewDict;
}

#pragma mark - init

- (void)setUserId:(CDVInvokedUrlCommand *)method {
    NSString *uid = method.arguments[0];
    if ([uid isKindOfClass:[NSString class]]) {
        MobADConfigModel *config = [MobADSDKApi getConfig];
        config.userId = uid;
        [ADH5Tool log:@"setUserId:%@", uid];
    } else {
        MobADConfigModel *config = [MobADSDKApi getConfig];
        config.userId = nil;
        [ADH5Tool log:@"setUserId:nil"];
    }
}

#pragma mark - outer methods

- (void)showRewardVideoAd:(CDVInvokedUrlCommand *)method {
    
    self.rvCallback = method.callbackId;
    
    NSMutableDictionary *info = [NSMutableDictionary dictionary];
    [info setObject:method.arguments[0] forKey:@"unitId"];
    
    [self _showRewardVideoAd:info];
}

- (void)showBannerAd:(CDVInvokedUrlCommand *)method {
    NSMutableDictionary *info = [NSMutableDictionary dictionary];
    
    NSString *callback = method.callbackId;
    [info setObject:method.arguments[0] forKey:@"unitId"];
    [info setObject:method.arguments[1] forKey:@"layout"];
    [info setObject:method.arguments[2] forKey:@"margins"];

    [self _showBannerAd:info callback:callback];
}

- (void)destroyBannerAd:(CDVInvokedUrlCommand *)method {
    [self _destroyBannerAd:@{@"unitId":method.arguments[0]}];
}

- (void)showInterstitialAd:(CDVInvokedUrlCommand *)method {
    NSMutableDictionary *info = [NSMutableDictionary dictionary];
    
    self.interCallback = method.callbackId;
    [info setObject:method.arguments[0] forKey:@"unitId"];
    
    [self _showInterstitialAd:info];
}

#pragma mark - inner methods

- (void)_showRewardVideoAd:(NSDictionary *)info {
    
    if (!_rewardVideo) {
        _rewardVideo = [MobADSDKApi rewardVideoAdManager];
    }
    
    NSString *group = info[@"unitId"];
    if ([ADH5Tool isInvalidString:group]) {
        group = @"rv1";
    }
    NSInteger timeout = [info[@"timeout"] integerValue];
    if (timeout <= 0) {
        timeout = 10;
    }
    [_rewardVideo loadRewardVideoWithViewController:[ADH5Tool findCurrentShowingViewController] delegate:self timeout:timeout group:group];
}

- (void)_showBannerAd:(NSDictionary *)info callback:(NSString *)callback {
    [ADH5Tool log:@"showBannerAd:%@", info];

    if (!_bannerAd) {
        _bannerAd = [MobADSDKApi bannerAdManager];
    }
    
    NSString *group = info[@"unitId"];
    if ([ADH5Tool isInvalidString:group]) {
        group = @"b1";
    }
    
    if (self.bannerCallbackDict[group]) {
        
    } else {
        if (callback) {
            [self.bannerCallbackDict setObject:callback forKey:group];
        }
    }
    
    NSInteger interval = [info[@"interval"] integerValue];
//    if (interval < 30) {
//        interval = 30;
//    }
    
    CGFloat ratio = [info[@"ratio"] floatValue];
    if (ratio <= 0) {
        ratio = 6.4;
    }
    
    NSArray *margins = info[@"margins"];
    CGFloat left = [margins[0] floatValue];
    CGFloat top = [margins[1] floatValue];
    CGFloat right = [margins[2] floatValue];
    CGFloat bottom = [margins[3] floatValue];
    NSString *layout = info[@"layout"];
    
    CGSize screenSize = [UIScreen mainScreen].bounds.size;
    CGFloat statusBarHeight = [ADH5Tool statusBarHeight];
    
    CGFloat width, height;
    width = screenSize.width - left - right;
    height = width / ratio;
    
    CGRect frame;
    if ([layout isEqualToString:@"top"]) {
        top += statusBarHeight;
        frame = CGRectMake(left, top, width, height);
    } else {
        frame = CGRectMake(left, screenSize.height - bottom - height, width, height);
    }
    
    [_bannerAd loadBannerAdWithFrame:frame viewController:[ADH5Tool findCurrentShowingViewController] delegate:self interval:interval group:group];
}

- (void)_destroyBannerAd:(NSDictionary *)info {
    [ADH5Tool log:@"destroyBannerAd:%@", info];
    
    NSString *group = info[@"unitId"];
    if ([ADH5Tool isInvalidString:group]) {
        group = @"b1";
    }
    
    UIView *adView = self.bannerViewDict[group];
    if (adView) {
        [_bannerAd removeBannerAd:adView];
        if (group) {
            [self.bannerViewDict removeObjectForKey:group];
        }
        [ADH5Tool log:@"destroyBannerAd:1"];
        
    } else {
        [ADH5Tool log:@"destroyBannerAd:0"];
    }
}

- (void)_showInterstitialAd:(NSDictionary *)info {
    
    NSString *group = info[@"unitId"];
    if ([ADH5Tool isInvalidString:group]) {
        group = @"i1";
    }
    [MobADSDKApi showInterstitialAdWithViewController:[ADH5Tool findCurrentShowingViewController] delegate:self group:group];
    
}

#pragma mark - AdDelegate
- (void)ad_rewardVideoCallbackWithEvent:(MADRewardVideoCallbackEvent)event error:(NSError *)error andInfo:(NSDictionary *)info {
    BOOL keep = YES;
    if (event == MADRewardVideoCallbackEventAdLoadError || event == MADRewardVideoCallbackEventAdDidClose) {
        keep = NO;
    }
    
    if (self.rvCallback) {
        NSMutableDictionary *result = [NSMutableDictionary dictionaryWithDictionary:info];
        [result setObject:[[self class] rewardVideo_eventStringWithEvent:event] forKey:@"event"];
        if (error) {
            NSString *msg = error.userInfo[NSLocalizedDescriptionKey]?: @"";
            [result setObject:@(error.code) forKey:@"code"];
            [result setObject:msg forKey:@"msg"];
        }
        
        CDVPluginResult *r = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:result];
        r.keepCallback = @(keep);
        [self.commandDelegate sendPluginResult:r callbackId:self.rvCallback];
    }
}

- (void)ad_interstitialAdCallbackWithEvent:(MADInterstitialAdCallbackEvent)event error:(NSError *)error andInfo:(NSDictionary *)info {
    BOOL keep = YES;
    if (event == MADInterstitialAdCallbackEventAdLoadError) {
        keep = NO;
    }
    
    if (self.interCallback) {
        NSMutableDictionary *result = [NSMutableDictionary dictionaryWithDictionary:info];
        
        [result setObject:[[self class] intersticial_eventStringWithEvent:event] forKey:@"event"];
        if (error) {
            NSString *msg = error.userInfo[NSLocalizedDescriptionKey]?: @"";
            [result setObject:@(error.code) forKey:@"code"];
            [result setObject:msg forKey:@"msg"];
        }
        
        CDVPluginResult *r = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:result];
        r.keepCallback = @(keep);
        [self.commandDelegate sendPluginResult:r callbackId:self.interCallback];
    }
}

- (void)ad_bannerAdView:(UIView<MADBannerAdViewProtocol> *)adView callbackWithEvent:(MADBannerAdCallbackEvent)event error:(NSError *)error andInfo:(NSDictionary *)info {
    NSString *group = adView.group;
    
    BOOL keep = YES;
    if (event == MADBannerAdCallbackEventAdLoadSuccess) {
        if (!adView.superview) {
            UIViewController *top = [ADH5Tool findCurrentShowingViewController];
            [top.view addSubview:adView];
            if (group) {
                [self.bannerViewDict setObject:adView forKey:group];
            }
        }
    } else if (event == MADBannerAdCallbackEventAdDidClose) {
        [_bannerAd removeBannerAd:adView];
        if (group) {
            [self.bannerViewDict removeObjectForKey:group];
        }
    }
    
    
    NSString *callback = self.bannerCallbackDict[group];
    if (callback) {
        NSMutableDictionary *result = [NSMutableDictionary dictionaryWithDictionary:info];
        [result setObject:[[self class] intersticial_eventStringWithEvent:event] forKey:@"event"];
        if (error) {
            NSString *msg = error.userInfo[NSLocalizedDescriptionKey]?: @"";
            [result setObject:@(error.code) forKey:@"code"];
            [result setObject:msg forKey:@"msg"];
        }
        
        CDVPluginResult *r = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:result];
        r.keepCallback = @(keep);
        [self.commandDelegate sendPluginResult:r callbackId:callback];
    }
    
}

#pragma mark - EventMapper

+ (NSString *)splash_eventStringWithEvent:(NSInteger)event {
    switch (event) {
        case MADSplashAdCallbackEventAdLoadSuccess:
            //return @"onAdLoad";
            return nil;
            break;
        case MADSplashAdCallbackEventAdWillVisible:
            //return @"onAdShow";
            return nil;
            break;
        case MADSplashAdCallbackEventAdDidClick:
            //return @"onAdClick";
            return nil;
            break;
        case MADSplashAdCallbackEventAdDidClose:
            return @"onAdDismiss";
            break;
        default:
            return @"onError";
            break;
    }
}

+ (NSString *)rewardVideo_eventStringWithEvent:(NSInteger)event {
    switch (event) {
        case MADRewardVideoCallbackEventAdLoadSuccess:
            return @"onAdLoad";
            break;
        case MADRewardVideoCallbackEventAdDidLoadVideo:
            return @"onVideoCached";
            break;
        case MADRewardVideoCallbackEventAdWillVisible:
            return @"onAdShow";
            break;
        case MADRewardVideoCallbackEventAdDidClick:
            return @"onAdClick";
            break;
        case MADRewardVideoCallbackEventAdRewardSuccess:
            return @"onReward";
            break;
        case MADRewardVideoCallbackEventAdPlayFinish:
            return @"onVideoComplete";
            break;
        case MADRewardVideoCallbackEventAdDidClose:
            return @"onAdClose";
            break;
        default:
            return @"onError";
            break;
    }
}

+ (NSString *)intersticial_eventStringWithEvent:(NSInteger)event {
    switch (event) {
        case MADInterstitialAdCallbackEventAdLoadSuccess:
            return @"onAdLoad";
            break;
        case MADInterstitialAdCallbackEventAdWillVisible:
            return @"onAdShow";
            break;
        case MADInterstitialAdCallbackEventAdDidClick:
            return @"onAdClick";
            break;
        case MADInterstitialAdCallbackEventAdDidClose:
            return @"onAdClose";
            break;
        default:
            return @"onError";
            break;
    }
}

@end
