//
//  UnityFanCraftWrapper.mm
//
//  Created by Sunmeng on 2023/12/21.
//

#import "Yodo1UnityTool.h"
#import "Yodo1Tool+Commons.h"
#import "Yodo1Commons.h"
#import "FanCraftSDK.h"
#import "FanCraftDelegates.h"
#import "FanCraftPushNotificationCenter.h"

static NSString* kYodo1FanCraftGameObject;
static NSString* kYodo1FanCraftMethodName;

#pragma mark - UnityFanCraftWrapper

@interface UnityFanCraftWrapper : NSObject<FanCraftInitializationDelegate, FanCraftUpdateUserDelegate, FanCraftAddUserTagsDelegate, FanCraftInterstitialNotificationDelegate, FanCraftPushNotificationCenter>

+ (UnityFanCraftWrapper *)sharedInstance;

- (void)initWithAppKey:(NSString *)appKey
      gameUserSettings:(FanCraftGameUserSettings *)gameUserSettings
       privacySettings:(FanCraftPrivacySettings *)privacySettings
pushNotificationSettings:(FanCraftPushNotificationSettings*)pushNotificationSettings
      sdkConfiguration:(FanCraftConfiguration* _Nullable)configuration;

- (void)updateGameUser:(FanCraftGameUserInfo*)gameUser;

- (void)setTags:(NSArray*)tags;

- (void)showInterstitialNotification;
- (void)showInterstitialNotification:(NSString*)locationId;

- (void)registerForRemoteNotifications;

@end

@implementation UnityFanCraftWrapper

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

- (void)initWithAppKey:(NSString *)appKey
      gameUserSettings:(FanCraftGameUserSettings *)gameUserSettings
       privacySettings:(FanCraftPrivacySettings *)privacySettings
pushNotificationSettings:(FanCraftPushNotificationSettings*)pushNotificationSettings
      sdkConfiguration:(FanCraftConfiguration* _Nullable)configuration {
    
    [[FanCraftSDK sharedInstance] initWithAppKey:appKey gameUserSettings:gameUserSettings privacySettings:privacySettings pushNotificationSettings:pushNotificationSettings sdkConfiguration:configuration delegate:self];
}

- (void)updateGameUser:(FanCraftGameUserInfo*)gameUser {
    [[FanCraftSDK sharedInstance] updateGameUser:gameUser delegate:self];
}

- (void)setTags:(NSArray*)tags {
    [[FanCraftSDK sharedInstance] setTags:tags delegate:self];
}

- (void)showInterstitialNotification {
    [[FanCraftSDK sharedInstance] showInterstitialNotification:[Yodo1Commons getRootViewController] delegate:self];
}

- (void)showInterstitialNotification:(NSString*)locationId {
    [[FanCraftSDK sharedInstance] showInterstitialNotification:[Yodo1Commons getRootViewController] locationId:locationId delegate:self];
}

#pragma mark - FanCraftDelegate
/// 初始化事件
/// @param info 初始化成功后，获得的FanCraft's user
/// @param error Error
- (void)fancraftDidInitialized:(FanCraftInitSuccessInfo* _Nullable)info withError:(NSError* _Nullable)error {
    dispatch_async(dispatch_get_main_queue(), ^{
        if(kYodo1FanCraftGameObject && kYodo1FanCraftMethodName) {
            NSMutableDictionary* dict = [NSMutableDictionary dictionary];
            [dict setObject:@"OnInitEvent" forKey:@"event_name"];
            
            NSMutableDictionary* dataDict = [NSMutableDictionary dictionary];
            // error
            if (error) {
                NSMutableDictionary* errorDict = [NSMutableDictionary dictionary];
                [errorDict setObject:[NSNumber numberWithInt:(int)error.code] forKey:@"code"];
                [errorDict setObject:error.localizedDescription forKey:@"message"];
                [dataDict setObject:errorDict forKey:@"error"];
            }
            
            // init_success_info
            if (info) {
                [dataDict setObject:[info toDictionary] forKey:@"init_success_info"];
            }
            
            [dict setObject:dataDict forKey:@"event_data"];
            
            NSError* parseJSONError = nil;
            NSString* msg = [Yd1OpsTools stringWithJSONObject:dict error:&parseJSONError];
            if(!parseJSONError){
                UnitySendMessage([kYodo1FanCraftGameObject cStringUsingEncoding:NSUTF8StringEncoding],
                                 [kYodo1FanCraftMethodName cStringUsingEncoding:NSUTF8StringEncoding],
                                 [msg cStringUsingEncoding:NSUTF8StringEncoding]);
            }
        }
    });
}

