//
//  DynatraceRNBridge.m
//

#import "DynatraceRNBridge.h"
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>

@implementation DynatraceRNBridge

NSMutableDictionary *actionDict;

NSString *const PlatformAndroid = @"android";
NSString *const PlatformiOS = @"ios";
NSString *const DataCollectionOff = @"OFF";
NSString *const DataCollectionUser = @"USER_BEHAVIOR";
NSString *const DataCollectionPerformance = @"PERFORMANCE";

RCT_EXPORT_MODULE(DynatraceBridge);

- (id) init
{
  self = [super init];
  if (self) {
    actionDict = [[NSMutableDictionary alloc] init];
  }
  return self;
}

- (NSDictionary *)constantsToExport
{
    return @{ @"PLATFORM_ANDROID" : PlatformAndroid,
              @"PLATFORM_IOS" : PlatformiOS,
              @"DATA_COLLECTION_OFF" : DataCollectionOff,
              @"DATA_COLLECTION_USER" : DataCollectionUser,
              @"DATA_COLLECTION_PERFORMANCE" : DataCollectionPerformance };
}

RCT_EXPORT_METHOD(enterAction:(NSString *)name key:(nonnull NSNumber *)key platform: (NSString *) platform)
{
  if ([self shouldWorkOnIosWithPlatform: platform])
  {
    [self newAction:name key:key parentAction:nil];
  }
}

RCT_EXPORT_METHOD(enterActionWithParent:(NSString *)name key:(nonnull NSNumber *)key parentKey:(nonnull NSNumber *)parentKey platform: (NSString *) platform)
{
    if ([self shouldWorkOnIosWithPlatform: platform])
    {
        [self newAction:name key:key parentAction:[self getAction:parentKey]];
    }
}

RCT_EXPORT_METHOD(leaveAction:(nonnull NSNumber *)key platform: (NSString *) platform)
{
    if ([self shouldWorkOnIosWithPlatform: platform])
    {
        DTXAction *action = [self getAction:key];
        if (action == nil) return;
        [actionDict removeObjectForKey:key];
    }
}

RCT_EXPORT_METHOD(endVisit: (NSString *) platform)
{
    if ([self shouldWorkOnIosWithPlatform: platform])
    {
        [Dynatrace endVisit];
    }
}

RCT_EXPORT_METHOD(reportErrorWithoutStacktrace:(NSString *)errorName errorCode:(nonnull NSNumber *)errorCode platform: (NSString *) platform)
{
    if ([self shouldWorkOnIosWithPlatform: platform])
    {
        DTXAction *action = [DTXAction enterActionWithName:@"Error"];
        [action reportErrorWithName:errorName errorValue:[errorCode intValue]];
        [action leaveAction];
    }
}

RCT_EXPORT_METHOD(reportError:(NSString *)errorName errorValue:(NSString *)errorValue errorReason:(NSString *)errorReason stacktrace:(NSString *)stacktrace platform: (NSString *) platform)
{
    if ([self shouldWorkOnIosWithPlatform: platform])
    {
        [DTXAction reportExternalErrorForPlatformType:DTXActionPlatformJavaScript errorName:errorName errorValue:errorValue reason:errorReason stacktrace:stacktrace];
    }
}

RCT_EXPORT_METHOD(reportCrash:(NSString *)errorName errorReason:(NSString *)errorReason stacktrace:(NSString *)stacktrace platform: (NSString *) platform)
{
    if ([self shouldWorkOnIosWithPlatform: platform])
    {
        [DTXAction reportExternalCrashForPlatformType:DTXActionPlatformJavaScript crashName:errorName reason:errorReason stacktrace:stacktrace];
        [Dynatrace endVisitWithEndEvent:YES];
    }
}

RCT_EXPORT_METHOD(reportErrorInAction:(nonnull NSNumber *)key errorName:(NSString *)errorName errorCode:(nonnull NSNumber *)errorCode platform: (NSString *) platform)
{
    if ([self shouldWorkOnIosWithPlatform: platform])
    {
        DTXAction *action = [self getAction:key];
        if (action == nil)
            return;
        [action reportErrorWithName:errorName errorValue:[errorCode intValue]];
    }
}

RCT_EXPORT_METHOD(reportStringValueInAction:(nonnull NSNumber *)actionKey withName:(NSString *)name value: (NSString *)value platform: (NSString *) platform)
{
  if ([self shouldWorkOnIosWithPlatform: platform])
  {
    DTXAction *action = [self getAction:actionKey];
    if (action == nil) return;
    [action reportValueWithName:name stringValue:value];
  }
}

