#import "PluggerReactNativeJSI.h"
#import <React/RCTBridge+Private.h>
#import <React/RCTUtils.h>
#import <jsi/jsi.h>
#import "JSIUtils.h"
#import "plugger_react_native-Swift.h"


using namespace facebook::jsi;
using namespace std;


@implementation PluggerReactNativeJSI

@synthesize bridge = _bridge;
@synthesize methodQueue = _methodQueue;

RCT_EXPORT_MODULE(PluggerReactNativeJSI)

+ (BOOL)requiresMainQueueSetup {
    return YES;
}


static Value setLocation(Runtime &runtime, const Value &thisValue, const Value *arguments, size_t count) {
    NSString *latitude = pluggerUtils::convertJSIStringToNSString(runtime, arguments[0].getString(runtime));
    NSString *longitude = pluggerUtils::convertJSIStringToNSString(runtime, arguments[1].getString(runtime));
    [[PluggerReactNative shared] setLocationSyncWithLatitude:latitude longitude:longitude];
    return Value();
}


static Value setUser(Runtime &runtime, const Value &thisValue, const Value *arguments, size_t count) {
    NSString *user = pluggerUtils::convertJSIStringToNSString(runtime, arguments[0].getString(runtime));
    [[PluggerReactNative shared] setUserSyncWithUserId:user];
    return Value();
}

static Value setGuest(Runtime &runtime, const Value &thisValue, const Value *arguments, size_t count) {
    NSString *user = pluggerUtils::convertJSIStringToNSString(runtime, arguments[0].getString(runtime));
    [[PluggerReactNative shared] setGuestSyncWithGuestId:user];
    return Value();
}

static Value initializePluggerSync(Runtime &runtime, const Value &thisValue, const Value *arguments, size_t count) {
    NSDictionary *config = pluggerUtils::convertJSIObjectToNSDictionary(runtime, arguments[0].getObject(runtime));
    BOOL state = [[PluggerReactNative shared] initializePluggerSyncWithConfig:config];
    auto jsiValue = pluggerUtils::convertObjCObjectToJSIValue(runtime, @(state));
    return jsiValue;
}

static Value isPluggerInitialized(Runtime &runtime, const Value &thisValue, const Value *arguments, size_t count) {
    BOOL state = [[PluggerReactNative shared] isPluggerInitializedSync];
    auto jsiValue = pluggerUtils::convertObjCObjectToJSIValue(runtime, @(state));
    return jsiValue;
}

static void install(Runtime &jsiRuntime) {
    Object module = Object(jsiRuntime);
    
    pluggerUtils::registerCxxFunction(jsiRuntime,module, "setUser", 1, setUser);
    pluggerUtils::registerCxxFunction(jsiRuntime,module, "setGuest", 1, setGuest);
    pluggerUtils::registerCxxFunction(jsiRuntime,module, "setLocation", 2, setLocation);
    pluggerUtils::registerCxxFunction(jsiRuntime,module, "isPluggerInitialized", 0, isPluggerInitialized);
    pluggerUtils::registerCxxFunction(jsiRuntime,module, "initializePluggerInSync", 1, initializePluggerSync);
    
    jsiRuntime.global().setProperty(jsiRuntime, "PluggerJSIModule", std::move(module));

}

RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(install) {
    RCTBridge* bridge = [RCTBridge currentBridge];
    RCTCxxBridge* cxxBridge = (RCTCxxBridge*)bridge;
    if (cxxBridge == nil) {
        return @false;
    }
    auto jsiRuntime = (facebook::jsi::Runtime*) cxxBridge.runtime;
    if (jsiRuntime == nil) {
        return @false;
    }
    install(*(facebook::jsi::Runtime *)jsiRuntime);
    return @true;
}

@end