#pragma mark - FanCraftUpdateUserDelegate
/// 用户识别/绑定事件
/// @param user 已识别/绑定的FanCraft用户
/// @param error Error
- (void)fancraftDidIdentifyUser:(FanCraftUserInfo* _Nullable)user withError:(NSError* _Nullable)error {
    dispatch_async(dispatch_get_main_queue(), ^{
        if(kYodo1FanCraftGameObject && kYodo1FanCraftMethodName) {
            NSMutableDictionary* dict = [NSMutableDictionary dictionary];
            [dict setObject:@"OnUpdateGameUser" forKey:@"event_name"];
            
            NSMutableDictionary* dataDict = [NSMutableDictionary dictionary];
            // error
            if (error) {
                NSMutableDictionary* errorDict = [NSMutableDictionary dictionary];
                [errorDict setObject:[NSNumber numberWithInt:(int)error.code] forKey:@"code"];
                [errorDict setObject:error.localizedDescription forKey:@"message"];
                [dataDict setObject:errorDict forKey:@"error"];
            }
            
            // user_info
            if (user) {
                [dataDict setObject:[user toDictionary] forKey:@"user_info"];
            }
            
            [dict setObject:dataDict forKey:@"event_data"];
            
            NSError* parseJSONError = nil;
            NSString* msg = [Yd1OpsTools stringWithJSONObject:dict error:&parseJSONError];
            if(!parseJSONError){
                UnitySendMessage([kYodo1FanCraftGameObject cStringUsingEncoding:NSUTF8StringEncoding],
                                 [kYodo1FanCraftMethodName cStringUsingEncoding:NSUTF8StringEncoding],
                                 [msg cStringUsingEncoding:NSUTF8StringEncoding]);
            }
        }
    });
}

#pragma mark - FanCraftAddUserTagsDelegate

- (void)fancraftDidAddUserTags:(BOOL)status
                     withError:(NSError* _Nullable)error {
    dispatch_async(dispatch_get_main_queue(), ^{
        if(kYodo1FanCraftGameObject && kYodo1FanCraftMethodName) {
            NSMutableDictionary* dict = [NSMutableDictionary dictionary];
            [dict setObject:@"OnAddUserTags" forKey:@"event_name"];
            
            NSMutableDictionary* dataDict = [NSMutableDictionary dictionary];
            // error
            if (error) {
                NSMutableDictionary* errorDict = [NSMutableDictionary dictionary];
                [errorDict setObject:[NSNumber numberWithInt:(int)error.code] forKey:@"code"];
                [errorDict setObject:error.localizedDescription forKey:@"message"];
                [dataDict setObject:errorDict forKey:@"error"];
            }
            
            [dataDict setObject:@(status) forKey:@"status"];
            [dict setObject:dataDict forKey:@"event_data"];
            
            NSError* parseJSONError = nil;
            NSString* msg = [Yd1OpsTools stringWithJSONObject:dict error:&parseJSONError];
            if(!parseJSONError){
                UnitySendMessage([kYodo1FanCraftGameObject cStringUsingEncoding:NSUTF8StringEncoding],
                                 [kYodo1FanCraftMethodName cStringUsingEncoding:NSUTF8StringEncoding],
                                 [msg cStringUsingEncoding:NSUTF8StringEncoding]);
            }
        }
    });
}

#pragma mark - FanCraftInterstitialNotificationDelegate