RCT_EXPORT_METHOD(reportIntValueInAction:(nonnull NSNumber *)actionKey withName:(NSString *)name value: (nonnull NSNumber *)value platform: (NSString *) platform)
{
  if ([self shouldWorkOnIosWithPlatform: platform])
  {
    DTXAction *action = [self getAction:actionKey];
    if (action == nil) return;
    [action reportValueWithName:name intValue:value.intValue];
  }
}

RCT_EXPORT_METHOD(reportDoubleValueInAction:(nonnull NSNumber *)actionKey withName:(NSString *)name value: (nonnull NSNumber *)value platform: (NSString *) platform)
{
  if ([self shouldWorkOnIosWithPlatform: platform])
  {
    DTXAction *action = [self getAction:actionKey];
    if (action == nil) return;
    [action reportValueWithName:name doubleValue:value.doubleValue];
  }
}

RCT_REMAP_METHOD(getRequestTag, getRequestTagWithResolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
  resolve([Dynatrace getRequestTagValueForURL:nil]);
}

RCT_EXPORT_METHOD(identifyUser:(NSString *)user platform: (NSString *) platform)
{
    if ([self shouldWorkOnIosWithPlatform: platform])
    {
        [Dynatrace identifyUser:user];
    }
}

RCT_EXPORT_METHOD(reportEventInAction:(nonnull NSNumber *)actionKey withName: (NSString *)name platform: (NSString *) platform)
{
    if ([self shouldWorkOnIosWithPlatform: platform])
    {
        DTXAction *action = [self getAction:actionKey];
        if (action == nil) return;
        [action reportEventWithName: name];
    }
}

RCT_EXPORT_METHOD(setGPSLocation:(double)latitude andLongitude: (double)longitude platform: (NSString *) platform)
{
    if ([self shouldWorkOnIosWithPlatform: platform])
    {
        CLLocation *location = [[CLLocation alloc] initWithLatitude:latitude longitude:longitude];
        [Dynatrace setGpsLocation:location];
    }
}

RCT_EXPORT_METHOD(flushEvents:(NSString *) platform)
{
    if ([self shouldWorkOnIosWithPlatform: platform])
    {
        [Dynatrace flushEvents];
    }
}

RCT_EXPORT_METHOD(isCrashReportingOptedIn:(NSString *) platform findEventsWithResolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
    if ([self shouldWorkOnIosWithPlatform: platform])
    {
        if([Dynatrace crashReportingOptedIn]){
            resolve(@"true");
        }else{
            resolve(@"false");
        }
    }
}

RCT_EXPORT_METHOD(setCrashReportingOptedIn:(BOOL) crashReportingOptedIn platform: (NSString *) platform)
{
    if ([self shouldWorkOnIosWithPlatform: platform])
    {
        [Dynatrace setCrashReportingOptedIn:crashReportingOptedIn];
    }
}

RCT_EXPORT_METHOD(getDataCollectionLevel:(NSString *) platform findEventsWithResolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
    if ([self shouldWorkOnIosWithPlatform: platform])
    {
        int i = [Dynatrace dataCollectionLevel];
        
        if(i == DTX_DataCollectionUserBehavior){
            resolve(DataCollectionUser);
        }else if(i == DTX_DataCollectionPerformance){
            resolve(DataCollectionPerformance);
        }else{
            resolve(DataCollectionOff);
        }
    }
}

RCT_EXPORT_METHOD(setDataCollectionLevel:(nonnull NSString *) dataCollectionLevel platform: (NSString *) platform)
{
    if ([self shouldWorkOnIosWithPlatform: platform])
    {
        int dataCollectionLevelEnum;
        
        if([dataCollectionLevel isEqualToString: DataCollectionPerformance]){
            dataCollectionLevelEnum = DTX_DataCollectionPerformance;
        }else if([dataCollectionLevel isEqualToString: DataCollectionUser]){
            dataCollectionLevelEnum = DTX_DataCollectionUserBehavior;
        }else{
            dataCollectionLevelEnum = DTX_DataCollectionOff;
        }
        
        [Dynatrace setDataCollectionLevel:dataCollectionLevelEnum completion:^(BOOL successful) {
            // I am not sure
        }];
    }
}

- (void) newAction:(NSString *)name key:(nonnull NSNumber *)key parentAction:(DTXAction *)parentAction
{
    DTXAction *action = [DTXAction integrateActionWithName:name];
    
    if (action)
    {
        [actionDict setObject:action forKey:key];
    }
}

- (DTXAction *) getAction:(nonnull NSNumber *)key
{
  return [actionDict objectForKey:key];
}


+ (BOOL)requiresMainQueueSetup
{
  return YES;
}

- (BOOL) shouldWorkOnIosWithPlatform: (NSString *) platform
{
    return platform == nil || [platform isEqualToString:PlatformiOS] || [platform isEqualToString:@""];
}

@end
