//
//  RangersAppLogPicker.m
//  react-native-rangers-applog-reactnative-plugin
//
//  Created by bytedance on 2022/11/21.
//

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

#import <Foundation/Foundation.h>
#import "RangersAppLogEmitter.h"
#import "RangersAppLogPicker.h"

static NSString const *kBDEventID = @"eventid";
static NSString const *kBDX       = @"x";
static NSString const *kBDY       = @"y";
static NSString const *kBDWidth   = @"width";
static NSString const *kBDHeight  = @"height";

#pragma RangersAppLogPickerEvent

@interface RangersAppLogPickerEvent : NSObject

@property (nonatomic, strong) NSString *eventID;
@property (nonatomic, strong) NSNumber *rootTag;
@property (nonatomic, copy) void(^callback)(NSDictionary *info);
@property (nonatomic, assign) NSTimeInterval timeoutms;
@property (nonatomic, assign) NSTimeInterval startTime;

@end

#pragma RangersAppLogPickerEvent

@interface RangersAppLogPicker()

@property (atomic, strong) NSMapTable<NSString *, RangersAppLogPickerEvent *> *listenerMap;
@property (nonatomic, assign) NSInteger callCount;

@end

@implementation RangersAppLogPickerEvent

@end

@implementation RangersAppLogPicker

+ (instancetype)shared {
    static RangersAppLogPicker *sharedInstance = nil;
    static dispatch_once_t onceToken;
    
    dispatch_once(&onceToken, ^{
        sharedInstance = [self new];
    });
    
    return sharedInstance;
}

- (instancetype)init{
    self = [super init];
    if (self) {
        self.listenerMap = [NSMapTable strongToStrongObjectsMapTable];
        self.callCount = 0;
    }
    return self;
}

- (void)pageInfoFromJS:(RCTRootView *) rootView success:(void(^)(NSDictionary *info)) successBlock failed:(void(^)(NSString *message)) failedBlock timeout:(NSTimeInterval) timestamp {
    if (!rootView) {
        if (failedBlock) {
            failedBlock(@"failed: rootView should not be empty!");
        }
        return;
    }
    
    NSString *eventID = [NSString stringWithFormat:@"%@_%ld", rootView.reactTag, self.callCount++];
    RangersAppLogPickerEvent *event = [RangersAppLogPickerEvent new];
    event.eventID = eventID;
    event.rootTag = rootView.reactTag;
    event.callback = successBlock;
    event.timeoutms = timestamp;
    event.startTime = [[NSDate date] timeIntervalSince1970] * 1000;
    [self.listenerMap setObject:event forKey:eventID];
    
    __weak RangersAppLogPicker *__self = self;
    __block NSString *__eventID = eventID;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, timestamp * NSEC_PER_MSEC), dispatch_get_main_queue(), ^{
        if (__self && __eventID && [__self.listenerMap objectForKey:__eventID] && failedBlock) {
            failedBlock(@"failed: timeout!");
        }
    });
    
    NSDictionary *params = @{
        kBDEventID: eventID,
        kBDX: @(rootView.bounds.origin.x),
        kBDY: @(rootView.bounds.origin.y),
        kBDWidth: @(rootView.bounds.size.width),
        kBDHeight: @(rootView.bounds.size.height),
    };
    [RangersAppLogEmitter sendPagePickerEventByRootView:rootView withParams:params];
}

+ (void)updatePickerInfo:(NSString *)eventID pageInfo:(NSDictionary *)info {
    if (!eventID) {
        return;
    }
    
    RangersAppLogPicker *instance = [RangersAppLogPicker shared];
    RangersAppLogPickerEvent *event = [instance.listenerMap objectForKey:eventID];
    if (!event) {
        return;
    }
    
    NSTimeInterval nowTime = [[NSDate date] timeIntervalSince1970] * 1000;
    if (nowTime - event.startTime > event.timeoutms) {
        return;
    }
    
    if (!event.callback) {
        return;
    }
    
    if (info == nil) {
        return;
    }
    
    event.callback(info);
    [instance.listenerMap removeObjectForKey:eventID];
}

@end