- (void)fancraftInterstitialNotification:(NSString* _Nullable)noticiationId
                                     error:(NSError* _Nullable)error
                                   handler:(FanCraftInterstialNotificationHandler* _Nullable)handler {
    dispatch_async(dispatch_get_main_queue(), ^{
        if(kYodo1FanCraftGameObject && kYodo1FanCraftMethodName) {
            NSMutableDictionary* dict = [NSMutableDictionary dictionary];
            [dict setObject:@"OnInterstitialNotificationEvent" forKey:@"event_name"];
            
            NSMutableDictionary* dataDict = [NSMutableDictionary dictionary];
            // notification_id
            if (noticiationId != nil && noticiationId.length > 0) {
                [dataDict setObject:noticiationId forKey:@"notification_id"];
            }
            // error
            if (error) {
                NSMutableDictionary* errorDict = [NSMutableDictionary dictionary];
                [errorDict setObject:[NSNumber numberWithInt:(int)error.code] forKey:@"code"];
                [errorDict setObject:error.localizedDescription forKey:@"message"];
                [dataDict setObject:errorDict forKey:@"error"];
            }
            
            // notification_handler
            if (handler) {
                [dataDict setObject:handler.toDictionary forKey:@"notification_handler"];
            }
            
            [dict setObject:dataDict forKey:@"event_data"];
            
            NSError* parseJSONError = nil;
            NSString* msg = [Yd1OpsTools stringWithJSONObject:dict error:&parseJSONError];
            if(!parseJSONError){
                UnitySendMessage([kYodo1FanCraftGameObject cStringUsingEncoding:NSUTF8StringEncoding],
                                 [kYodo1FanCraftMethodName cStringUsingEncoding:NSUTF8StringEncoding],
                                 [msg cStringUsingEncoding:NSUTF8StringEncoding]);
            }
        }
    });
}

#pragma mark - FanCraftPushNotificationCenter

- (void)registerForRemoteNotifications {
    [[FanCraftPushNotificationCenter sharedInstance] registerForRemoteNotifications:self];
}

#pragma mark - FanCraftPushNotificationCenter

- (void)fancraftDidRegisterForRemoteNotificationsWithDeviceToken:(NSString *)deviceToken {
    dispatch_async(dispatch_get_main_queue(), ^{
        if(kYodo1FanCraftGameObject && kYodo1FanCraftMethodName) {
            NSMutableDictionary* dict = [NSMutableDictionary dictionary];
            [dict setObject:@"OnRegisterForRemoteNotificationsDeviceToken" forKey:@"event_name"];
            
            NSMutableDictionary* dataDict = [NSMutableDictionary dictionary];
            // device_token
            if (deviceToken != nil && deviceToken.length > 0) {
                [dataDict setObject:deviceToken forKey:@"device_token"];
            }
            [dict setObject:dataDict forKey:@"event_data"];
            
            NSError* parseJSONError = nil;
            NSString* msg = [Yd1OpsTools stringWithJSONObject:dict error:&parseJSONError];
            if(!parseJSONError){
                UnitySendMessage([kYodo1FanCraftGameObject cStringUsingEncoding:NSUTF8StringEncoding],
                                 [kYodo1FanCraftMethodName cStringUsingEncoding:NSUTF8StringEncoding],
                                 [msg cStringUsingEncoding:NSUTF8StringEncoding]);
            }
        }
    });
}
- (void)fancraftDidFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
    dispatch_async(dispatch_get_main_queue(), ^{
        if(kYodo1FanCraftGameObject && kYodo1FanCraftMethodName) {
            NSMutableDictionary* dict = [NSMutableDictionary dictionary];
            [dict setObject:@"OnRegisterForRemoteNotificationsDeviceToken" forKey:@"event_name"];
            
            NSMutableDictionary* dataDict = [NSMutableDictionary dictionary];
            // error
            if (error) {
                NSMutableDictionary* errorDict = [NSMutableDictionary dictionary];
                [errorDict setObject:[NSNumber numberWithInt:(int)error.code] forKey:@"code"];
                [errorDict setObject:error.localizedDescription forKey:@"message"];
                [dataDict setObject:errorDict forKey:@"error"];
            }
            
            [dict setObject:dataDict forKey:@"event_data"];
            
            NSError* parseJSONError = nil;
            NSString* msg = [Yd1OpsTools stringWithJSONObject:dict error:&parseJSONError];
            if(!parseJSONError){
                UnitySendMessage([kYodo1FanCraftGameObject cStringUsingEncoding:NSUTF8StringEncoding],
                                 [kYodo1FanCraftMethodName cStringUsingEncoding:NSUTF8StringEncoding],
                                 [msg cStringUsingEncoding:NSUTF8StringEncoding]);
            }
        }
    });
}

@end

