//
//  RangersAppLogEmitter.m
//  react-native-rangers-applog-reactnative-plugin
//
//  Created by bytedance on 2022/6/24.
//

#if __has_include(<React/RCTLog.h>)
#import <React/RCTLog.h>
#else
#import "RCTLog.h"
#endif

#if __has_include(<React/UIView+React.h>)
#import <React/UIView+React.h>
#else
#import "UIView+React.h"
#endif

#import "RangersAppLogModule.h"
#import "RangersAppLogModule+AutoTrack.h"
#import "RangersAppLogEmitter.h"

static NSString * const kBDPageShowEventName = @"onPageShow";
static NSString * const kBDPageHideventName = @"onPageHide";
static NSString * const kBDPagePickerEventName = @"onPagePicker";
static NSString * const kBDPageParamsRootTag = @"rootTag";
static NSString * const kBDPageParamsModuleName = @"moduleName";

static NSMutableArray *delayEvents;
static NSString * const kBDDelayEventBridge = @"bridge";
static NSString * const kBDDelayEventName   = @"eventName";
static NSString * const kBDDelayEventBody   = @"body";



@interface RangersAppLogEmitter()

@property (nonatomic, assign) bool hasConnected;

@end

@implementation RangersAppLogEmitter

RCT_EXPORT_MODULE(RangersAppLogEmitter)

# pragma overrides

- (NSArray<NSString *> *)supportedEvents {
    return @[kBDPageShowEventName, kBDPageHideventName, kBDPagePickerEventName];
}



# pragma methods

RCT_EXPORT_METHOD(connect)
{
    if (!self.hasConnected) {
        [self sendDelayEvents];
    }
    self.hasConnected = YES;
}



#pragma instance functins

- (void)sendEvent:(NSString *) name body:(NSDictionary *)body {
//    NSLog(@">>>> RangersAppLogEmitter sendEvent: %@", name);
    RangersAppLogModule *module = [self.bridge moduleForClass:[RangersAppLogModule class]];
    if (module == nil) {
        return;
    }
    
//    NSLog(@">>>> RangersAppLogEmitter sendEventWithName: %@", name);
    [self sendEventWithName:name body:body];
}

- (void)sendDelayEvents {
    if (delayEvents == nil) {
        return;
    }
    
//    NSLog(@">>> delayEvents size: %lu", delayEvents.count);
    NSMutableIndexSet *indexSet = [NSMutableIndexSet indexSet];
    for (long index = 0; index < delayEvents.count; index++) {
        NSMutableDictionary *eventInfo = [delayEvents objectAtIndex:index];
        if (eventInfo == nil) {
            continue;
        }
        RCTBridge *bridge = [eventInfo objectForKey:kBDDelayEventBridge];
        RangersAppLogEmitter *emitter = [bridge moduleForClass:[RangersAppLogEmitter class]];
        if (emitter == self) {
            NSString *eventName = [eventInfo objectForKey:kBDDelayEventName];
            NSDictionary *body = [eventInfo objectForKey:kBDDelayEventBody];
            [self sendEvent:eventName body:body];
            [indexSet addIndex:index];
//            NSLog(@">>> sendDelayEvent: %@, %@, %@", bridge, eventName, body);
        }
    }
    [delayEvents removeObjectsAtIndexes:indexSet];
//    NSLog(@">>> delayEvents size: %lu", delayEvents.count);
}


#pragma public functions

+ (void)pushDelayEvent:(RCTBridge *) bridge eventName:(NSString *) eventName body:(NSDictionary *) body {
//    NSLog(@">>> pushDelayEvent: %@, %@, %@", bridge, eventName, body);
    if (delayEvents == nil) {
        delayEvents = [[NSMutableArray alloc] initWithCapacity:10];
    }
    NSMutableDictionary *eventInfo = [NSMutableDictionary new];
    [eventInfo setObject:bridge forKey:kBDDelayEventBridge];
    [eventInfo setObject:eventName forKey:kBDDelayEventName];
    [eventInfo setObject:body forKey:kBDDelayEventBody];
    [delayEvents addObject:eventInfo];
}

+ (void)sendEvent:(NSString *) name body:(NSDictionary *)body widthBridge:(RCTBridge *) bridge {
    if (bridge == nil) {
        RCTLogInfo(@"bridge should not be empty, %s", __func__);
        return;
    }

    RangersAppLogEmitter *emitter = [bridge moduleForClass:[RangersAppLogEmitter class]];
    if (emitter != nil && emitter.hasConnected) {
        [emitter sendEvent:name body:body];
    } else {
        [RangersAppLogEmitter pushDelayEvent:bridge eventName:name body:body];
    }
}

+ (void)sendPageShowEvent:(NSDictionary *) params widthBridge:(RCTBridge *) bridge {
    [RangersAppLogEmitter sendEvent:kBDPageShowEventName body:params widthBridge:bridge];
}

+ (void)sendPageHideEvent:(NSDictionary *) params widthBridge:(RCTBridge *) bridge {
    [RangersAppLogEmitter sendEvent:kBDPageHideventName body:params widthBridge:bridge];
}

+ (void)sendPageShowEventByRootView:(RCTRootView *) rootView withParams:(nullable NSDictionary *) params {
    NSMutableDictionary *info = [[NSMutableDictionary alloc] init];
    [info setValue:rootView.reactTag forKey:kBDPageParamsRootTag];
    [info setValue:rootView.moduleName forKey:kBDPageParamsModuleName];
    if (params != nil) {
        [info addEntriesFromDictionary:params];
    }
    [RangersAppLogEmitter sendPageShowEvent:info widthBridge:rootView.bridge];
}

+ (void)sendPageHideEventByRootView:(RCTRootView *) rootView withParams:(nullable NSDictionary *) params {
    NSMutableDictionary *info = [[NSMutableDictionary alloc] init];
    [info setValue:rootView.reactTag forKey:kBDPageParamsRootTag];
    [info setValue:rootView.moduleName forKey:kBDPageParamsModuleName];
    if (params != nil) {
        [info addEntriesFromDictionary:params];
    }
    [RangersAppLogEmitter sendPageHideEvent:info widthBridge:rootView.bridge];
}

+ (void)sendPagePickerEventByRootView:(nonnull RCTRootView *) rootView withParams:(nullable NSDictionary *) params {
    NSMutableDictionary *info = [[NSMutableDictionary alloc] init];
    [info setValue:rootView.reactTag forKey:kBDPageParamsRootTag];
    [info setValue:rootView.moduleName forKey:kBDPageParamsModuleName];
    if (params != nil) {
        [info addEntriesFromDictionary:params];
    }
    [RangersAppLogEmitter sendEvent:kBDPagePickerEventName body:info widthBridge:rootView.bridge];
}

@end