#ifdef __cplusplus
extern "C" {
#endif

void UnityFanCraft_Init(const char* c_appKey, const char* c_gameUserSettings, const char* c_privacySettings, const char* c_pushNotificationSettings, const char* c_configuration, const char* c_gameObjectName, const char* c_callbackMethodName)
{
    kYodo1FanCraftGameObject = ConvertCharToNSString(c_gameObjectName);
    kYodo1FanCraftMethodName = ConvertCharToNSString(c_callbackMethodName);
    
    NSString* appKey = ConvertCharToNSString(c_appKey);
    
    // GameUserSettings
    NSString* gameUserSettingsJson = ConvertCharToNSString(c_gameUserSettings);
    NSDictionary* gameUserSettingsDict = [Yodo1Commons JSONObjectWithString:gameUserSettingsJson error:nil];
    FanCraftGameUserSettings *gameUserSettings = [[FanCraftGameUserSettings alloc] initWithDictionary:gameUserSettingsDict];
    
    // PrivacySettings
    NSString* privacySettingsJson = ConvertCharToNSString(c_privacySettings);
    NSDictionary* privacySettingsDict = [Yodo1Commons JSONObjectWithString:privacySettingsJson error:nil];
    FanCraftPrivacySettings *privacySettings = [FanCraftPrivacySettings instance];
    [privacySettings initWithDictionary:privacySettingsDict];
    
    // PushNotificationSettings
    NSString* pushNotificationSettingsJson = ConvertCharToNSString(c_pushNotificationSettings);
    NSDictionary* pushNotificationSettingsDict = [Yodo1Commons JSONObjectWithString:pushNotificationSettingsJson error:nil];
    FanCraftPushNotificationSettings *pushNotificationSettings = [[FanCraftPushNotificationSettings alloc] initWithDictionary:pushNotificationSettingsDict];
    
    // Configuration
    NSString* configurationJson = ConvertCharToNSString(c_configuration);
    NSDictionary* configurationDict = [Yodo1Commons JSONObjectWithString:configurationJson error:nil];
    FanCraftConfiguration *configuration = [[FanCraftConfiguration alloc] initWithDictionary:configurationDict];
    
    [[UnityFanCraftWrapper sharedInstance] initWithAppKey:appKey gameUserSettings:gameUserSettings privacySettings:privacySettings pushNotificationSettings:pushNotificationSettings sdkConfiguration:configuration];
}

void UnityFanCraft_UpdateGameUser(const char* c_gameUserJsonString, const char* c_gameObjectName, const char* c_callbackMethodName)
{
    NSString* gameUserJson = ConvertCharToNSString(c_gameUserJsonString);
    NSDictionary* gameUserJsonDict = [Yodo1Commons JSONObjectWithString:gameUserJson error:nil];
    FanCraftGameUserInfo *gameUserInfo = [[FanCraftGameUserInfo alloc] initWithDictionary:gameUserJsonDict];
    
    [[UnityFanCraftWrapper sharedInstance] updateGameUser:gameUserInfo];
}

void UnityFanCraft_SetTags(const char* c_tagsJsonString, const char* c_gameObjectName, const char* c_callbackMethodName)
{
    NSString* tagsJson = ConvertCharToNSString(c_tagsJsonString);
    NSArray* tagsArray = [Yodo1Commons JSONObjectWithString:tagsJson error:nil];
        
    [[UnityFanCraftWrapper sharedInstance] setTags:tagsArray];
}

void UnityFanCraft_ShowInterstitialNotification(const char* c_gameObjectName, const char* c_callbackMethodName)
{
    kYodo1FanCraftGameObject = ConvertCharToNSString(c_gameObjectName);
    kYodo1FanCraftMethodName = ConvertCharToNSString(c_callbackMethodName);
    
    [[UnityFanCraftWrapper sharedInstance] showInterstitialNotification];
}

void UnityFanCraft_ShowInterstitialNotificationByLocation(const char* c_locationId, const char* c_gameObjectName, const char* c_callbackMethodName)
{
    NSString* locationId = ConvertCharToNSString(c_locationId);
    kYodo1FanCraftGameObject = ConvertCharToNSString(c_gameObjectName);
    kYodo1FanCraftMethodName = ConvertCharToNSString(c_callbackMethodName);
    
    [[UnityFanCraftWrapper sharedInstance] showInterstitialNotification:locationId];
}

void UnityFanCraft_RegisterForRemoteNotifications(const char* c_gameObjectName, const char* c_callbackMethodName)
{
    kYodo1FanCraftGameObject = ConvertCharToNSString(c_gameObjectName);
    kYodo1FanCraftMethodName = ConvertCharToNSString(c_callbackMethodName);
    
    [[UnityFanCraftWrapper sharedInstance] registerForRemoteNotifications];
}

#ifdef __cplusplus
}
#endif
